PageSourceSearch

https://copernicube.eu/rasdaman/ows/assets/components/xmlToJSON.js/lib/xmlToJSON.js

js copernicube.eu collected 2026-10-07 23:22:52 UTC 9,041 bytes, 242 lines download raw bytes

1/* Copyright 2015 William Summers, MetaTribal LLC
2 * adapted from https://developer.mozilla.org/en-US/docs/JXON
3 *
4 * Licensed under the MIT License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     https://opensource.org/licenses/MIT
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16/**
17 * @author William Summers
18 *
19 */
20
21var xmlToJSON = (function () {
22
23    this.version = "1.3";
24
25    var options = { // set up the default options
26        mergeCDATA: true, // extract cdata and merge with text
27        grokAttr: true, // convert truthy attributes to boolean, etc
28        grokText: true, // convert truthy text/attr to boolean, etc
29        normalize: true, // collapse multiple spaces to single space
30        xmlns: true, // include namespaces as attribute in output
31        namespaceKey: '_ns', // tag name for namespace objects
32        textKey: '_text', // tag name for text nodes
33        valueKey: '_value', // tag name for attribute values
34        attrKey: '_attr', // tag for attr groups
35        cdataKey: '_cdata', // tag for cdata nodes (ignored if mergeCDATA is true)
36        attrsAsObject: true, // if false, key is used as prefix to name, set prefix to '' to merge children and attrs.
37        stripAttrPrefix: true, // remove namespace prefixes from attributes
38        stripElemPrefix: true, // for elements of same name in diff namespaces, you can enable namespaces and access the nskey property
39        childrenAsArray: true // force children into arrays
40    };
41
42    var prefixMatch = new RegExp(/(?!xmlns)^.*:/);
43    var trimMatch = new RegExp(/^\s+|\s+$/g);
44
45    this.grokType = function (sValue) {
46        if (/^\s*$/.test(sValue)) {
47            return null;
48        }
49        if (/^(?:true|false)$/i.test(sValue)) {
50            return sValue.toLowerCase() === "true";
51        }
52        if (isFinite(sValue)) {
53            return parseFloat(sValue);
54        }
55        return sValue;
56    };
57
58    this.parseString = function (xmlString, opt) {
59        return this.parseXML(this.stringToXML(xmlString), opt);
60    }
61
62    this.parseXML = function (oXMLParent, opt) {
63
64        // initialize options
65        for (var key in opt) {
66            options[key] = opt[key];
67        }
68
69        var vResult = {},
70            nLength = 0,
71            sCollectedTxt = "";
72
73        // parse namespace information
74        if (options.xmlns && oXMLParent.namespaceURI) {
75            vResult[options.namespaceKey] = oXMLParent.namespaceURI;
76        }
77
78        // parse attributes
79        // using attributes property instead of hasAttributes method to support older browsers
80        if (oXMLParent.attributes && oXMLParent.attributes.length > 0) {
81            var vAttribs = {};
82
83            for (nLength; nLength < oXMLParent.attributes.length; nLength++) {
84                var oAttrib = oXMLParent.attributes.item(nLength);
85                vContent = {};
86                var attribName = '';
87
88                if (options.stripAttrPrefix) {
89                    attribName = oAttrib.name.replace(prefixMatch, '');
90
91                } else {
92                    attribName = oAttrib.name;
93                }
94
95                if (options.grokAttr) {
96                    vContent[options.valueKey] = this.grokType(oAttrib.value.replace(trimMatch, ''));
97                } else {
98                    vContent[options.valueKey] = oAttrib.value.replace(trimMatch, '');
99                }
100
101                if (options.xmlns && oAttrib.namespaceURI) {
102                    vContent[options.namespaceKey] = oAttrib.namespaceURI;
103                }
104
105                if (options.attrsAsObject) { // attributes with same local name must enable prefixes
106                    vAttribs[attribName] = vContent;
107                } else {
108                    vResult[options.attrKey + attribName] = vContent;
109                }
110            }
111
112            if (options.attrsAsObject) {
113                vResult[options.attrKey] = vAttribs;
114            } else {}
115        }
116
117        // iterate over the children
118        if (oXMLParent.hasChildNodes()) {
119            for (var oNode, sProp, vContent, nItem = 0; nItem < oXMLParent.childNodes.length; nItem++) {
120                oNode = oXMLParent.childNodes.item(nItem);
121
122                if (oNode.nodeType === 4) {
123                    if (options.mergeCDATA) {
124                        sCollectedTxt += oNode.nodeValue;
125                    } else {
126                        if (vResult.hasOwnProperty(options.cdataKey)) {
127                            if (vResult[options.cdataKey].constructor !== Array) {
128                                vResult[options.cdataKey] = [vResult[options.cdataKey]];
129                            }
130                            vResult[options.cdataKey].push(oNode.nodeValue);
131
132                        } else {
133                            if (options.childrenAsArray) {
134                                vResult[options.cdataKey] = [];
135                                vResult[options.cdataKey].push(oNode.nodeValue);
136                            } else {
137                                vResult[options.cdataKey] = oNode.nodeValue;
138                            }
139                        }
140                    }
141                } /* nodeType is "CDATASection" (4) */
142                else if (oNode.nodeType === 3) {
143                    sCollectedTxt += oNode.nodeValue;
144                } /* nodeType is "Text" (3) */
145                else if (oNode.nodeType === 1) { /* nodeType is "Element" (1) */
146
147                    if (nLength === 0) {
148                        vResult = {};
149                    }
150
151                    // using nodeName to support browser (IE) implementation with no 'localName' property
152                    if (options.stripElemPrefix) {
153                        sProp = oNode.nodeName.replace(prefixMatch, '');
154                    } else {
155                        sProp = oNode.nodeName;
156                    }
157
158                    vContent = xmlToJSON.parseXML(oNode);
159
160                    if (vResult.hasOwnProperty(sProp)) {
161                        if (vResult[sProp].constructor !== Array) {
162                            vResult[sProp] = [vResult[sProp]];
163                        }
164                        vResult[sProp].push(vContent);
165
166                    } else {
167                        if (options.childrenAsArray) {
168                            vResult[sProp] = [];
169                            vResult[sProp].push(vContent);
170                        } else {
171                            vResult[sProp] = vContent;
172                        }
173                        nLength++;
174                    }
175                }
176            }
177        } else if (!sCollectedTxt) { // no children and no text, return null
178            if (options.childrenAsArray) {
179                vResult[options.textKey] = [];
180                vResult[options.textKey].push(null);
181            } else {
182                vResult[options.textKey] = null;
183            }
184        }
185
186        if (sCollectedTxt) {
187            if (options.grokText) {
188                var value = this.grokType(sCollectedTxt.replace(trimMatch, ''));
189                if (value !== null && value !== undefined) {
190                    vResult[options.textKey] = value;
191                }
192            } else if (options.normalize) {
193                vResult[options.textKey] = sCollectedTxt.replace(trimMatch, '').replace(/\s+/g, " ");
194            } else {
195                vResult[options.textKey] = sCollectedTxt.replace(trimMatch, '');
196            }
197        }
198
199        return vResult;
200    }
201
202
203    // Convert xmlDocument to a string
204    // Returns null on failure
205    this.xmlToString = function (xmlDoc) {
206        try {
207            var xmlString = xmlDoc.xml ? xmlDoc.xml : (new XMLSerializer()).serializeToString(xmlDoc);
208            return xmlString;
209        } catch (err) {
210            return null;
211        }
212    }
213
214    // Convert a string to XML Node Structure
215    // Returns null on failure
216    this.stringToXML = function (xmlString) {
217        try {
218            var xmlDoc = null;
219
220            if (window.DOMParser) {
221
222                var parser = new DOMParser();
223                xmlDoc = parser.parseFromString(xmlString, "text/xml");
224
225                return xmlDoc;
226            } else {
227                xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
228                xmlDoc.async = false;
229                xmlDoc.loadXML(xmlString);
230
231                return xmlDoc;
232            }
233        } catch (e) {
234            return null;
235        }
236    }
237
238    return this;
239}).call({});
240
241if (typeof module != "undefined" && module !== null && module.exports) module.exports = xmlToJSON;
242else if (typeof define === "function" && define.amd) define(function() {return xmlToJSON});

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.