corrade-nucleus-nucleons – Blame information for rev 21

Subversion Repositories:
Rev:
Rev Author Line No. Line
21 office 1 /*
2 Copyright 2015 Axinom
3 Copyright 2011-2013 Abdulla Abdurakhmanov
4 Original sources are available at https://code.google.com/p/x2js/
5  
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
9  
10 http://www.apache.org/licenses/LICENSE-2.0
11  
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License for the specific language governing permissions and
16 limitations under the License.
17 */
18  
19 /*
20 Supported export methods:
21 * AMD
22 * <script> (window.X2JS)
23 * Node.js
24  
25 Limitations:
26 * Attribute namespace prefixes are not parsed as such.
27 * Overall the serialization/deserializaton code is "best effort" and not foolproof.
28 */
29  
30 // Module definition pattern used is returnExports from https://github.com/umdjs/umd
31 (function (root, factory) {
32 "use strict";
33  
34 /* global define */
35 if (typeof define === 'function' && define.amd) {
36 // AMD. Register as an anonymous module.
37 define([], factory);
38 } else if (typeof module === 'object' && module.exports) {
39 // Node. Does not work with strict CommonJS, but only CommonJS-like
40 // environments that support module.exports, like Node.
41 module.exports = factory(require("xmldom").DOMParser);
42 } else {
43 // Browser globals (root is window)
44 root.X2JS = factory();
45 }
46 })(this, function (CustomDOMParser) {
47 "use strict";
48  
49 // We return a constructor that can be used to make X2JS instances.
50 return function X2JS(config) {
51 var VERSION = "3.1.1";
52  
53 config = config || {};
54  
55 function initConfigDefaults() {
56 // If set to "property" then <element>_asArray will be created
57 // to allow you to access any element as an array (even if there is only one of it).
58 config.arrayAccessForm = config.arrayAccessForm || "none";
59  
60 // If "text" then <empty></empty> will be transformed to "".
61 // If "object" then <empty></empty> will be transformed to {}.
62 config.emptyNodeForm = config.emptyNodeForm || "text";
63  
64 // Allows attribute values to be converted on the fly during parsing to objects.
65 // "test": function(name, value) { return true; }
66 // "convert": function(name, value) { return parseFloat(value);
67 // convert() will be called for every attribute where test() returns true
68 // and the return value from convert() will replace the original value of the attribute.
69 config.attributeConverters = config.attributeConverters || [];
70  
71 // Any elements that match the paths here will have their text parsed
72 // as an XML datetime value (2011-11-12T13:00:00-07:00 style).
73 // The path can be a plain string (parent.child1.child2),
74 // a regex (/.*\.child2/) or function(elementPath).
75 config.datetimeAccessFormPaths = config.datetimeAccessFormPaths || [];
76  
77 // Any elements that match the paths listed here will be stored in JavaScript objects
78 // as arrays even if there is only one of them. The path can be a plain string
79 // (parent.child1.child2), a regex (/.*\.child2/) or function(elementName, elementPath).
80 config.arrayAccessFormPaths = config.arrayAccessFormPaths || [];
81  
82 // If true, a toString function is generated to print nodes containing text or cdata.
83 // Useful if you want to accept both plain text and CData as equivalent inputs.
84 if (config.enableToStringFunc === undefined) {
85 config.enableToStringFunc = true;
86 }
87  
88 // If true, empty text tags are ignored for elements with child nodes.
89 if (config.skipEmptyTextNodesForObj === undefined) {
90 config.skipEmptyTextNodesForObj = true;
91 }
92  
93 // If true, whitespace is trimmed from text nodes.
94 if (config.stripWhitespaces === undefined) {
95 config.stripWhitespaces = true;
96 }
97  
98 // If true, double quotes are used in generated XML.
99 if (config.useDoubleQuotes === undefined) {
100 config.useDoubleQuotes = true;
101 }
102  
103 // If true, the root element of the XML document is ignored when converting to objects.
104 // The result will directly have the root element's children as its own properties.
105 if (config.ignoreRoot === undefined) {
106 config.ignoreRoot = false;
107 }
108  
109 // Whether XML characters in text are escaped when reading/writing XML.
110 if (config.escapeMode === undefined) {
111 config.escapeMode = true;
112 }
113  
114 // Prefix to use for properties that are created to represent XML attributes.
115 if (config.attributePrefix === undefined) {
116 config.attributePrefix = "_";
117 }
118  
119 // If true, empty elements will created as self closing elements (<element />)
120 // If false, empty elements will be created with start and end tags (<element></element>)
121 if (config.selfClosingElements === undefined) {
122 config.selfClosingElements = true;
123 }
124  
125 // If this property defined as false and an XML element has CData node ONLY, it will be converted to text without additional property "__cdata"
126 if (config.keepCData === undefined) {
127 config.keepCData = false;
128 }
129 }
130  
131 function initRequiredPolyfills() {
132 function pad(number) {
133 var r = String(number);
134 if (r.length === 1) {
135 r = '0' + r;
136 }
137 return r;
138 }
139 // Hello IE8-
140 if (typeof String.prototype.trim !== 'function') {
141 String.prototype.trim = function trim() {
142 return this.replace(/^\s+|^\n+|(\s|\n)+$/g, '');
143 };
144 }
145 if (typeof Date.prototype.toISOString !== 'function') {
146 // Implementation from http://stackoverflow.com/questions/2573521/how-do-i-output-an-iso-8601-formatted-string-in-javascript
147 Date.prototype.toISOString = function toISOString() {
148 var MS_IN_S = 1000;
149  
150 return this.getUTCFullYear()
151 + '-' + pad(this.getUTCMonth() + 1)
152 + '-' + pad(this.getUTCDate())
153 + 'T' + pad(this.getUTCHours())
154 + ':' + pad(this.getUTCMinutes())
155 + ':' + pad(this.getUTCSeconds())
156 + '.' + String((this.getUTCMilliseconds() / MS_IN_S).toFixed(3)).slice(2, 5)
157 + 'Z';
158 };
159 }
160 }
161  
162 initConfigDefaults();
163 initRequiredPolyfills();
164  
165 var DOMNodeTypes = {
166 "ELEMENT_NODE": 1,
167 "TEXT_NODE": 3,
168 "CDATA_SECTION_NODE": 4,
169 "COMMENT_NODE": 8,
170 "DOCUMENT_NODE": 9
171 };
172  
173 function getDomNodeLocalName(domNode) {
174 var localName = domNode.localName;
175 if (localName == null) {
176 // Yeah, this is IE!!
177 localName = domNode.baseName;
178 }
179 if (localName == null || localName === "") {
180 // ==="" is IE too
181 localName = domNode.nodeName;
182 }
183 return localName;
184 }
185  
186 function getDomNodeNamespacePrefix(node) {
187 return node.prefix;
188 }
189  
190 function escapeXmlChars(str) {
191 if (typeof str === "string")
192 return str.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '&quot;').replace(/'/g, '&#x27;');
193 else
194 return str;
195 }
196  
197 function unescapeXmlChars(str) {
198 return str.replace(/&lt;/g, '<').replace(/&gt;/g, '>').replace(/&quot;/g, '"').replace(/&#x27;/g, "'").replace(/&amp;/g, '&');
199 }
200  
201 function ensureProperArrayAccessForm(element, childName, elementPath) {
202 switch (config.arrayAccessForm) {
203 case "property":
204 if (!(element[childName] instanceof Array))
205 element[childName + "_asArray"] = [element[childName]];
206 else
207 element[childName + "_asArray"] = element[childName];
208 break;
209 }
210  
211 if (!(element[childName] instanceof Array) && config.arrayAccessFormPaths.length > 0) {
212 var match = false;
213  
214 for (var i = 0; i < config.arrayAccessFormPaths.length; i++) {
215 var arrayPath = config.arrayAccessFormPaths[i];
216 if (typeof arrayPath === "string") {
217 if (arrayPath === elementPath) {
218 match = true;
219 break;
220 }
221 } else if (arrayPath instanceof RegExp) {
222 if (arrayPath.test(elementPath)) {
223 match = true;
224 break;
225 }
226 } else if (typeof arrayPath === "function") {
227 if (arrayPath(childName, elementPath)) {
228 match = true;
229 break;
230 }
231 }
232 }
233  
234 if (match)
235 element[childName] = [element[childName]];
236 }
237 }
238  
239 function xmlDateTimeToDate(prop) {
240 // Implementation based up on http://stackoverflow.com/questions/8178598/xml-datetime-to-javascript-date-object
241 // Improved to support full spec and optional parts
242 var MINUTES_PER_HOUR = 60;
243  
244 var bits = prop.split(/[-T:+Z]/g);
245  
246 var d = new Date(bits[0], bits[1] - 1, bits[2]);
247 var secondBits = bits[5].split("\.");
248 d.setHours(bits[3], bits[4], secondBits[0]);
249 if (secondBits.length > 1)
250 d.setMilliseconds(secondBits[1]);
251  
252 // Get supplied time zone offset in minutes
253 if (bits[6] && bits[7]) {
254 var offsetMinutes = bits[6] * MINUTES_PER_HOUR + Number(bits[7]);
255 var sign = /\d\d-\d\d:\d\d$/.test(prop) ? '-' : '+';
256  
257 // Apply the sign
258 offsetMinutes = 0 + (sign === '-' ? -1 * offsetMinutes : offsetMinutes);
259  
260 // Apply offset and local timezone
261 d.setMinutes(d.getMinutes() - offsetMinutes - d.getTimezoneOffset());
262 } else if (prop.indexOf("Z", prop.length - 1) !== -1) {
263 d = new Date(Date.UTC(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours(), d.getMinutes(), d.getSeconds(), d.getMilliseconds()));
264 }
265  
266 // d is now a local time equivalent to the supplied time
267 return d;
268 }
269  
270 function convertToDateIfRequired(value, childName, fullPath) {
271 if (config.datetimeAccessFormPaths.length > 0) {
272 var pathWithoutTextNode = fullPath.split("\.#")[0];
273  
274 for (var i = 0; i < config.datetimeAccessFormPaths.length; i++) {
275 var candidatePath = config.datetimeAccessFormPaths[i];
276 if (typeof candidatePath === "string") {
277 if (candidatePath === pathWithoutTextNode)
278 return xmlDateTimeToDate(value);
279 } else if (candidatePath instanceof RegExp) {
280 if (candidatePath.test(pathWithoutTextNode))
281 return xmlDateTimeToDate(value);
282 } else if (typeof candidatePath === "function") {
283 if (candidatePath(pathWithoutTextNode))
284 return xmlDateTimeToDate(value);
285 }
286 }
287 }
288  
289 return value;
290 }
291  
292 function deserializeRootElementChildren(rootElement) {
293 var result = {};
294 var children = rootElement.childNodes;
295  
296 // Alternative for firstElementChild which is not supported in some environments
297 for (var i = 0; i < children.length; i++) {
298 var child = children.item(i);
299 if (child.nodeType === DOMNodeTypes.ELEMENT_NODE) {
300 var childName = getDomNodeLocalName(child);
301  
302 if (config.ignoreRoot)
303 result = deserializeDomChildren(child, childName);
304 else
305 result[childName] = deserializeDomChildren(child, childName);
306 }
307 }
308  
309 return result;
310 }
311  
312 function deserializeElementChildren(element, elementPath) {
313 var result = {};
314 result.__cnt = 0;
315  
316 var nodeChildren = element.childNodes;
317  
318 // Child nodes.
319 for (var iChild = 0; iChild < nodeChildren.length; iChild++) {
320 var child = nodeChildren.item(iChild);
321 var childName = getDomNodeLocalName(child);
322  
323 if (child.nodeType === DOMNodeTypes.COMMENT_NODE)
324 continue;
325  
326 result.__cnt++;
327  
328 // We deliberately do not accept everything falsey here because
329 // elements that resolve to empty string should still be preserved.
330 if (result[childName] == null) {
331 result[childName] = deserializeDomChildren(child, elementPath + "." + childName);
332 ensureProperArrayAccessForm(result, childName, elementPath + "." + childName);
333 } else {
334 if (!(result[childName] instanceof Array)) {
335 result[childName] = [result[childName]];
336 ensureProperArrayAccessForm(result, childName, elementPath + "." + childName);
337 }
338  
339 result[childName][result[childName].length] = deserializeDomChildren(child, elementPath + "." + childName);
340 }
341 }
342  
343 // Attributes
344 for (var iAttribute = 0; iAttribute < element.attributes.length; iAttribute++) {
345 var attribute = element.attributes.item(iAttribute);
346 result.__cnt++;
347  
348 var adjustedValue = attribute.value;
349 for (var iConverter = 0; iConverter < config.attributeConverters.length; iConverter++) {
350 var converter = config.attributeConverters[iConverter];
351 if (converter.test.call(null, attribute.name, attribute.value))
352 adjustedValue = converter.convert.call(null, attribute.name, attribute.value);
353 }
354  
355 result[config.attributePrefix + attribute.name] = adjustedValue;
356 }
357  
358 // Node namespace prefix
359 var namespacePrefix = getDomNodeNamespacePrefix(element);
360 if (namespacePrefix) {
361 result.__cnt++;
362 result.__prefix = namespacePrefix;
363 }
364  
365 if (result["#text"]) {
366 result.__text = result["#text"];
367  
368 if (result.__text instanceof Array) {
369 result.__text = result.__text.join("\n");
370 }
371  
372 if (config.escapeMode)
373 result.__text = unescapeXmlChars(result.__text);
374  
375 if (config.stripWhitespaces)
376 result.__text = result.__text.trim();
377  
378 delete result["#text"];
379  
380 if (config.arrayAccessForm === "property")
381 delete result["#text_asArray"];
382  
383 result.__text = convertToDateIfRequired(result.__text, "#text", elementPath + ".#text");
384 }
385  
386 if (result.hasOwnProperty('#cdata-section')) {
387 result.__cdata = result["#cdata-section"];
388 delete result["#cdata-section"];
389  
390 if (config.arrayAccessForm === "property")
391 delete result["#cdata-section_asArray"];
392 }
393  
394 if (result.__cnt === 1 && result.__text) {
395 result = result.__text;
396 } else if (result.__cnt === 0 && config.emptyNodeForm === "text") {
397 result = '';
398 } else if (result.__cnt > 1 && result.__text !== undefined && config.skipEmptyTextNodesForObj) {
399 if (config.stripWhitespaces && result.__text === "" || result.__text.trim() === "") {
400 delete result.__text;
401 }
402 }
403 delete result.__cnt;
404  
405 if (!config.keepCData && (!result.hasOwnProperty('__text') && result.hasOwnProperty('__cdata'))) {
406 return (result.__cdata ? result.__cdata : '');
407 }
408  
409 if (config.enableToStringFunc && (result.__text || result.__cdata)) {
410 result.toString = function toString() {
411 return (this.__text ? this.__text : '') + (this.__cdata ? this.__cdata : '');
412 };
413 }
414  
415 return result;
416 }
417  
418 function deserializeDomChildren(node, parentPath) {
419 if (node.nodeType === DOMNodeTypes.DOCUMENT_NODE) {
420 return deserializeRootElementChildren(node);
421 } else if (node.nodeType === DOMNodeTypes.ELEMENT_NODE) {
422 return deserializeElementChildren(node, parentPath);
423 } else if (node.nodeType === DOMNodeTypes.TEXT_NODE || node.nodeType === DOMNodeTypes.CDATA_SECTION_NODE) {
424 return node.nodeValue;
425 } else {
426 return null;
427 }
428 }
429  
430 function serializeStartTag(jsObject, elementName, attributeNames, selfClosing) {
431 var resultStr = "<" + ((jsObject && jsObject.__prefix) ? (jsObject.__prefix + ":") : "") + elementName;
432  
433 if (attributeNames) {
434 for (var i = 0; i < attributeNames.length; i++) {
435 var attributeName = attributeNames[i];
436 var attributeValue = jsObject[attributeName];
437  
438 if (config.escapeMode)
439 attributeValue = escapeXmlChars(attributeValue);
440  
441 resultStr += " " + attributeName.substr(config.attributePrefix.length) + "=";
442  
443 if (config.useDoubleQuotes)
444 resultStr += '"' + attributeValue + '"';
445 else
446 resultStr += "'" + attributeValue + "'";
447 }
448 }
449  
450 if (!selfClosing)
451 resultStr += ">";
452 else
453 resultStr += " />";
454  
455 return resultStr;
456 }
457  
458 function serializeEndTag(jsObject, elementName) {
459 return "" + ((jsObject && jsObject.__prefix) ? (jsObject.__prefix + ":") : "") + elementName + ">";
460 }
461  
462 function endsWith(str, suffix) {
463 return str.indexOf(suffix, str.length - suffix.length) !== -1;
464 }
465  
466 function isSpecialProperty(jsonObj, propertyName) {
467 if ((config.arrayAccessForm === "property" && endsWith(propertyName.toString(), ("_asArray")))
468 || propertyName.toString().indexOf(config.attributePrefix) === 0
469 || propertyName.toString().indexOf("__") === 0
470 || (jsonObj[propertyName] instanceof Function))
471 return true;
472 else
473 return false;
474 }
475  
476 function getDataElementCount(jsObject) {
477 var count = 0;
478  
479 if (jsObject instanceof Object) {
480 for (var propertyName in jsObject) {
481 if (isSpecialProperty(jsObject, propertyName))
482 continue;
483  
484 count++;
485 }
486 }
487  
488 return count;
489 }
490  
491 function getDataAttributeNames(jsObject) {
492 var names = [];
493  
494 if (jsObject instanceof Object) {
495 for (var attributeName in jsObject) {
496 if (attributeName.toString().indexOf("__") === -1
497 && attributeName.toString().indexOf(config.attributePrefix) === 0) {
498 names.push(attributeName);
499 }
500 }
501 }
502  
503 return names;
504 }
505  
506 function serializeComplexTextNodeContents(textNode) {
507 var result = "";
508  
509 if (textNode.__cdata) {
510 result += "<![CDATA[" + textNode.__cdata + "]]>";
511 }
512  
513 if (textNode.__text) {
514 if (config.escapeMode)
515 result += escapeXmlChars(textNode.__text);
516 else
517 result += textNode.__text;
518 }
519  
520 return result;
521 }
522  
523 function serializeTextNodeContents(textNode) {
524 var result = "";
525  
526 if (textNode instanceof Object) {
527 result += serializeComplexTextNodeContents(textNode);
528 } else if (textNode !== null) {
529 if (config.escapeMode)
530 result += escapeXmlChars(textNode);
531 else
532 result += textNode;
533 }
534  
535 return result;
536 }
537  
538 function serializeArray(elementArray, elementName, attributes) {
539 var result = "";
540  
541 if (elementArray.length === 0) {
542 result += serializeStartTag(elementArray, elementName, attributes, true);
543 } else {
544 for (var i = 0; i < elementArray.length; i++) {
545 result += serializeJavaScriptObject(elementArray[i], elementName, getDataAttributeNames(elementArray[i]));
546 }
547 }
548  
549 return result;
550 }
551  
552 function serializeJavaScriptObject(element, elementName, attributes) {
553 var result = "";
554  
555 if ((element === undefined || element === null || element === '') && config.selfClosingElements) {
556 result += serializeStartTag(element, elementName, attributes, true);
557 } else if (typeof element === 'object') {
558 if (Object.prototype.toString.call(element) === '[object Array]') {
559 result += serializeArray(element, elementName, attributes);
560 } else if (element instanceof Date) {
561 result += serializeStartTag(element, elementName, attributes, false);
562 result += element.toISOString();
563 result += serializeEndTag(element, elementName);
564 } else {
565 var childElementCount = getDataElementCount(element);
566 if (childElementCount > 0 || element.__text || element.__cdata) {
567 result += serializeStartTag(element, elementName, attributes, false);
568 result += serializeJavaScriptObjectChildren(element);
569 result += serializeEndTag(element, elementName);
570 } else if (config.selfClosingElements) {
571 result += serializeStartTag(element, elementName, attributes, true);
572 } else {
573 result += serializeStartTag(element, elementName, attributes, false);
574 result += serializeEndTag(element, elementName);
575 }
576 }
577 } else {
578 result += serializeStartTag(element, elementName, attributes, false);
579 result += serializeTextNodeContents(element);
580 result += serializeEndTag(element, elementName);
581 }
582  
583 return result;
584 }
585  
586 function serializeJavaScriptObjectChildren(jsObject) {
587 var result = "";
588  
589 var elementCount = getDataElementCount(jsObject);
590  
591 if (elementCount > 0) {
592 for (var elementName in jsObject) {
593 if (isSpecialProperty(jsObject, elementName))
594 continue;
595  
596 var element = jsObject[elementName];
597 var attributes = getDataAttributeNames(element);
598  
599 result += serializeJavaScriptObject(element, elementName, attributes);
600 }
601 }
602  
603 result += serializeTextNodeContents(jsObject);
604  
605 return result;
606 }
607  
608 function parseXml(xml) {
609 if (xml === undefined) {
610 return null;
611 }
612  
613 if (typeof xml !== "string") {
614 return null;
615 }
616  
617 var parser = null;
618 var domNode = null;
619  
620 if (CustomDOMParser) {
621 // This branch is used for node.js, with the xmldom parser.
622 parser = new CustomDOMParser();
623  
624 domNode = parser.parseFromString(xml, "text/xml");
625 } else if (window && window.DOMParser) {
626 parser = new window.DOMParser();
627 var parsererrorNS = null;
628  
629 var isIEParser = window.ActiveXObject || "ActiveXObject" in window;
630  
631 // IE9+ now is here
632 if (!isIEParser) {
633 try {
634 parsererrorNS = parser.parseFromString("INVALID", "text/xml").childNodes[0].namespaceURI;
635 } catch (err) {
636 parsererrorNS = null;
637 }
638 }
639  
640 try {
641 domNode = parser.parseFromString(xml, "text/xml");
642 if (parsererrorNS !== null && domNode.getElementsByTagNameNS(parsererrorNS, "parsererror").length > 0) {
643 domNode = null;
644 }
645 } catch (err) {
646 domNode = null;
647 }
648 } else {
649 // IE :(
650 if (xml.indexOf("
651 ") + 2);
652
653  
654 * global ActiveXObject */
655 domNode = new ActiveXObject("Microsoft.XMLDOM");
656 domNode.async = "false";
657 domNode.loadXML(xml);
658 }
659  
660 return domNode;
661 }
662  
663 this.asArray = function asArray(prop) {
664 if (prop === undefined || prop === null) {
665 return [];
666 } else if (prop instanceof Array) {
667 return prop;
668 } else {
669 return [prop];
670 }
671 };
672  
673 this.toXmlDateTime = function toXmlDateTime(dt) {
674 if (dt instanceof Date) {
675 return dt.toISOString();
676 } else if (typeof (dt) === 'number') {
677 return new Date(dt).toISOString();
678 } else {
679 return null;
680 }
681 };
682  
683 this.asDateTime = function asDateTime(prop) {
684 if (typeof (prop) === "string") {
685 return xmlDateTimeToDate(prop);
686 } else {
687 return prop;
688 }
689 };
690  
691 /*
692 in a cycle:
693
694
695
696 /
697  
698 // Transformns an XML string into DOM-tree
699 this.xml2dom = function xml2dom(xml) {
700 return parseXml(xml);
701 };
702  
703 // Transforms a DOM tree to JavaScript objects.
704 this.dom2js = function dom2js(domNode) {
705 return deserializeDomChildren(domNode, null);
706 };
707  
708 // Transforms JavaScript objects to a DOM tree.
709 this.js2dom = function js2dom(jsObject) {
710 var xml = this.js2xml(jsObject);
711 return parseXml(xml);
712 };
713  
714 // Transformns an XML string into JavaScript objects.
715 this.xml2js = function xml2js(xml) {
716 var domNode = parseXml(xml);
717 if (domNode != null)
718 return this.dom2js(domNode);
719 else
720 return null;
721 };
722  
723 // Transforms JavaScript objects into an XML string.
724 this.js2xml = function js2xml(jsObject) {
725 return serializeJavaScriptObjectChildren(jsObject);
726 };
727  
728 this.getVersion = function getVersion() {
729 return VERSION;
730 };
731 };
732 });