view xml2json.js @ 2:eb5b6d3ab09b

Better import of ns and jid; fix email and missing ns.
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Wed, 13 Jul 2011 13:11:54 +0200
parents f62b5c395a48
children
line wrap: on
line source

/*	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));
}