You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

155 lines
6.4 KiB

8 years ago
  1. /* This work is licensed under Creative Commons GNU LGPL License.
  2. License: http://creativecommons.org/licenses/LGPL/2.1/
  3. Version: 0.9
  4. Author: Stefan Goessner/2006
  5. Web: http://goessner.net/
  6. */
  7. function xml2json(xml, tab) {
  8. var X = {
  9. toObj: function(xml) {
  10. var o = {};
  11. if (xml.nodeType==1) { // element node ..
  12. if (xml.attributes.length) // element with attributes ..
  13. for (var i=0; i<xml.attributes.length; i++)
  14. o["@"+xml.attributes[i].nodeName] = (xml.attributes[i].nodeValue||"").toString();
  15. if (xml.firstChild) { // element has child nodes ..
  16. var textChild=0, cdataChild=0, hasElementChild=false;
  17. for (var n=xml.firstChild; n; n=n.nextSibling) {
  18. if (n.nodeType==1) hasElementChild = true;
  19. else if (n.nodeType==3 && n.nodeValue.match(/[^ \f\n\r\t\v]/)) textChild++; // non-whitespace text
  20. else if (n.nodeType==4) cdataChild++; // cdata section node
  21. }
  22. if (hasElementChild) {
  23. if (textChild < 2 && cdataChild < 2) { // structured element with evtl. a single text or/and cdata node ..
  24. X.removeWhite(xml);
  25. for (var n=xml.firstChild; n; n=n.nextSibling) {
  26. if (n.nodeType == 3) // text node
  27. o["#text"] = X.escape(n.nodeValue);
  28. else if (n.nodeType == 4) // cdata node
  29. o["#cdata"] = X.escape(n.nodeValue);
  30. else if (o[n.nodeName]) { // multiple occurence of element ..
  31. if (o[n.nodeName] instanceof Array)
  32. o[n.nodeName][o[n.nodeName].length] = X.toObj(n);
  33. else
  34. o[n.nodeName] = [o[n.nodeName], X.toObj(n)];
  35. }
  36. else // first occurence of element..
  37. o[n.nodeName] = X.toObj(n);
  38. }
  39. }
  40. else { // mixed content
  41. if (!xml.attributes.length)
  42. o = X.escape(X.innerXml(xml));
  43. else
  44. o["#text"] = X.escape(X.innerXml(xml));
  45. }
  46. }
  47. else if (textChild) { // pure text
  48. if (!xml.attributes.length)
  49. o = X.escape(X.innerXml(xml));
  50. else
  51. o["#text"] = X.escape(X.innerXml(xml));
  52. }
  53. else if (cdataChild) { // cdata
  54. if (cdataChild > 1)
  55. o = X.escape(X.innerXml(xml));
  56. else
  57. for (var n=xml.firstChild; n; n=n.nextSibling)
  58. o["#cdata"] = X.escape(n.nodeValue);
  59. }
  60. }
  61. if (!xml.attributes.length && !xml.firstChild) o = null;
  62. }
  63. else if (xml.nodeType==9) { // document.node
  64. o = X.toObj(xml.documentElement);
  65. }
  66. else
  67. alert("unhandled node type: " + xml.nodeType);
  68. return o;
  69. },
  70. toJson: function(o, name, ind) {
  71. var json = name ? ("\""+name+"\"") : "";
  72. if (o instanceof Array) {
  73. for (var i=0,n=o.length; i<n; i++)
  74. o[i] = X.toJson(o[i], "", ind+"\t");
  75. json += (name?":[":"[") + (o.length > 1 ? ("\n"+ind+"\t"+o.join(",\n"+ind+"\t")+"\n"+ind) : o.join("")) + "]";
  76. }
  77. else if (o == null)
  78. json += (name&&":") + "null";
  79. else if (typeof(o) == "object") {
  80. var arr = [];
  81. for (var m in o)
  82. arr[arr.length] = X.toJson(o[m], m, ind+"\t");
  83. json += (name?":{":"{") + (arr.length > 1 ? ("\n"+ind+"\t"+arr.join(",\n"+ind+"\t")+"\n"+ind) : arr.join("")) + "}";
  84. }
  85. else if (typeof(o) == "string")
  86. json += (name&&":") + "\"" + o.toString() + "\"";
  87. else
  88. json += (name&&":") + o.toString();
  89. return json;
  90. },
  91. innerXml: function(node) {
  92. var s = ""
  93. if ("innerHTML" in node)
  94. s = node.innerHTML;
  95. else {
  96. var asXml = function(n) {
  97. var s = "";
  98. if (n.nodeType == 1) {
  99. s += "<" + n.nodeName;
  100. for (var i=0; i<n.attributes.length;i++)
  101. s += " " + n.attributes[i].nodeName + "=\"" + (n.attributes[i].nodeValue||"").toString() + "\"";
  102. if (n.firstChild) {
  103. s += ">";
  104. for (var c=n.firstChild; c; c=c.nextSibling)
  105. s += asXml(c);
  106. s += "</"+n.nodeName+">";
  107. }
  108. else
  109. s += "/>";
  110. }
  111. else if (n.nodeType == 3)
  112. s += n.nodeValue;
  113. else if (n.nodeType == 4)
  114. s += "<![CDATA[" + n.nodeValue + "]]>";
  115. return s;
  116. };
  117. for (var c=node.firstChild; c; c=c.nextSibling)
  118. s += asXml(c);
  119. }
  120. return s;
  121. },
  122. escape: function(txt) {
  123. return txt.replace(/[\\]/g, "\\\\")
  124. .replace(/[\"]/g, '\\"')
  125. .replace(/[\n]/g, '\\n')
  126. .replace(/[\r]/g, '\\r');
  127. },
  128. removeWhite: function(e) {
  129. e.normalize();
  130. for (var n = e.firstChild; n; ) {
  131. if (n.nodeType == 3) { // text node
  132. if (!n.nodeValue.match(/[^ \f\n\r\t\v]/)) { // pure whitespace text node
  133. var nxt = n.nextSibling;
  134. e.removeChild(n);
  135. n = nxt;
  136. }
  137. else
  138. n = n.nextSibling;
  139. }
  140. else if (n.nodeType == 1) { // element node
  141. X.removeWhite(n);
  142. n = n.nextSibling;
  143. }
  144. else // any other node
  145. n = n.nextSibling;
  146. }
  147. return e;
  148. }
  149. };
  150. if (xml.nodeType == 9) // document node
  151. xml = xml.documentElement;
  152. var json = X.toJson(X.toObj(X.removeWhite(xml)), xml.nodeName, "\t");
  153. return "{\n" + tab + (tab ? json.replace(/\t/g, tab) : json.replace(/\t|\n/g, "")) + "\n}";
  154. }