123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339 |
- /*
- The below work is licensed under Creative Commons GNU LGPL License.
- Original work:
- License: http://creativecommons.org/licenses/LGPL/2.1/
- Author: Stefan Goessner/2006
- Web: http://goessner.net/
- Modifications made:
- Version: 0.9-p5
- Description: Restructured code, JSLint validated (no strict whitespaces),
- added handling of empty arrays, empty strings, and int/floats values.
- Author: Michael Schøler/2008-01-29
- Web: http://michael.hinnerup.net/blog/2008/01/26/converting-json-to-xml-and-xml-to-json/
-
- Description: json2xml added support to convert functions as CDATA
- so it will be easy to write characters that cause some problems when convert
- Author: Tony Tomov
- */
- /*global alert */
- var xmlJsonClass = {
- // Param "xml": Element or document DOM node.
- // Param "tab": Tab or indent string for pretty output formatting omit or use empty string "" to supress.
- // Returns: JSON string
- xml2json: function(xml, tab) {
- if (xml.nodeType === 9) {
- // document node
- xml = xml.documentElement;
- }
- var nws = this.removeWhite(xml);
- var obj = this.toObj(nws);
- var json = this.toJson(obj, xml.nodeName, "\t");
- return "{\n" + tab + (tab ? json.replace(/\t/g, tab) : json.replace(/\t|\n/g, "")) + "\n}";
- },
- // Param "o": JavaScript object
- // Param "tab": tab or indent string for pretty output formatting omit or use empty string "" to supress.
- // Returns: XML string
- json2xml: function(o, tab) {
- var toXml = function(v, name, ind) {
- var xml = "";
- var i, n;
- if (v instanceof Array) {
- if (v.length === 0) {
- xml += ind + "<"+name+">__EMPTY_ARRAY_</"+name+">\n";
- }
- else {
- for (i = 0, n = v.length; i < n; i += 1) {
- var sXml = ind + toXml(v[i], name, ind+"\t") + "\n";
- xml += sXml;
- }
- }
- }
- else if (typeof(v) === "object") {
- var hasChild = false;
- xml += ind + "<" + name;
- var m;
- for (m in v) if (v.hasOwnProperty(m)) {
- if (m.charAt(0) === "@") {
- xml += " " + m.substr(1) + "=\"" + v[m].toString() + "\"";
- }
- else {
- hasChild = true;
- }
- }
- xml += hasChild ? ">" : "/>";
- if (hasChild) {
- for (m in v) if (v.hasOwnProperty(m)) {
- if (m === "#text") {
- xml += v[m];
- }
- else if (m === "#cdata") {
- xml += "<![CDATA[" + v[m] + "]]>";
- }
- else if (m.charAt(0) !== "@") {
- xml += toXml(v[m], m, ind+"\t");
- }
- }
- xml += (xml.charAt(xml.length - 1) === "\n" ? ind : "") + "</" + name + ">";
- }
- }
- else if (typeof(v) === "function") {
- xml += ind + "<" + name + ">" + "<![CDATA[" + v + "]]>" + "</" + name + ">";
- }
- else {
- if (v === undefined ) { v = ""; }
- if (v.toString() === "\"\"" || v.toString().length === 0) {
- xml += ind + "<" + name + ">__EMPTY_STRING_</" + name + ">";
- }
- else {
- xml += ind + "<" + name + ">" + v.toString() + "</" + name + ">";
- }
- }
- return xml;
- };
- var xml = "";
- var m;
- for (m in o) if (o.hasOwnProperty(m)) {
- xml += toXml(o[m], m, "");
- }
- return tab ? xml.replace(/\t/g, tab) : xml.replace(/\t|\n/g, "");
- },
- // Internal methods
- toObj: function(xml) {
- var o = {};
- var FuncTest = /function/i;
- if (xml.nodeType === 1) {
- // element node ..
- if (xml.attributes.length) {
- // element with attributes ..
- var i;
- for (i = 0; i < xml.attributes.length; i += 1) {
- o["@" + xml.attributes[i].nodeName] = (xml.attributes[i].nodeValue || "").toString();
- }
- }
- if (xml.firstChild) {
- // element has child nodes ..
- var textChild = 0, cdataChild = 0, hasElementChild = false;
- var n;
- for (n = xml.firstChild; n; n = n.nextSibling) {
- if (n.nodeType === 1) {
- hasElementChild = true;
- }
- else if (n.nodeType === 3 && n.nodeValue.match(/[^ \f\n\r\t\v]/)) {
- // non-whitespace text
- textChild += 1;
- }
- else if (n.nodeType === 4) {
- // cdata section node
- cdataChild += 1;
- }
- }
- if (hasElementChild) {
- if (textChild < 2 && cdataChild < 2) {
- // structured element with evtl. a single text or/and cdata node ..
- this.removeWhite(xml);
- for (n = xml.firstChild; n; n = n.nextSibling) {
- if (n.nodeType === 3) {
- // text node
- o["#text"] = this.escape(n.nodeValue);
- }
- else if (n.nodeType === 4) {
- // cdata node
- if (FuncTest.test(n.nodeValue)) {
- o[n.nodeName] = [o[n.nodeName], n.nodeValue];
- } else {
- o["#cdata"] = this.escape(n.nodeValue);
- }
- }
- else if (o[n.nodeName]) {
- // multiple occurence of element ..
- if (o[n.nodeName] instanceof Array) {
- o[n.nodeName][o[n.nodeName].length] = this.toObj(n);
- }
- else {
- o[n.nodeName] = [o[n.nodeName], this.toObj(n)];
- }
- }
- else {
- // first occurence of element ..
- o[n.nodeName] = this.toObj(n);
- }
- }
- }
- else {
- // mixed content
- if (!xml.attributes.length) {
- o = this.escape(this.innerXml(xml));
- }
- else {
- o["#text"] = this.escape(this.innerXml(xml));
- }
- }
- }
- else if (textChild) {
- // pure text
- if (!xml.attributes.length) {
- o = this.escape(this.innerXml(xml));
- if (o === "__EMPTY_ARRAY_") {
- o = "[]";
- } else if (o === "__EMPTY_STRING_") {
- o = "";
- }
- }
- else {
- o["#text"] = this.escape(this.innerXml(xml));
- }
- }
- else if (cdataChild) {
- // cdata
- if (cdataChild > 1) {
- o = this.escape(this.innerXml(xml));
- }
- else {
- for (n = xml.firstChild; n; n = n.nextSibling) {
- if(FuncTest.test(xml.firstChild.nodeValue)) {
- o = xml.firstChild.nodeValue;
- break;
- } else {
- o["#cdata"] = this.escape(n.nodeValue);
- }
- }
- }
- }
- }
- if (!xml.attributes.length && !xml.firstChild) {
- o = null;
- }
- }
- else if (xml.nodeType === 9) {
- // document.node
- o = this.toObj(xml.documentElement);
- }
- else {
- alert("unhandled node type: " + xml.nodeType);
- }
- return o;
- },
- toJson: function(o, name, ind, wellform) {
- if(wellform === undefined) wellform = true;
- var json = name ? ("\"" + name + "\"") : "", tab = "\t", newline = "\n";
- if(!wellform) {
- tab= ""; newline= "";
- }
- if (o === "[]") {
- json += (name ? ":[]" : "[]");
- }
- else if (o instanceof Array) {
- var n, i, ar=[];
- for (i = 0, n = o.length; i < n; i += 1) {
- ar[i] = this.toJson(o[i], "", ind + tab, wellform);
- }
- json += (name ? ":[" : "[") + (ar.length > 1 ? (newline + ind + tab + ar.join(","+newline + ind + tab) + newline + ind) : ar.join("")) + "]";
- }
- else if (o === null) {
- json += (name && ":") + "null";
- }
- else if (typeof(o) === "object") {
- var arr = [], m;
- for (m in o) {
- if (o.hasOwnProperty(m)) {
- arr[arr.length] = this.toJson(o[m], m, ind + tab, wellform);
- }
- }
- json += (name ? ":{" : "{") + (arr.length > 1 ? (newline + ind + tab + arr.join(","+newline + ind + tab) + newline + ind) : arr.join("")) + "}";
- }
- else if (typeof(o) === "string") {
- /*
- var objRegExp = /(^-?\d+\.?\d*$)/;
- var FuncTest = /function/i;
- var os = o.toString();
- if (objRegExp.test(os) || FuncTest.test(os) || os==="false" || os==="true") {
- // int or float
- json += (name && ":") + "\"" +os + "\"";
- }
- else {
- */
- json += (name && ":") + "\"" + o.replace(/\\/g,'\\\\').replace(/\"/g,'\\"') + "\"";
- //}
- }
- else {
- json += (name && ":") + o.toString();
- }
- return json;
- },
- innerXml: function(node) {
- var s = "";
- if ("innerHTML" in node) {
- s = node.innerHTML;
- }
- else {
- var asXml = function(n) {
- var s = "", i;
- if (n.nodeType === 1) {
- s += "<" + n.nodeName;
- for (i = 0; i < n.attributes.length; i += 1) {
- 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();
- var n;
- for (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
- this.removeWhite(n);
- n = n.nextSibling;
- }
- else {
- // any other node
- n = n.nextSibling;
- }
- }
- return e;
- }
- };
|