jquery.xml2json.js 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. /*
  2. ### jQuery XML to JSON Plugin v1.3 - 2013-02-18 ###
  3. * http://www.fyneworks.com/ - diego@fyneworks.com
  4. * Licensed under http://en.wikipedia.org/wiki/MIT_License
  5. ###
  6. Website: http://www.fyneworks.com/jquery/xml-to-json/
  7. *//*
  8. # INSPIRED BY: http://www.terracoder.com/
  9. AND: http://www.thomasfrank.se/xml_to_json.html
  10. AND: http://www.kawa.net/works/js/xml/objtree-e.html
  11. *//*
  12. This simple script converts XML (document of code) into a JSON object. It is the combination of 2
  13. 'xml to json' great parsers (see below) which allows for both 'simple' and 'extended' parsing modes.
  14. */
  15. // Avoid collisions
  16. ;if(window.jQuery) (function($){
  17. // Add function to jQuery namespace
  18. $.extend({
  19. // converts xml documents and xml text to json object
  20. xml2json: function(xml, extended) {
  21. if(!xml) return {}; // quick fail
  22. //### PARSER LIBRARY
  23. // Core function
  24. function parseXML(node, simple){
  25. if(!node) return null;
  26. var txt = '', obj = null, att = null;
  27. var nt = node.nodeType, nn = jsVar(node.localName || node.nodeName);
  28. var nv = node.text || node.nodeValue || '';
  29. /*DBG*/ //if(window.console) console.log(['x2j',nn,nt,nv.length+' bytes']);
  30. if(node.childNodes){
  31. if(node.childNodes.length>0){
  32. /*DBG*/ //if(window.console) console.log(['x2j',nn,'CHILDREN',node.childNodes]);
  33. $.each(node.childNodes, function(n,cn){
  34. var cnt = cn.nodeType, cnn = jsVar(cn.localName || cn.nodeName);
  35. var cnv = cn.text || cn.nodeValue || '';
  36. /*DBG*/ //if(window.console) console.log(['x2j',nn,'node>a',cnn,cnt,cnv]);
  37. if(cnt == 8){
  38. /*DBG*/ //if(window.console) console.log(['x2j',nn,'node>b',cnn,'COMMENT (ignore)']);
  39. return; // ignore comment node
  40. }
  41. else if(cnt == 3 || cnt == 4 || !cnn){
  42. // ignore white-space in between tags
  43. if(cnv.match(/^\s+$/)){
  44. /*DBG*/ //if(window.console) console.log(['x2j',nn,'node>c',cnn,'WHITE-SPACE (ignore)']);
  45. return;
  46. };
  47. /*DBG*/ //if(window.console) console.log(['x2j',nn,'node>d',cnn,'TEXT']);
  48. txt += cnv.replace(/^\s+/,'').replace(/\s+$/,'');
  49. // make sure we ditch trailing spaces from markup
  50. }
  51. else{
  52. /*DBG*/ //if(window.console) console.log(['x2j',nn,'node>e',cnn,'OBJECT']);
  53. obj = obj || {};
  54. if(obj[cnn]){
  55. /*DBG*/ //if(window.console) console.log(['x2j',nn,'node>f',cnn,'ARRAY']);
  56. // http://forum.jquery.com/topic/jquery-jquery-xml2json-problems-when-siblings-of-the-same-tagname-only-have-a-textnode-as-a-child
  57. if(!obj[cnn].length) obj[cnn] = myArr(obj[cnn]);
  58. obj[cnn] = myArr(obj[cnn]);
  59. obj[cnn][ obj[cnn].length ] = parseXML(cn, true/* simple */);
  60. obj[cnn].length = obj[cnn].length;
  61. }
  62. else{
  63. /*DBG*/ //if(window.console) console.log(['x2j',nn,'node>g',cnn,'dig deeper...']);
  64. obj[cnn] = parseXML(cn);
  65. };
  66. };
  67. });
  68. };//node.childNodes.length>0
  69. };//node.childNodes
  70. if(node.attributes){
  71. if(node.attributes.length>0){
  72. /*DBG*/ //if(window.console) console.log(['x2j',nn,'ATTRIBUTES',node.attributes])
  73. att = {}; obj = obj || {};
  74. $.each(node.attributes, function(a,at){
  75. var atn = jsVar(at.name), atv = at.value;
  76. att[atn] = atv;
  77. if(obj[atn]){
  78. /*DBG*/ //if(window.console) console.log(['x2j',nn,'attr>',atn,'ARRAY']);
  79. // http://forum.jquery.com/topic/jquery-jquery-xml2json-problems-when-siblings-of-the-same-tagname-only-have-a-textnode-as-a-child
  80. //if(!obj[atn].length) obj[atn] = myArr(obj[atn]);//[ obj[ atn ] ];
  81. obj[cnn] = myArr(obj[cnn]);
  82. obj[atn][ obj[atn].length ] = atv;
  83. obj[atn].length = obj[atn].length;
  84. }
  85. else{
  86. /*DBG*/ //if(window.console) console.log(['x2j',nn,'attr>',atn,'TEXT']);
  87. obj[atn] = atv;
  88. };
  89. });
  90. //obj['attributes'] = att;
  91. };//node.attributes.length>0
  92. };//node.attributes
  93. if(obj){
  94. obj = $.extend( (txt!='' ? new String(txt) : {}),/* {text:txt},*/ obj || {}/*, att || {}*/);
  95. //txt = (obj.text) ? (typeof(obj.text)=='object' ? obj.text : [obj.text || '']).concat([txt]) : txt;
  96. txt = (obj.text) ? ([obj.text || '']).concat([txt]) : txt;
  97. if(txt) obj.text = txt;
  98. txt = '';
  99. };
  100. var out = obj || txt;
  101. //console.log([extended, simple, out]);
  102. if(extended){
  103. if(txt) out = {};//new String(out);
  104. txt = out.text || txt || '';
  105. if(txt) out.text = txt;
  106. if(!simple) out = myArr(out);
  107. };
  108. return out;
  109. };// parseXML
  110. // Core Function End
  111. // Utility functions
  112. var jsVar = function(s){ return String(s || '').replace(/-/g,"_"); };
  113. // NEW isNum function: 01/09/2010
  114. // Thanks to Emile Grau, GigaTecnologies S.L., www.gigatransfer.com, www.mygigamail.com
  115. function isNum(s){
  116. // based on utility function isNum from xml2json plugin (http://www.fyneworks.com/ - diego@fyneworks.com)
  117. // few bugs corrected from original function :
  118. // - syntax error : regexp.test(string) instead of string.test(reg)
  119. // - regexp modified to accept comma as decimal mark (latin syntax : 25,24 )
  120. // - regexp modified to reject if no number before decimal mark : ".7" is not accepted
  121. // - string is "trimmed", allowing to accept space at the beginning and end of string
  122. var regexp=/^((-)?([0-9]+)(([\.\,]{0,1})([0-9]+))?$)/
  123. return (typeof s == "number") || regexp.test(String((s && typeof s == "string") ? jQuery.trim(s) : ''));
  124. };
  125. // OLD isNum function: (for reference only)
  126. //var isNum = function(s){ return (typeof s == "number") || String((s && typeof s == "string") ? s : '').test(/^((-)?([0-9]*)((\.{0,1})([0-9]+))?$)/); };
  127. var myArr = function(o){
  128. // http://forum.jquery.com/topic/jquery-jquery-xml2json-problems-when-siblings-of-the-same-tagname-only-have-a-textnode-as-a-child
  129. //if(!o.length) o = [ o ]; o.length=o.length;
  130. if(!$.isArray(o)) o = [ o ]; o.length=o.length;
  131. // here is where you can attach additional functionality, such as searching and sorting...
  132. return o;
  133. };
  134. // Utility functions End
  135. //### PARSER LIBRARY END
  136. // Convert plain text to xml
  137. if(typeof xml=='string') xml = $.text2xml(xml);
  138. // Quick fail if not xml (or if this is a node)
  139. if(!xml.nodeType) return;
  140. if(xml.nodeType == 3 || xml.nodeType == 4) return xml.nodeValue;
  141. // Find xml root node
  142. var root = (xml.nodeType == 9) ? xml.documentElement : xml;
  143. // Convert xml to json
  144. var out = parseXML(root, true /* simple */);
  145. // Clean-up memory
  146. xml = null; root = null;
  147. // Send output
  148. return out;
  149. },
  150. // Convert text to XML DOM
  151. text2xml: function(str) {
  152. // NOTE: I'd like to use jQuery for this, but jQuery makes all tags uppercase
  153. //return $(xml)[0];
  154. /* prior to jquery 1.9 */
  155. /*
  156. var out;
  157. try{
  158. var xml = ((!$.support.opacity && !$.support.style))?new ActiveXObject("Microsoft.XMLDOM"):new DOMParser();
  159. xml.async = false;
  160. }catch(e){ throw new Error("XML Parser could not be instantiated") };
  161. try{
  162. if((!$.support.opacity && !$.support.style)) out = (xml.loadXML(str))?xml:false;
  163. else out = xml.parseFromString(str, "text/xml");
  164. }catch(e){ throw new Error("Error parsing XML string") };
  165. return out;
  166. */
  167. /* jquery 1.9+ */
  168. return $.parseXML(str);
  169. }
  170. }); // extend $
  171. })(jQuery);