corrade-nucleus-nucleons – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 /*
2 Copyright 2011-2013 Abdulla Abdurakhmanov
3 Original sources are available at https://code.google.com/p/x2js/
4  
5 Licensed under the Apache License, Version 2.0 (the "License");
6 you may not use this file except in compliance with the License.
7 You may obtain a copy of the License at
8  
9 http://www.apache.org/licenses/LICENSE-2.0
10  
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16 */
17  
18 (function (root, factory) {
19 if (typeof define === "function" && define.amd) {
20 define([], factory);
21 } else if (typeof exports === "object") {
22 module.exports = factory();
23 } else {
24 root.X2JS = factory();
25 }
26 }(this, function () {
27 return function (config) {
28 'use strict';
29  
30 var VERSION = "1.2.0";
31  
32 config = config || {};
33 initConfigDefaults();
34 initRequiredPolyfills();
35  
36 function initConfigDefaults() {
37 if(config.escapeMode === undefined) {
38 config.escapeMode = true;
39 }
40  
41 config.attributePrefix = config.attributePrefix || "_";
42 config.arrayAccessForm = config.arrayAccessForm || "none";
43 config.emptyNodeForm = config.emptyNodeForm || "text";
44  
45 if(config.enableToStringFunc === undefined) {
46 config.enableToStringFunc = true;
47 }
48 config.arrayAccessFormPaths = config.arrayAccessFormPaths || [];
49 if(config.skipEmptyTextNodesForObj === undefined) {
50 config.skipEmptyTextNodesForObj = true;
51 }
52 if(config.stripWhitespaces === undefined) {
53 config.stripWhitespaces = true;
54 }
55 config.datetimeAccessFormPaths = config.datetimeAccessFormPaths || [];
56  
57 if(config.useDoubleQuotes === undefined) {
58 config.useDoubleQuotes = false;
59 }
60  
61 config.xmlElementsFilter = config.xmlElementsFilter || [];
62 config.jsonPropertiesFilter = config.jsonPropertiesFilter || [];
63  
64 if(config.keepCData === undefined) {
65 config.keepCData = false;
66 }
67 }
68  
69 var DOMNodeTypes = {
70 ELEMENT_NODE : 1,
71 TEXT_NODE : 3,
72 CDATA_SECTION_NODE : 4,
73 COMMENT_NODE : 8,
74 DOCUMENT_NODE : 9
75 };
76  
77 function initRequiredPolyfills() {
78 }
79  
80 function getNodeLocalName( node ) {
81 var nodeLocalName = node.localName;
82 if(nodeLocalName == null) // Yeah, this is IE!!
83 nodeLocalName = node.baseName;
84 if(nodeLocalName == null || nodeLocalName=="") // =="" is IE too
85 nodeLocalName = node.nodeName;
86 return nodeLocalName;
87 }
88  
89 function getNodePrefix(node) {
90 return node.prefix;
91 }
92  
93 function escapeXmlChars(str) {
94 if(typeof(str) == "string")
95 return str.replace(/&/g, '&').replace(/g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''');
96 else
97 return str;
98 }
99  
100 function unescapeXmlChars(str) {
101 return str.replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, "'").replace(/&/g, '&');
102 }
103  
104 function checkInStdFiltersArrayForm(stdFiltersArrayForm, obj, name, path) {
105 var idx = 0;
106 for(; idx < stdFiltersArrayForm.length; idx++) {
107 var filterPath = stdFiltersArrayForm[idx];
108 if( typeof filterPath === "string" ) {
109 if(filterPath == path)
110 break;
111 }
112 else
113 if( filterPath instanceof RegExp) {
114 if(filterPath.test(path))
115 break;
116 }
117 else
118 if( typeof filterPath === "function") {
119 if(filterPath(obj, name, path))
120 break;
121 }
122 }
123 return idx!=stdFiltersArrayForm.length;
124 }
125  
126 function toArrayAccessForm(obj, childName, path) {
127 switch(config.arrayAccessForm) {
128 case "property":
129 if(!(obj[childName] instanceof Array))
130 obj[childName+"_asArray"] = [obj[childName]];
131 else
132 obj[childName+"_asArray"] = obj[childName];
133 break;
134 /*case "none":
135 break;*/
136 }
137  
138 if(!(obj[childName] instanceof Array) && config.arrayAccessFormPaths.length > 0) {
139 if(checkInStdFiltersArrayForm(config.arrayAccessFormPaths, obj, childName, path)) {
140 obj[childName] = [obj[childName]];
141 }
142 }
143 }
144  
145 function fromXmlDateTime(prop) {
146 // Implementation based up on http://stackoverflow.com/questions/8178598/xml-datetime-to-javascript-date-object
147 // Improved to support full spec and optional parts
148 var bits = prop.split(/[-T:+Z]/g);
149  
150 var d = new Date(bits[0], bits[1]-1, bits[2]);
151 var secondBits = bits[5].split("\.");
152 d.setHours(bits[3], bits[4], secondBits[0]);
153 if(secondBits.length>1)
154 d.setMilliseconds(secondBits[1]);
155  
156 // Get supplied time zone offset in minutes
157 if(bits[6] && bits[7]) {
158 var offsetMinutes = bits[6] * 60 + Number(bits[7]);
159 var sign = /\d\d-\d\d:\d\d$/.test(prop)? '-' : '+';
160  
161 // Apply the sign
162 offsetMinutes = 0 + (sign == '-'? -1 * offsetMinutes : offsetMinutes);
163  
164 // Apply offset and local timezone
165 d.setMinutes(d.getMinutes() - offsetMinutes - d.getTimezoneOffset())
166 }
167 else
168 if(prop.indexOf("Z", prop.length - 1) !== -1) {
169 d = new Date(Date.UTC(d.getFullYear(), d.getMonth(), d.getDate(), d.getHours(), d.getMinutes(), d.getSeconds(), d.getMilliseconds()));
170 }
171  
172 // d is now a local time equivalent to the supplied time
173 return d;
174 }
175  
176 function checkFromXmlDateTimePaths(value, childName, fullPath) {
177 if(config.datetimeAccessFormPaths.length > 0) {
178 var path = fullPath.split("\.#")[0];
179 if(checkInStdFiltersArrayForm(config.datetimeAccessFormPaths, value, childName, path)) {
180 return fromXmlDateTime(value);
181 }
182 else
183 return value;
184 }
185 else
186 return value;
187 }
188  
189 function checkXmlElementsFilter(obj, childType, childName, childPath) {
190 if( childType == DOMNodeTypes.ELEMENT_NODE && config.xmlElementsFilter.length > 0) {
191 return checkInStdFiltersArrayForm(config.xmlElementsFilter, obj, childName, childPath);
192 }
193 else
194 return true;
195 }
196  
197 function parseDOMChildren( node, path ) {
198 if(node.nodeType == DOMNodeTypes.DOCUMENT_NODE) {
199 var result = new Object;
200 var nodeChildren = node.childNodes;
201 // Alternative for firstElementChild which is not supported in some environments
202 for(var cidx=0; cidx <nodeChildren.length; cidx++) {
203 var child = nodeChildren.item(cidx);
204 if(child.nodeType == DOMNodeTypes.ELEMENT_NODE) {
205 var childName = getNodeLocalName(child);
206 result[childName] = parseDOMChildren(child, childName);
207 }
208 }
209 return result;
210 }
211 else
212 if(node.nodeType == DOMNodeTypes.ELEMENT_NODE) {
213 var result = new Object;
214 result.__cnt=0;
215  
216 var nodeChildren = node.childNodes;
217  
218 // Children nodes
219 for(var cidx=0; cidx <nodeChildren.length; cidx++) {
220 var child = nodeChildren.item(cidx); // nodeChildren[cidx];
221 var childName = getNodeLocalName(child);
222  
223 if(child.nodeType!= DOMNodeTypes.COMMENT_NODE) {
224 var childPath = path+"."+childName;
225 if (checkXmlElementsFilter(result,child.nodeType,childName,childPath)) {
226 result.__cnt++;
227 if(result[childName] == null) {
228 result[childName] = parseDOMChildren(child, childPath);
229 toArrayAccessForm(result, childName, childPath);
230 }
231 else {
232 if(result[childName] != null) {
233 if( !(result[childName] instanceof Array)) {
234 result[childName] = [result[childName]];
235 toArrayAccessForm(result, childName, childPath);
236 }
237 }
238 (result[childName])[result[childName].length] = parseDOMChildren(child, childPath);
239 }
240 }
241 }
242 }
243  
244 // Attributes
245 for(var aidx=0; aidx <node.attributes.length; aidx++) {
246 var attr = node.attributes.item(aidx); // [aidx];
247 result.__cnt++;
248 result[config.attributePrefix+attr.name]=attr.value;
249 }
250  
251 // Node namespace prefix
252 var nodePrefix = getNodePrefix(node);
253 if(nodePrefix!=null && nodePrefix!="") {
254 result.__cnt++;
255 result.__prefix=nodePrefix;
256 }
257  
258 if(result["#text"]!=null) {
259 result.__text = result["#text"];
260 if(result.__text instanceof Array) {
261 result.__text = result.__text.join("\n");
262 }
263 //if(config.escapeMode)
264 // result.__text = unescapeXmlChars(result.__text);
265 if(config.stripWhitespaces)
266 result.__text = result.__text.trim();
267 delete result["#text"];
268 if(config.arrayAccessForm=="property")
269 delete result["#text_asArray"];
270 result.__text = checkFromXmlDateTimePaths(result.__text, childName, path+"."+childName);
271 }
272 if(result["#cdata-section"]!=null) {
273 result.__cdata = result["#cdata-section"];
274 delete result["#cdata-section"];
275 if(config.arrayAccessForm=="property")
276 delete result["#cdata-section_asArray"];
277 }
278  
279 if( result.__cnt == 0 && config.emptyNodeForm=="text" ) {
280 result = '';
281 }
282 else
283 if( result.__cnt == 1 && result.__text!=null ) {
284 result = result.__text;
285 }
286 else
287 if( result.__cnt == 1 && result.__cdata!=null && !config.keepCData ) {
288 result = result.__cdata;
289 }
290 else
291 if ( result.__cnt > 1 && result.__text!=null && config.skipEmptyTextNodesForObj) {
292 if( (config.stripWhitespaces && result.__text=="") || (result.__text.trim()=="")) {
293 delete result.__text;
294 }
295 }
296 delete result.__cnt;
297  
298 if( config.enableToStringFunc && (result.__text!=null || result.__cdata!=null )) {
299 result.toString = function() {
300 return (this.__text!=null? this.__text:'')+( this.__cdata!=null ? this.__cdata:'');
301 };
302 }
303  
304 return result;
305 }
306 else
307 if(node.nodeType == DOMNodeTypes.TEXT_NODE || node.nodeType == DOMNodeTypes.CDATA_SECTION_NODE) {
308 return node.nodeValue;
309 }
310 }
311  
312 function startTag(jsonObj, element, attrList, closed) {
313 var resultStr = "<"+ ( (jsonObj!=null && jsonObj.__prefix!=null)? (jsonObj.__prefix+":"):"") + element;
314 if(attrList!=null) {
315 for(var aidx = 0; aidx < attrList.length; aidx++) {
316 var attrName = attrList[aidx];
317 var attrVal = jsonObj[attrName];
318 if(config.escapeMode)
319 attrVal=escapeXmlChars(attrVal);
320 resultStr+=" "+attrName.substr(config.attributePrefix.length)+"=";
321 if(config.useDoubleQuotes)
322 resultStr+='"'+attrVal+'"';
323 else
324 resultStr+="'"+attrVal+"'";
325 }
326 }
327 if(!closed)
328 resultStr+=">";
329 else
330 resultStr+="/>";
331 return resultStr;
332 }
333  
334 function endTag(jsonObj,elementName) {
335 return "</"+ (jsonObj.__prefix!=null? (jsonObj.__prefix+":"):"")+elementName+">";
336 }
337  
338 function endsWith(str, suffix) {
339 return str.indexOf(suffix, str.length - suffix.length) !== -1;
340 }
341  
342 function jsonXmlSpecialElem ( jsonObj, jsonObjField ) {
343 if((config.arrayAccessForm=="property" && endsWith(jsonObjField.toString(),("_asArray")))
344 || jsonObjField.toString().indexOf(config.attributePrefix)==0
345 || jsonObjField.toString().indexOf("__")==0
346 || (jsonObj[jsonObjField] instanceof Function) )
347 return true;
348 else
349 return false;
350 }
351  
352 function jsonXmlElemCount ( jsonObj ) {
353 var elementsCnt = 0;
354 if(jsonObj instanceof Object ) {
355 for( var it in jsonObj ) {
356 if(jsonXmlSpecialElem ( jsonObj, it) )
357 continue;
358 elementsCnt++;
359 }
360 }
361 return elementsCnt;
362 }
363  
364 function checkJsonObjPropertiesFilter(jsonObj, propertyName, jsonObjPath) {
365 return config.jsonPropertiesFilter.length == 0
366 || jsonObjPath==""
367 || checkInStdFiltersArrayForm(config.jsonPropertiesFilter, jsonObj, propertyName, jsonObjPath);
368 }
369  
370 function parseJSONAttributes ( jsonObj ) {
371 var attrList = [];
372 if(jsonObj instanceof Object ) {
373 for( var ait in jsonObj ) {
374 if(ait.toString().indexOf("__")== -1 && ait.toString().indexOf(config.attributePrefix)==0) {
375 attrList.push(ait);
376 }
377 }
378 }
379 return attrList;
380 }
381  
382 function parseJSONTextAttrs ( jsonTxtObj ) {
383 var result ="";
384  
385 if(jsonTxtObj.__cdata!=null) {
386 result+="<![CDATA["+jsonTxtObj.__cdata+"]]>";
387 }
388  
389 if(jsonTxtObj.__text!=null) {
390 if(config.escapeMode)
391 result+=escapeXmlChars(jsonTxtObj.__text);
392 else
393 result+=jsonTxtObj.__text;
394 }
395 return result;
396 }
397  
398 function parseJSONTextObject ( jsonTxtObj ) {
399 var result ="";
400  
401 if( jsonTxtObj instanceof Object ) {
402 result+=parseJSONTextAttrs ( jsonTxtObj );
403 }
404 else
405 if(jsonTxtObj!=null) {
406 if(config.escapeMode)
407 result+=escapeXmlChars(jsonTxtObj);
408 else
409 result+=jsonTxtObj;
410 }
411  
412 return result;
413 }
414  
415 function getJsonPropertyPath(jsonObjPath, jsonPropName) {
416 if (jsonObjPath==="") {
417 return jsonPropName;
418 }
419 else
420 return jsonObjPath+"."+jsonPropName;
421 }
422  
423 function parseJSONArray ( jsonArrRoot, jsonArrObj, attrList, jsonObjPath ) {
424 var result = "";
425 if(jsonArrRoot.length == 0) {
426 result+=startTag(jsonArrRoot, jsonArrObj, attrList, true);
427 }
428 else {
429 for(var arIdx = 0; arIdx < jsonArrRoot.length; arIdx++) {
430 result+=startTag(jsonArrRoot[arIdx], jsonArrObj, parseJSONAttributes(jsonArrRoot[arIdx]), false);
431 result+=parseJSONObject(jsonArrRoot[arIdx], getJsonPropertyPath(jsonObjPath,jsonArrObj));
432 result+=endTag(jsonArrRoot[arIdx],jsonArrObj);
433 }
434 }
435 return result;
436 }
437  
438 function parseJSONObject ( jsonObj, jsonObjPath ) {
439 var result = "";
440  
441 var elementsCnt = jsonXmlElemCount ( jsonObj );
442  
443 if(elementsCnt > 0) {
444 for( var it in jsonObj ) {
445  
446 if(jsonXmlSpecialElem ( jsonObj, it) || (jsonObjPath!="" && !checkJsonObjPropertiesFilter(jsonObj, it, getJsonPropertyPath(jsonObjPath,it))) )
447 continue;
448  
449 var subObj = jsonObj[it];
450  
451 var attrList = parseJSONAttributes( subObj )
452  
453 if(subObj == null || subObj == undefined) {
454 result+=startTag(subObj, it, attrList, true);
455 }
456 else
457 if(subObj instanceof Object) {
458  
459 if(subObj instanceof Array) {
460 result+=parseJSONArray( subObj, it, attrList, jsonObjPath );
461 }
462 else if(subObj instanceof Date) {
463 result+=startTag(subObj, it, attrList, false);
464 result+=subObj.toISOString();
465 result+=endTag(subObj,it);
466 }
467 else {
468 var subObjElementsCnt = jsonXmlElemCount ( subObj );
469 if(subObjElementsCnt > 0 || subObj.__text!=null || subObj.__cdata!=null) {
470 result+=startTag(subObj, it, attrList, false);
471 result+=parseJSONObject(subObj, getJsonPropertyPath(jsonObjPath,it));
472 result+=endTag(subObj,it);
473 }
474 else {
475 result+=startTag(subObj, it, attrList, true);
476 }
477 }
478 }
479 else {
480 result+=startTag(subObj, it, attrList, false);
481 result+=parseJSONTextObject(subObj);
482 result+=endTag(subObj,it);
483 }
484 }
485 }
486 result+=parseJSONTextObject(jsonObj);
487  
488 return result;
489 }
490  
491 this.parseXmlString = function(xmlDocStr) {
492 var isIEParser = window.ActiveXObject || "ActiveXObject" in window;
493 if (xmlDocStr === undefined) {
494 return null;
495 }
496 var xmlDoc;
497 if (window.DOMParser) {
498 var parser=new window.DOMParser();
499 var parsererrorNS = null;
500 // IE9+ now is here
501 if(!isIEParser) {
502 try {
503 parsererrorNS = parser.parseFromString("INVALID", "text/xml").getElementsByTagName("parsererror")[0].namespaceURI;
504 }
505 catch(err) {
506 parsererrorNS = null;
507 }
508 }
509 try {
510 xmlDoc = parser.parseFromString( xmlDocStr, "text/xml" );
511 if( parsererrorNS!= null && xmlDoc.getElementsByTagNameNS(parsererrorNS, "parsererror").length > 0) {
512 //throw new Error('Error parsing XML: '+xmlDocStr);
513 xmlDoc = null;
514 }
515 }
516 catch(err) {
517 xmlDoc = null;
518 }
519 }
520 else {
521 // IE :(
522 if(xmlDocStr.indexOf("<?")==0) {
523 xmlDocStr = xmlDocStr.substr( xmlDocStr.indexOf("?>") + 2 );
524 }
525 xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
526 xmlDoc.async="false";
527 xmlDoc.loadXML(xmlDocStr);
528 }
529 return xmlDoc;
530 };
531  
532 this.asArray = function(prop) {
533 if (prop === undefined || prop == null)
534 return [];
535 else
536 if(prop instanceof Array)
537 return prop;
538 else
539 return [prop];
540 };
541  
542 this.toXmlDateTime = function(dt) {
543 if(dt instanceof Date)
544 return dt.toISOString();
545 else
546 if(typeof(dt) === 'number' )
547 return new Date(dt).toISOString();
548 else
549 return null;
550 };
551  
552 this.asDateTime = function(prop) {
553 if(typeof(prop) == "string") {
554 return fromXmlDateTime(prop);
555 }
556 else
557 return prop;
558 };
559  
560 this.xml2json = function (xmlDoc) {
561 return parseDOMChildren ( xmlDoc );
562 };
563  
564 this.xml_str2json = function (xmlDocStr) {
565 var xmlDoc = this.parseXmlString(xmlDocStr);
566 if(xmlDoc!=null)
567 return this.xml2json(xmlDoc);
568 else
569 return null;
570 };
571  
572 this.json2xml_str = function (jsonObj) {
573 return parseJSONObject ( jsonObj, "" );
574 };
575  
576 this.json2xml = function (jsonObj) {
577 var xmlDocStr = this.json2xml_str (jsonObj);
578 return this.parseXmlString(xmlDocStr);
579 };
580  
581 this.getVersion = function () {
582 return VERSION;
583 };
584 }
585 }))