From 684975127f1d8f0a71c77dc7dde7c7a5686f9b2e Mon Sep 17 00:00:00 2001 From: Laubstein Date: Tue, 16 Aug 2016 11:58:56 -0300 Subject: [PATCH 1/4] Fixes #33 - Added support to xml prolog --- README.md | 11 ++++--- jxon.js | 92 ++++++++++++++++++++++++++++++++++++++++++++++++---- test/spec.js | 29 +++++++++++++---- 3 files changed, 116 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 31d60f1..c46e799 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ Implementation of Mozilla's [JXON](https://developer.mozilla.org/en-US/docs/JXON #### Example: ```js -{name: 'myportal'} +{name: 'myportal'} myportal {user: { @@ -56,7 +56,9 @@ trueIsEmpty: false, autoDate: false, ignorePrefixedNodes: false, parseValues: false, -parserErrorHandler: undefined +parserErrorHandler: undefined, +forceXmlProlog: false, +defaultXmlProlog: '' ``` ### .stringToJs(xmlString) @@ -73,7 +75,7 @@ parserErrorHandler: undefined - verbosity - Optional verbosity level of conversion, from 0 to 3. It is almost equivalent to our algorithms from #4 to #1 (default value is 1, which is equivalent to the algorithm #3). - freeze - Optional boolean expressing whether the created object must be freezed or not (default value is false). - nestedAttributes - Optional boolean expressing whether the the nodeAttributes must be nested into a child-object named keyAttributes or not (default value is false for verbosity levels from 0 to 2; true for verbosity level 3). - + Example: ```js var myObject = JXON.build(xmlDoc); @@ -84,7 +86,7 @@ var myObject = JXON.build(xmlDoc); - namespaceURI - Optional DOMString containing the namespace URI of the document to be created, or null if the document doesn't belong to one. - qualifiedNameStr - Optional DOMString containing the qualified name, that is an optional prefix and colon plus the local root element name, of the document to be created. - documentType - Optional DocumentType of the document to be created. It defaults to null. - + Example: ```js var myObject = JXON.unbuild(myObject); @@ -122,4 +124,5 @@ changes from version 1.x to 2.0 include: * (breaking) more usefull default settings (see above) * (breaking) stringify Dates to ISO format instead of GMT * improved xml namespace handling on node and browsers +* improved xml prolog handling * renamed main source file to `jxon.js` diff --git a/jxon.js b/jxon.js index b099249..e955621 100644 --- a/jxon.js +++ b/jxon.js @@ -20,7 +20,7 @@ * bugfixes and code cleanup by user @laubstein * https://github.com/tyrasd/jxon/pull/32 * - * adapted for nodejs and npm by @tyrasd (Martin Raifer ) + * adapted for nodejs and npm by @tyrasd (Martin Raifer ) */ (function(root, factory) { @@ -54,11 +54,16 @@ trueIsEmpty: false, autoDate: false, ignorePrefixedNodes: false, - parseValues: false + parseValues: false, + forceXmlProlog: false, + defaultXmlProlog: '' }; var aCache = []; var rIsNull = /^\s*$/; var rIsBool = /^(?:true|false)$/i; + var rXmlProlog = /^(<\?xml.*?\?>)/; + var rXmlPrologAttributes = /\b(version|encoding|standalone)="([^"]+?)"/g; + var oXmlProlog = {}; var DOMParser; return new (function() { @@ -76,6 +81,56 @@ } }; + /** + * Helper function: given a xml prolog (eg: ), + * returns a object (eg: { version: "1.0" }). + */ + function getPrologFromString(sXmlProlog) { + var matches = sXmlProlog.match(rXmlPrologAttributes); + var oReturn = {}; + for (var i = 0; i < matches.length; i++) { + var currentAttribute = matches[i].split('='); + oReturn[currentAttribute[0]] = currentAttribute[1].replace(/["]/g, ''); + } + + return oReturn; + }; + + /** + * Helper function: given an object representing a xml prolog (eg: { version: "1.0", encoding: "UTF-8", standalone: "true" }), + * returns a string (eg: ). + */ + function getPrologFromObject(oProlog) { + var ret = []; + for (var prop in oProlog) { + if (oProlog.hasOwnProperty(prop)) { + ret.push(prop + '="' + oProlog[prop] + '"'); + } + } + + return ret.length ? '' : ''; + }; + + /** + * Helper function: check for empty object + */ + function isEmptyObject(obj) { + for (var prop in obj) { + if (obj.hasOwnProperty(prop)) { + return false; + } + } + + return true && JSON.stringify(obj) === JSON.stringify({}); + }; + + /** + * Helper function: clone a object + */ + function cloneObject(obj) { + return JSON.parse(JSON.stringify(obj)); + }; + function parseText(sValue) { if (!opts.parseValues) { return sValue; @@ -253,7 +308,12 @@ if (isNodeJs) { oParentEl.setAttribute(sName.slice(1), vValue); } - // do nothing: special handling of xml namespaces is done via createElementNS() + // do nothing: special handling of xml namespaces is done via createElementNS() + } else if (sName === opts.attrPrefix + 'xmlProlog') { + // store xmlProlog + if (vValue) { + oXmlProlog = cloneObject(vValue); + } } else if (sName.charAt(0) === opts.attrPrefix) { oParentEl.setAttribute(sName.slice(1), vValue); } else if (vValue.constructor === Array) { @@ -289,7 +349,14 @@ } this.xmlToJs = this.build = function(oXMLParent, nVerbosity /* optional */ , bFreeze /* optional */ , bNesteAttributes /* optional */ ) { var _nVerb = arguments.length > 1 && typeof nVerbosity === 'number' ? nVerbosity & 3 : /* put here the default verbosity level: */ 1; - return createObjTree(oXMLParent, _nVerb, bFreeze || false, arguments.length > 3 ? bNesteAttributes : _nVerb === 3); + var oTree = createObjTree(oXMLParent, _nVerb, bFreeze || false, arguments.length > 3 ? bNesteAttributes : _nVerb === 3); + + if (!isEmptyObject(oXmlProlog)) { + oTree[opts.attrPrefix + 'xmlProlog'] = cloneObject(oXmlProlog); + oXmlProlog = {}; + } + + return oTree; }; this.jsToXml = this.unbuild = function(oObjTree, sNamespaceURI /* optional */ , sQualifiedName /* optional */ , oDocumentType /* optional */ ) { @@ -304,15 +371,28 @@ DOMParser = new xmlDom.DOMParser(); } + if (rXmlProlog.test(xmlStr)) { + oXmlProlog = getPrologFromString(xmlStr.match(rXmlProlog)[0]); + } + return DOMParser.parseFromString(xmlStr, 'application/xml'); }; this.xmlToString = function(xmlObj) { + var sReturn = ''; + if (typeof xmlObj.xml !== 'undefined') { - return xmlObj.xml; + sReturn = xmlObj.xml; } else { - return (new xmlDom.XMLSerializer()).serializeToString(xmlObj); + sReturn = (new xmlDom.XMLSerializer()).serializeToString(xmlObj); } + + // if the original string has a prolog we include them, else we check the forceXmlProlog option + if (!rXmlProlog.test(sReturn) && (!isEmptyObject(oXmlProlog) || opts.forceXmlProlog)) { + sReturn = (getPrologFromObject(oXmlProlog) || opts.defaultXmlProlog) + sReturn; + } + + return sReturn; }; this.stringToJs = function(str) { diff --git a/test/spec.js b/test/spec.js index 610dad5..7714859 100644 --- a/test/spec.js +++ b/test/spec.js @@ -7,19 +7,18 @@ var assert = require('chai').assert, $attr: 'value', _: 'root value' } - }; - +}; describe('JXON', function() { describe('.jsToXml > .xmlToJs', function() { - it('should return return identical object', function() { + it('should return identical object', function() { var xml = JXON.jsToXml(jsObj); var newJs = JXON.xmlToJs(xml); assert.deepEqual(jsObj, newJs); }); }); describe('.jsToString > .stringToJs', function() { - it('should return return identical object', function() { + it('should return identical object', function() { var str = JXON.jsToString(jsObj); var newJs = JXON.stringToJs(str); assert.deepEqual(jsObj, newJs); @@ -76,7 +75,7 @@ describe('JXON', function() { }); var strTwo = JXON.jsToString(JXON.stringToJs('first positionsecond position')); - + assert.equal(strOne, strTwo); }); @@ -123,7 +122,7 @@ describe('JXON', function() { var str = JXON.jsToString(obj); assert.equal(str, ''); }); - it('as property', function() { // addigional test from #26 + it('as property', function() { // additional test from #26 var strNull = JXON.jsToString({ 'TrainingCenterDatabase': { '$xmlns': '6', @@ -145,4 +144,22 @@ describe('JXON', function() { assert.equal(strNull, strEmptyObj); }); }); + describe('xml prolog', function() { + it('should be consistent', function() { + var originalString = '1'; + var xmlObject = JXON.stringToXml(originalString); + var jsonFromXml = JXON.xmlToJs(xmlObject); + var jsonFromString = JXON.stringToJs(originalString); + + assert.equal(originalString, JXON.jsToString(jsonFromXml)); + assert.equal(originalString, JXON.jsToString(jsonFromString)); + + // PhantomJS do not serialize the prolog, so we are forcing a default + JXON.config({ + forceXmlProlog: true, + defaultXmlProlog: '' + }); + assert.equal(originalString, JXON.xmlToString(xmlObject)); + }); + }); }); From e8add2c0fc8a03df65c3baae22b4f8f1ceec02c2 Mon Sep 17 00:00:00 2001 From: Laubstein Date: Tue, 16 Aug 2016 12:02:05 -0300 Subject: [PATCH 2/4] Minified version --- jxon.min.js | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/jxon.min.js b/jxon.min.js index ce7a673..77cfe4e 100644 --- a/jxon.min.js +++ b/jxon.min.js @@ -20,7 +20,7 @@ * bugfixes and code cleanup by user @laubstein * https://github.com/tyrasd/jxon/pull/32 * - * adapted for nodejs and npm by @tyrasd (Martin Raifer ) + * adapted for nodejs and npm by @tyrasd (Martin Raifer ) */ (function(e,t){if(typeof define==="function"&&define.amd){ // AMD. Register as an anonymous module. @@ -33,7 +33,25 @@ module.exports=t(window)}else{ // like Node. module.exports=t(require("xmldom"),true)}}else{ // Browser globals (root is window) -e.JXON=t(window)}})(this,function(e,t){var r={valueKey:"_",attrKey:"$",attrPrefix:"$",lowerCaseTags:false,trueIsEmpty:false,autoDate:false,ignorePrefixedNodes:false,parseValues:false};var n=[];var i=/^\s*$/;var o=/^(?:true|false)$/i;var a;return new function(){this.config=function(t){for(var n in t){r[n]=t[n]}if(r.parserErrorHandler){a=new e.DOMParser({errorHandler:r.parserErrorHandler,locator:{}})}};function s(e){if(!r.parseValues){return e}if(i.test(e)){return null}if(o.test(e)){return e.toLowerCase()==="true"}if(isFinite(e)){return parseFloat(e)}if(r.autoDate&&isFinite(Date.parse(e))){return new Date(e)}return e}function l(){}l.prototype.toString=function(){return"null"};l.prototype.valueOf=function(){return null};function f(e){return e===null?new l:e instanceof Object?e:new e.constructor(e)}function u(e,t,i,o){var a=4,l=3,c=1,d=n.length,p=e.hasChildNodes(),m=e.nodeType===e.ELEMENT_NODE&&e.hasAttributes(),h=Boolean(t&2),g=0,x="",v=h?{}:/* put here the default value for empty nodes: */r.trueIsEmpty?true:"",w,y;if(p){for(var T,S=0;S0)&&x){v[r.valueKey]=b}else if(!h&&g===0&&x){v=b}if(i&&(h||g>0)){Object.freeze(v)}n.length=d;return v}function c(e,n,i){var o,a,s;if(i.constructor===String||i.constructor===Number||i.constructor===Boolean){n.appendChild(e.createTextNode(i.toString()));/* verbosity level is 0 or 1 */ -if(i===i.valueOf()){return}}else if(i.constructor===Date){n.appendChild(e.createTextNode(i.toISOString()))}for(var l in i){o=i[l];if(o===null){o={}}if(isFinite(l)||o instanceof Function){continue}/* verbosity level is 0 */ -if(l===r.valueKey){if(o!==null&&o!==true){n.appendChild(e.createTextNode(o.constructor===Date?o.toISOString():String(o)))}}else if(l===r.attrKey){/* verbosity level is 3 */ -for(var f in o){n.setAttribute(f,o[f])}}else if(l===r.attrPrefix+"xmlns"){if(t){n.setAttribute(l.slice(1),o)}}else if(l.charAt(0)===r.attrPrefix){n.setAttribute(l.slice(1),o)}else if(o.constructor===Array){for(var u in o){s=o[u]&&o[u][r.attrPrefix+"xmlns"]||n.namespaceURI;if(s){a=e.createElementNS(s,l)}else{a=e.createElement(l)}c(e,a,o[u]||{});n.appendChild(a)}}else{s=(o||{})[r.attrPrefix+"xmlns"]||n.namespaceURI;if(s){a=e.createElementNS(s,l)}else{a=e.createElement(l)}if(o instanceof Object){c(e,a,o)}else if(o!==null&&o!==true){a.appendChild(e.createTextNode(o.toString()))}else if(!r.trueIsEmpty&&o===true){a.appendChild(e.createTextNode(o.toString()))}n.appendChild(a)}}}this.xmlToJs=this.build=function(e,t,r,n){var i=arguments.length>1&&typeof t==="number"?t&3:1;return u(e,i,r||false,arguments.length>3?n:i===3)};this.jsToXml=this.unbuild=function(t,r,n,i){var o=e.document&&e.document.implementation||new e.DOMImplementation;var a=o.createDocument(r||null,n||"",i||null);c(a,a.documentElement||a,t);return a};this.stringToXml=function(t){if(!a){a=new e.DOMParser}return a.parseFromString(t,"application/xml")};this.xmlToString=function(t){if(typeof t.xml!=="undefined"){return t.xml}else{return(new e.XMLSerializer).serializeToString(t)}};this.stringToJs=function(e){var t=this.stringToXml(e);return this.xmlToJs(t)};this.jsToString=this.stringify=function(e,t,r,n){return this.xmlToString(this.jsToXml(e,t,r,n))};this.each=function(e,t,r){if(e instanceof Array){e.forEach(t,r)}else{[e].forEach(t,r)}}}}); \ No newline at end of file +e.JXON=t(window)}})(this,function(e,t){var r={valueKey:"_",attrKey:"$",attrPrefix:"$",lowerCaseTags:false,trueIsEmpty:false,autoDate:false,ignorePrefixedNodes:false,parseValues:false,forceXmlProlog:false,defaultXmlProlog:''};var n=[];var i=/^\s*$/;var o=/^(?:true|false)$/i;var a=/^(<\?xml.*?\?>)/;var l=/\b(version|encoding|standalone)="([^"]+?)"/g;var s={};var f;return new function(){this.config=function(t){for(var n in t){r[n]=t[n]}if(r.parserErrorHandler){f=new e.DOMParser({errorHandler:r.parserErrorHandler,locator:{}})}};/** + * Helper function: given a xml prolog (eg: ), + * returns a object (eg: { version: "1.0" }). + */ +function u(e){var t=e.match(l);var r={};for(var n=0;n). + */ +function c(e){var t=[];for(var r in e){if(e.hasOwnProperty(r)){t.push(r+'="'+e[r]+'"')}}return t.length?"":""}/** + * Helper function: check for empty object + */ +function d(e){for(var t in e){if(e.hasOwnProperty(t)){return false}}return true&&JSON.stringify(e)===JSON.stringify({})}/** + * Helper function: clone a object + */ +function m(e){return JSON.parse(JSON.stringify(e))}function p(e){if(!r.parseValues){return e}if(i.test(e)){return null}if(o.test(e)){return e.toLowerCase()==="true"}if(isFinite(e)){return parseFloat(e)}if(r.autoDate&&isFinite(Date.parse(e))){return new Date(e)}return e}function h(){}h.prototype.toString=function(){return"null"};h.prototype.valueOf=function(){return null};function g(e){return e===null?new h:e instanceof Object?e:new e.constructor(e)}function v(e,t,i,o){var a=4,l=3,s=1,f=n.length,u=e.hasChildNodes(),c=e.nodeType===e.ELEMENT_NODE&&e.hasAttributes(),d=Boolean(t&2),m=0,h="",x=d?{}:/* put here the default value for empty nodes: */r.trueIsEmpty?true:"",y,w;if(u){for(var T,S=0;S0)&&h){x[r.valueKey]=O}else if(!d&&m===0&&h){x=O}if(i&&(d||m>0)){Object.freeze(x)}n.length=f;return x}function x(e,n,i){var o,a,l;if(i.constructor===String||i.constructor===Number||i.constructor===Boolean){n.appendChild(e.createTextNode(i.toString()));/* verbosity level is 0 or 1 */ +if(i===i.valueOf()){return}}else if(i.constructor===Date){n.appendChild(e.createTextNode(i.toISOString()))}for(var f in i){o=i[f];if(o===null){o={}}if(isFinite(f)||o instanceof Function){continue}/* verbosity level is 0 */ +if(f===r.valueKey){if(o!==null&&o!==true){n.appendChild(e.createTextNode(o.constructor===Date?o.toISOString():String(o)))}}else if(f===r.attrKey){/* verbosity level is 3 */ +for(var u in o){n.setAttribute(u,o[u])}}else if(f===r.attrPrefix+"xmlns"){if(t){n.setAttribute(f.slice(1),o)}}else if(f===r.attrPrefix+"xmlProlog"){ +// store xmlProlog +if(o){s=m(o)}}else if(f.charAt(0)===r.attrPrefix){n.setAttribute(f.slice(1),o)}else if(o.constructor===Array){for(var c in o){l=o[c]&&o[c][r.attrPrefix+"xmlns"]||n.namespaceURI;if(l){a=e.createElementNS(l,f)}else{a=e.createElement(f)}x(e,a,o[c]||{});n.appendChild(a)}}else{l=(o||{})[r.attrPrefix+"xmlns"]||n.namespaceURI;if(l){a=e.createElementNS(l,f)}else{a=e.createElement(f)}if(o instanceof Object){x(e,a,o)}else if(o!==null&&o!==true){a.appendChild(e.createTextNode(o.toString()))}else if(!r.trueIsEmpty&&o===true){a.appendChild(e.createTextNode(o.toString()))}n.appendChild(a)}}}this.xmlToJs=this.build=function(e,t,n,i){var o=arguments.length>1&&typeof t==="number"?t&3:/* put here the default verbosity level: */1;var a=v(e,o,n||false,arguments.length>3?i:o===3);if(!d(s)){a[r.attrPrefix+"xmlProlog"]=m(s);s={}}return a};this.jsToXml=this.unbuild=function(t,r,n,i){var o=e.document&&e.document.implementation||new e.DOMImplementation;var a=o.createDocument(r||null,n||"",i||null);x(a,a.documentElement||a,t);return a};this.stringToXml=function(t){if(!f){f=new e.DOMParser}if(a.test(t)){s=u(t.match(a)[0])}return f.parseFromString(t,"application/xml")};this.xmlToString=function(t){var n="";if(typeof t.xml!=="undefined"){n=t.xml}else{n=(new e.XMLSerializer).serializeToString(t)} +// if the original string has a prolog we include them, else we check the forceXmlProlog option +if(!a.test(n)&&(!d(s)||r.forceXmlProlog)){n=(c(s)||r.defaultXmlProlog)+n}return n};this.stringToJs=function(e){var t=this.stringToXml(e);return this.xmlToJs(t)};this.jsToString=this.stringify=function(e,t,r,n){return this.xmlToString(this.jsToXml(e,t,r,n))};this.each=function(e,t,r){if(e instanceof Array){e.forEach(t,r)}else{[e].forEach(t,r)}}}}); \ No newline at end of file From ba6a86adf634275bce32dcc116c163e737b4fbe1 Mon Sep 17 00:00:00 2001 From: Laubstein Date: Tue, 16 Aug 2016 12:40:19 -0300 Subject: [PATCH 3/4] Fixed a problem with firefox Firefox always serialize XML with '' --- jxon.js | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/jxon.js b/jxon.js index e955621..6945dec 100644 --- a/jxon.js +++ b/jxon.js @@ -61,7 +61,7 @@ var aCache = []; var rIsNull = /^\s*$/; var rIsBool = /^(?:true|false)$/i; - var rXmlProlog = /^(<\?xml.*?\?>)/; + var rXmlProlog = /^(<\?xml.*?\?>[\n]?)/; var rXmlPrologAttributes = /\b(version|encoding|standalone)="([^"]+?)"/g; var oXmlProlog = {}; var DOMParser; @@ -387,9 +387,14 @@ sReturn = (new xmlDom.XMLSerializer()).serializeToString(xmlObj); } - // if the original string has a prolog we include them, else we check the forceXmlProlog option - if (!rXmlProlog.test(sReturn) && (!isEmptyObject(oXmlProlog) || opts.forceXmlProlog)) { - sReturn = (getPrologFromObject(oXmlProlog) || opts.defaultXmlProlog) + sReturn; + // if the original string has a prolog or forceXmlProlog option is true, we include a new one or replace the existent + if (!isEmptyObject(oXmlProlog) || opts.forceXmlProlog) { + if (rXmlProlog.test(sReturn)) { + // replace the prolog + sReturn = sReturn.replace(rXmlProlog, (getPrologFromObject(oXmlProlog) || opts.defaultXmlProlog)); + } else { + sReturn = (getPrologFromObject(oXmlProlog) || opts.defaultXmlProlog) + sReturn; + } } return sReturn; From a7aa48ea7b412f148f98d0a534ef7ea76426ea6d Mon Sep 17 00:00:00 2001 From: Laubstein Date: Tue, 16 Aug 2016 13:13:59 -0300 Subject: [PATCH 4/4] Minified version --- jxon.min.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/jxon.min.js b/jxon.min.js index 77cfe4e..d308603 100644 --- a/jxon.min.js +++ b/jxon.min.js @@ -33,7 +33,7 @@ module.exports=t(window)}else{ // like Node. module.exports=t(require("xmldom"),true)}}else{ // Browser globals (root is window) -e.JXON=t(window)}})(this,function(e,t){var r={valueKey:"_",attrKey:"$",attrPrefix:"$",lowerCaseTags:false,trueIsEmpty:false,autoDate:false,ignorePrefixedNodes:false,parseValues:false,forceXmlProlog:false,defaultXmlProlog:''};var n=[];var i=/^\s*$/;var o=/^(?:true|false)$/i;var a=/^(<\?xml.*?\?>)/;var l=/\b(version|encoding|standalone)="([^"]+?)"/g;var s={};var f;return new function(){this.config=function(t){for(var n in t){r[n]=t[n]}if(r.parserErrorHandler){f=new e.DOMParser({errorHandler:r.parserErrorHandler,locator:{}})}};/** +e.JXON=t(window)}})(this,function(e,t){var r={valueKey:"_",attrKey:"$",attrPrefix:"$",lowerCaseTags:false,trueIsEmpty:false,autoDate:false,ignorePrefixedNodes:false,parseValues:false,forceXmlProlog:false,defaultXmlProlog:''};var n=[];var i=/^\s*$/;var o=/^(?:true|false)$/i;var a=/^(<\?xml.*?\?>[\n]?)/;var l=/\b(version|encoding|standalone)="([^"]+?)"/g;var s={};var f;return new function(){this.config=function(t){for(var n in t){r[n]=t[n]}if(r.parserErrorHandler){f=new e.DOMParser({errorHandler:r.parserErrorHandler,locator:{}})}};/** * Helper function: given a xml prolog (eg: ), * returns a object (eg: { version: "1.0" }). */ @@ -47,11 +47,13 @@ function c(e){var t=[];for(var r in e){if(e.hasOwnProperty(r)){t.push(r+'="'+e[r function d(e){for(var t in e){if(e.hasOwnProperty(t)){return false}}return true&&JSON.stringify(e)===JSON.stringify({})}/** * Helper function: clone a object */ -function m(e){return JSON.parse(JSON.stringify(e))}function p(e){if(!r.parseValues){return e}if(i.test(e)){return null}if(o.test(e)){return e.toLowerCase()==="true"}if(isFinite(e)){return parseFloat(e)}if(r.autoDate&&isFinite(Date.parse(e))){return new Date(e)}return e}function h(){}h.prototype.toString=function(){return"null"};h.prototype.valueOf=function(){return null};function g(e){return e===null?new h:e instanceof Object?e:new e.constructor(e)}function v(e,t,i,o){var a=4,l=3,s=1,f=n.length,u=e.hasChildNodes(),c=e.nodeType===e.ELEMENT_NODE&&e.hasAttributes(),d=Boolean(t&2),m=0,h="",x=d?{}:/* put here the default value for empty nodes: */r.trueIsEmpty?true:"",y,w;if(u){for(var T,S=0;S0)&&h){x[r.valueKey]=O}else if(!d&&m===0&&h){x=O}if(i&&(d||m>0)){Object.freeze(x)}n.length=f;return x}function x(e,n,i){var o,a,l;if(i.constructor===String||i.constructor===Number||i.constructor===Boolean){n.appendChild(e.createTextNode(i.toString()));/* verbosity level is 0 or 1 */ +function m(e){return JSON.parse(JSON.stringify(e))}function p(e){if(!r.parseValues){return e}if(i.test(e)){return null}if(o.test(e)){return e.toLowerCase()==="true"}if(isFinite(e)){return parseFloat(e)}if(r.autoDate&&isFinite(Date.parse(e))){return new Date(e)}return e}function h(){}h.prototype.toString=function(){return"null"};h.prototype.valueOf=function(){return null};function g(e){return e===null?new h:e instanceof Object?e:new e.constructor(e)}function v(e,t,i,o){var a=4,l=3,s=1,f=n.length,u=e.hasChildNodes(),c=e.nodeType===e.ELEMENT_NODE&&e.hasAttributes(),d=Boolean(t&2),m=0,h="",x=d?{}:/* put here the default value for empty nodes: */r.trueIsEmpty?true:"",y,w;if(u){for(var T,P=0;P0)&&h){x[r.valueKey]=N}else if(!d&&m===0&&h){x=N}if(i&&(d||m>0)){Object.freeze(x)}n.length=f;return x}function x(e,n,i){var o,a,l;if(i.constructor===String||i.constructor===Number||i.constructor===Boolean){n.appendChild(e.createTextNode(i.toString()));/* verbosity level is 0 or 1 */ if(i===i.valueOf()){return}}else if(i.constructor===Date){n.appendChild(e.createTextNode(i.toISOString()))}for(var f in i){o=i[f];if(o===null){o={}}if(isFinite(f)||o instanceof Function){continue}/* verbosity level is 0 */ if(f===r.valueKey){if(o!==null&&o!==true){n.appendChild(e.createTextNode(o.constructor===Date?o.toISOString():String(o)))}}else if(f===r.attrKey){/* verbosity level is 3 */ for(var u in o){n.setAttribute(u,o[u])}}else if(f===r.attrPrefix+"xmlns"){if(t){n.setAttribute(f.slice(1),o)}}else if(f===r.attrPrefix+"xmlProlog"){ // store xmlProlog if(o){s=m(o)}}else if(f.charAt(0)===r.attrPrefix){n.setAttribute(f.slice(1),o)}else if(o.constructor===Array){for(var c in o){l=o[c]&&o[c][r.attrPrefix+"xmlns"]||n.namespaceURI;if(l){a=e.createElementNS(l,f)}else{a=e.createElement(f)}x(e,a,o[c]||{});n.appendChild(a)}}else{l=(o||{})[r.attrPrefix+"xmlns"]||n.namespaceURI;if(l){a=e.createElementNS(l,f)}else{a=e.createElement(f)}if(o instanceof Object){x(e,a,o)}else if(o!==null&&o!==true){a.appendChild(e.createTextNode(o.toString()))}else if(!r.trueIsEmpty&&o===true){a.appendChild(e.createTextNode(o.toString()))}n.appendChild(a)}}}this.xmlToJs=this.build=function(e,t,n,i){var o=arguments.length>1&&typeof t==="number"?t&3:/* put here the default verbosity level: */1;var a=v(e,o,n||false,arguments.length>3?i:o===3);if(!d(s)){a[r.attrPrefix+"xmlProlog"]=m(s);s={}}return a};this.jsToXml=this.unbuild=function(t,r,n,i){var o=e.document&&e.document.implementation||new e.DOMImplementation;var a=o.createDocument(r||null,n||"",i||null);x(a,a.documentElement||a,t);return a};this.stringToXml=function(t){if(!f){f=new e.DOMParser}if(a.test(t)){s=u(t.match(a)[0])}return f.parseFromString(t,"application/xml")};this.xmlToString=function(t){var n="";if(typeof t.xml!=="undefined"){n=t.xml}else{n=(new e.XMLSerializer).serializeToString(t)} -// if the original string has a prolog we include them, else we check the forceXmlProlog option -if(!a.test(n)&&(!d(s)||r.forceXmlProlog)){n=(c(s)||r.defaultXmlProlog)+n}return n};this.stringToJs=function(e){var t=this.stringToXml(e);return this.xmlToJs(t)};this.jsToString=this.stringify=function(e,t,r,n){return this.xmlToString(this.jsToXml(e,t,r,n))};this.each=function(e,t,r){if(e instanceof Array){e.forEach(t,r)}else{[e].forEach(t,r)}}}}); \ No newline at end of file +// if the original string has a prolog or forceXmlProlog option is true, we include a new one or replace the existent +if(!d(s)||r.forceXmlProlog){if(a.test(n)){ +// replace the prolog +n=n.replace(a,c(s)||r.defaultXmlProlog)}else{n=(c(s)||r.defaultXmlProlog)+n}}return n};this.stringToJs=function(e){var t=this.stringToXml(e);return this.xmlToJs(t)};this.jsToString=this.stringify=function(e,t,r,n){return this.xmlToString(this.jsToXml(e,t,r,n))};this.each=function(e,t,r){if(e instanceof Array){e.forEach(t,r)}else{[e].forEach(t,r)}}}}); \ No newline at end of file