Mercurial > eldonilo > blog
comparison 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 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:f62b5c395a48 |
---|---|
1 /* This work is licensed under Creative Commons GNU LGPL License. | |
2 | |
3 License: http://creativecommons.org/licenses/LGPL/2.1/ | |
4 Version: 0.9 | |
5 Author: Stefan Goessner/2006 | |
6 Web: http://goessner.net/ | |
7 */ | |
8 var Element = function() { | |
9 this.getChildren = function(name, ns) { | |
10 var children = []; | |
11 var r = false; | |
12 | |
13 for (var i in this) { | |
14 if (typeof this[i] !== 'object') | |
15 continue; | |
16 | |
17 var child = this[i]; | |
18 if((!name || i === name) && | |
19 (!ns || child[0]['@xmlns'] === ns)) { | |
20 for (var j=0; j<child.length; j++) | |
21 children.push(child[j]); | |
22 r = true; | |
23 } | |
24 } | |
25 | |
26 if (r) | |
27 return children; | |
28 | |
29 return null; | |
30 }; | |
31 | |
32 this.getChild = function(name, ns) { | |
33 var children = this.getChildren(name, ns); | |
34 if (!children || children.length != 1) | |
35 return null; | |
36 | |
37 return children[0]; | |
38 }; | |
39 | |
40 this.getAttribute = function(name, ns) { | |
41 return this['@'+name]; // FIXME: namespace | |
42 }; | |
43 | |
44 this.getText = function() { | |
45 return this; | |
46 } | |
47 }; | |
48 | |
49 function xml2json(xml, tab) { | |
50 var X = { | |
51 toObj: function(xml, parentNS) { | |
52 var o = new Element(); | |
53 if (xml.nodeType==1) { // element node .. | |
54 if (xml.attributes.length) // element with attributes .. | |
55 for (var i=0; i<xml.attributes.length; i++) { | |
56 o["@"+xml.attributes[i].nodeName] = (xml.attributes[i].nodeValue||"").toString(); | |
57 if (xml.attributes[i].nodeName === 'xmlns') | |
58 parentNS = xml.attributes[i].nodeValue; | |
59 } | |
60 if (!o['@xmlns']) | |
61 o['@xmlns'] = parentNS; | |
62 if (xml.firstChild) { // element has child nodes .. | |
63 var textChild=0, cdataChild=0, hasElementChild=false; | |
64 for (var n=xml.firstChild; n; n=n.nextSibling) { | |
65 if (n.nodeType==1) hasElementChild = true; | |
66 else if (n.nodeType==3 && n.nodeValue.match(/[\S]/)) textChild++; // non-whitespace text | |
67 else if (n.nodeType==4) cdataChild++; // cdata section node | |
68 } | |
69 if (hasElementChild) { | |
70 // structured element with evtl. a single text or/and cdata | |
71 // node .. | |
72 if (textChild < 2 && cdataChild < 2) { | |
73 X.removeWhite(xml); | |
74 for (var n=xml.firstChild; n; n=n.nextSibling) | |
75 if (n.nodeType == 3) // text node | |
76 o["#text"] = X.escape(n.nodeValue); | |
77 else if (n.nodeType == 4) // cdata node | |
78 o["#cdata"] = X.escape(n.nodeValue); | |
79 else { | |
80 if(!o[n.nodeName]) | |
81 o[n.nodeName] = [X.toObj(n, parentNS)]; | |
82 else | |
83 o[n.nodeName].push(X.toObj(n, parentNS)); | |
84 } | |
85 } | |
86 else { // mixed content | |
87 if (!xml.attributes.length) | |
88 o = X.escape(X.innerXml(xml)); | |
89 else | |
90 o["#text"] = X.escape(X.innerXml(xml)); | |
91 } | |
92 } | |
93 else if (textChild) { // pure text | |
94 if (!xml.attributes.length) | |
95 o = X.escape(X.innerXml(xml)).replace(/\\\\/g, '\\'); | |
96 else | |
97 o["#text"] = X.escape(X.innerXml(xml)); | |
98 } | |
99 else if (cdataChild) { // cdata | |
100 if (cdataChild > 1) | |
101 o = X.escape(X.innerXml(xml)); | |
102 else | |
103 for (var n=xml.firstChild; n; n=n.nextSibling) | |
104 o["#cdata"] = X.escape(n.nodeValue); | |
105 } | |
106 } | |
107 | |
108 return (!xml.attributes.length && !xml.firstChild) ? null : o; | |
109 } | |
110 | |
111 if (xml.nodeType==9) // document.node | |
112 return X.toObj(xml.documentElement); | |
113 | |
114 throw("unhandled node type: " + xml.nodeType); | |
115 }, | |
116 innerXml: function(node) { | |
117 var s = ""; | |
118 if ("innerHTML" in node) | |
119 s = node.innerHTML; | |
120 else { | |
121 var asXml = function(n) { | |
122 var s = ""; | |
123 if (n.nodeType == 1) { | |
124 s += "<" + n.nodeName; | |
125 for (var i=0; i<n.attributes.length;i++) | |
126 s += " " + n.attributes[i].nodeName + "=\"" + (n.attributes[i].nodeValue||"").toString() + "\""; | |
127 if (n.firstChild) { | |
128 s += ">"; | |
129 for (var c=n.firstChild; c; c=c.nextSibling) | |
130 s += asXml(c); | |
131 s += "</"+n.nodeName+">"; | |
132 } | |
133 else | |
134 s += "/>"; | |
135 } | |
136 else if (n.nodeType == 3) | |
137 s += n.nodeValue; | |
138 else if (n.nodeType == 4) | |
139 s += "<![CDATA[" + n.nodeValue + "]]>"; | |
140 return s; | |
141 }; | |
142 for (var c=node.firstChild; c; c=c.nextSibling) | |
143 s += asXml(c); | |
144 } | |
145 return s; | |
146 }, | |
147 escape: function(txt) { | |
148 return txt.replace(/[\\]/g, "\\\\") | |
149 .replace(/[\"]/g, '\\"') | |
150 .replace(/[\n]/g, '\\n') | |
151 .replace(/[\r]/g, '\\r'); | |
152 }, | |
153 removeWhite: function(e) { | |
154 e.normalize(); | |
155 for (var n = e.firstChild; n; ) { | |
156 if (n.nodeType == 3) { // text node | |
157 if (!n.nodeValue.match(/[^ \f\n\r\t\v]/)) { // pure whitespace text node | |
158 var nxt = n.nextSibling; | |
159 e.removeChild(n); | |
160 n = nxt; | |
161 } | |
162 else | |
163 n = n.nextSibling; | |
164 } | |
165 else if (n.nodeType == 1) { // element node | |
166 X.removeWhite(n); | |
167 n = n.nextSibling; | |
168 } | |
169 else // any other node | |
170 n = n.nextSibling; | |
171 } | |
172 return e; | |
173 } | |
174 }; | |
175 if (xml.nodeType == 9) // document node | |
176 xml = xml.documentElement; | |
177 | |
178 //modified | |
179 return X.toObj(X.removeWhite(xml)); | |
180 } |