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