Mercurial > eldonilo > blog
diff xml2json.js @ 0:f62b5c395a48
Initial commit.
author | Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> |
---|---|
date | Sat, 04 Jun 2011 05:02:47 +0200 |
parents | |
children | eb5b6d3ab09b |
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/xml2json.js @@ -0,0 +1,180 @@ +/* This work is licensed under Creative Commons GNU LGPL License. + + License: http://creativecommons.org/licenses/LGPL/2.1/ + Version: 0.9 + Author: Stefan Goessner/2006 + Web: http://goessner.net/ +*/ +var Element = function() { + this.getChildren = function(name, ns) { + var children = []; + var r = false; + + for (var i in this) { + if (typeof this[i] !== 'object') + continue; + + var child = this[i]; + if((!name || i === name) && + (!ns || child[0]['@xmlns'] === ns)) { + for (var j=0; j<child.length; j++) + children.push(child[j]); + r = true; + } + } + + if (r) + return children; + + return null; + }; + + this.getChild = function(name, ns) { + var children = this.getChildren(name, ns); + if (!children || children.length != 1) + return null; + + return children[0]; + }; + + this.getAttribute = function(name, ns) { + return this['@'+name]; // FIXME: namespace + }; + + this.getText = function() { + return this; + } +}; + +function xml2json(xml, tab) { + var X = { + toObj: function(xml, parentNS) { + var o = new Element(); + if (xml.nodeType==1) { // element node .. + if (xml.attributes.length) // element with attributes .. + for (var i=0; i<xml.attributes.length; i++) { + o["@"+xml.attributes[i].nodeName] = (xml.attributes[i].nodeValue||"").toString(); + if (xml.attributes[i].nodeName === 'xmlns') + parentNS = xml.attributes[i].nodeValue; + } + if (!o['@xmlns']) + o['@xmlns'] = parentNS; + if (xml.firstChild) { // element has child nodes .. + var textChild=0, cdataChild=0, hasElementChild=false; + for (var n=xml.firstChild; n; n=n.nextSibling) { + if (n.nodeType==1) hasElementChild = true; + else if (n.nodeType==3 && n.nodeValue.match(/[\S]/)) textChild++; // non-whitespace text + else if (n.nodeType==4) cdataChild++; // cdata section node + } + if (hasElementChild) { + // structured element with evtl. a single text or/and cdata + // node .. + if (textChild < 2 && cdataChild < 2) { + X.removeWhite(xml); + for (var n=xml.firstChild; n; n=n.nextSibling) + if (n.nodeType == 3) // text node + o["#text"] = X.escape(n.nodeValue); + else if (n.nodeType == 4) // cdata node + o["#cdata"] = X.escape(n.nodeValue); + else { + if(!o[n.nodeName]) + o[n.nodeName] = [X.toObj(n, parentNS)]; + else + o[n.nodeName].push(X.toObj(n, parentNS)); + } + } + else { // mixed content + if (!xml.attributes.length) + o = X.escape(X.innerXml(xml)); + else + o["#text"] = X.escape(X.innerXml(xml)); + } + } + else if (textChild) { // pure text + if (!xml.attributes.length) + o = X.escape(X.innerXml(xml)).replace(/\\\\/g, '\\'); + else + o["#text"] = X.escape(X.innerXml(xml)); + } + else if (cdataChild) { // cdata + if (cdataChild > 1) + o = X.escape(X.innerXml(xml)); + else + for (var n=xml.firstChild; n; n=n.nextSibling) + o["#cdata"] = X.escape(n.nodeValue); + } + } + + return (!xml.attributes.length && !xml.firstChild) ? null : o; + } + + if (xml.nodeType==9) // document.node + return X.toObj(xml.documentElement); + + throw("unhandled node type: " + xml.nodeType); + }, + innerXml: function(node) { + var s = ""; + if ("innerHTML" in node) + s = node.innerHTML; + else { + var asXml = function(n) { + var s = ""; + if (n.nodeType == 1) { + s += "<" + n.nodeName; + for (var i=0; i<n.attributes.length;i++) + s += " " + n.attributes[i].nodeName + "=\"" + (n.attributes[i].nodeValue||"").toString() + "\""; + if (n.firstChild) { + s += ">"; + for (var c=n.firstChild; c; c=c.nextSibling) + s += asXml(c); + s += "</"+n.nodeName+">"; + } + else + s += "/>"; + } + else if (n.nodeType == 3) + s += n.nodeValue; + else if (n.nodeType == 4) + s += "<![CDATA[" + n.nodeValue + "]]>"; + return s; + }; + for (var c=node.firstChild; c; c=c.nextSibling) + s += asXml(c); + } + return s; + }, + escape: function(txt) { + return txt.replace(/[\\]/g, "\\\\") + .replace(/[\"]/g, '\\"') + .replace(/[\n]/g, '\\n') + .replace(/[\r]/g, '\\r'); + }, + removeWhite: function(e) { + e.normalize(); + for (var n = e.firstChild; n; ) { + if (n.nodeType == 3) { // text node + if (!n.nodeValue.match(/[^ \f\n\r\t\v]/)) { // pure whitespace text node + var nxt = n.nextSibling; + e.removeChild(n); + n = nxt; + } + else + n = n.nextSibling; + } + else if (n.nodeType == 1) { // element node + X.removeWhite(n); + n = n.nextSibling; + } + else // any other node + n = n.nextSibling; + } + return e; + } + }; + if (xml.nodeType == 9) // document node + xml = xml.documentElement; + + //modified + return X.toObj(X.removeWhite(xml)); +}