-
Notifications
You must be signed in to change notification settings - Fork 0
/
xml2json.js
166 lines (165 loc) · 5.73 KB
/
xml2json.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
/* 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/
*/
export function xml2json(xml, tab) {
var X = {
toObj: function (xml) {
var o = {};
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.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(/[^ \f\n\r\t\v]/))
textChild++; // non-whitespace text
else if (n.nodeType == 4) cdataChild++; // cdata section node
}
if (hasElementChild) {
if (textChild < 2 && cdataChild < 2) {
// structured element with evtl. a single text or/and cdata node ..
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]) {
// multiple occurence of element ..
if (o[n.nodeName] instanceof Array)
o[n.nodeName][o[n.nodeName].length] = X.toObj(n);
else o[n.nodeName] = [o[n.nodeName], X.toObj(n)];
} // first occurence of element..
else o[n.nodeName] = X.toObj(n);
}
} 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));
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);
}
}
if (!xml.attributes.length && !xml.firstChild) o = null;
} else if (xml.nodeType == 9) {
// document.node
o = X.toObj(xml.documentElement);
}
return o;
},
toJson: function (o, name, ind) {
var json = name ? '"' + name + '"' : "";
if (o instanceof Array) {
for (var i = 0, n = o.length; i < n; i++)
o[i] = X.toJson(o[i], "", ind + "\t");
json +=
(name ? ":[" : "[") +
(o.length > 1
? "\n" + ind + "\t" + o.join(",\n" + ind + "\t") + "\n" + ind
: o.join("")) +
"]";
} else if (o == null) json += (name && ":") + "null";
else if (typeof o == "object") {
var arr = [];
for (var m in o) arr[arr.length] = X.toJson(o[m], m, ind + "\t");
json +=
(name ? ":{" : "{") +
(arr.length > 1
? "\n" + ind + "\t" + arr.join(",\n" + ind + "\t") + "\n" + ind
: arr.join("")) +
"}";
} else if (typeof o == "string")
json += (name && ":") + '"' + o.toString() + '"';
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 = "";
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;
} // any other node
else n = n.nextSibling;
}
return e;
},
};
if (xml.nodeType == 9)
// document node
xml = xml.documentElement;
var json = X.toJson(X.toObj(X.removeWhite(xml)), xml.nodeName, "\t");
return (
"{\n" +
tab +
(tab ? json.replace(/\t/g, tab) : json.replace(/\t|\n/g, "")) +
"\n}"
);
}