Convert XML to a JSON-Like JavaScript Object

5:38:00 PM |

The XML2jsobj Function

We’re going to write a function which recursively analyzes each node of an XML document’s DOM tree and returns a JavaScript object. The function is passed a starting node — which will normally be the root documentElement — and returns an object (internally named data):
  1. function XML2jsobj(node) {  
  2.     var data = {};  
We’ll now define an Add() function within XML2jsobj. This appends a name/value pair to the data object, e.g. data[name] = value. However, if that name already exists, it must convert data[name] to an array so two or more values can be applied:


  1. // append a value  
  2. function Add(name, value) {  
  3.     if (data[name]) {  
  4.         if (data[name].constructor != Array) {  
  5.             data[name] = [data[name]];  
  6.         }  
  7.         data[name][data[name].length] = value;  
  8.     }  
  9.     else {  
  10.         data[name] = value;  
  11.     }  
  12. };  
We now require a loop to examine the XML node’s attributes (e.g. <node attrib1="1" attrib2="2">) and append them to the data object using the Add() function:
  1. // element attributes  
  2. var c, cn;  
  3. for (c = 0; cn = node.attributes[c]; c++) {  
  4.     Add(cn.name, cn.value);  
  5. }  
The next loop examines all child nodes. Comments and white space are ignored but, if a child contains a single item of textual data, it’s appended to the data object using Add(). If that child has its own children, we recursively call XML2jsobj to generate the object:
  1. // child elements  
  2. for (c = 0; cn = node.childNodes[c]; c++) {  
  3.     if (cn.nodeType == 1) {  
  4.         if (cn.childNodes.length == 1 && cn.firstChild.nodeType == 3) {  
  5.             // text value  
  6.             Add(cn.nodeName, cn.firstChild.nodeValue);  
  7.         }  
  8.         else {  
  9.             // sub-object  
  10.             Add(cn.nodeName, XML2jsobj(cn));  
  11.         }  
  12.     }  
  13. }  
Finally, we return the data object to our calling function:
  1. return data;  

Converting XML

Our Ajax call can retrieve XML from a web service:
  1. // example XML feed  
  2. var url = "example.xml";  
  3. // AJAX request  
  4. var xhr = (window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP"));  
  5. xhr.onreadystatechange = XHRhandler;  
  6. xhr.open("GET", url, true);  
  7. xhr.send(null);  
Our XMLHttpRequest onreadystatechange handler receives the XML data and converts it to JavaScript object:
  1. // handle response  
  2. function XHRhandler() {  
  3.     if (xhr.readyState == 4) {  
  4.         var obj = XML2jsobj(xhr.responseXML.documentElement);  
  5.         // do something with our returned data...  
  6.         console.log(obj);  
  7.         xhr = null;  
  8.     }  
  9. }  
So, if example.xml returned the following XML data:
  1. <?xml version="1.0"?>  
  2. <statuses>  
  3.     <status id="one">  
  4.         <id>1</id>  
  5.         <text>Hello!</text>  
  6.     </status>  
  7. </statuses>  
XML2jsobj(xhr.responseXML.documentElement) would return the following object:
  1. {  
  2.     status: {  
  3.         id: ["one", 1],  
  4.         text: "Hello!"  
  5.     }  
  6. }  
You can therefore use obj.status.text to retrieve the “Hello!” text.

Buyer Beware!

A few notes about XML2jsobj:
  • No distinction is made between XML attributes and child elements — if they have the same name, an array of items will be returned with the attribute at index 0.

  • XML2jsobj should only be used when it’s practical. If you are retrieving just one or two XML node values, accessing them with DOM or XPath methods would be faster.

  • The code is cross-browser compatible (including IE6) and can process large XML documents quickly. That said, it may not be suitable for every situation. It probably shouldn’t be used in preference to returning JSON from your server.

  • Grab the Code

    Please  download the code and examples for your own projects.