How to Convert XML to a JSON-Like JavaScript Object

In my post How to Create an XML to JSON Proxy Server in PHP we created a system which translated XML messages into Ajax-ready JSON. That’s great if you’re running PHP or another suitable server-side process. But what if you’re limited to JavaScript only?

Randomly accessing data from an XML document isn’t fun. You can use DOM or XPath methods, but they’re not as easy as native (JSON-generated) JavaScript object properties such as myobj.list[0].property1. If you’re frequently accessing data from the same XML document, it may be practical to translate it to a JavaScript object first. Ready to write some code?…

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):


function XML2jsobj(node) {

	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:


	// append a value
	function Add(name, value) {
		if (data[name]) {
			if (data[name].constructor != Array) {
				data[name] = [data[name]];
			}
			data[name][data[name].length] = value;
		}
		else {
			data[name] = value;
		}
	};

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:


	// element attributes
	var c, cn;
	for (c = 0; cn = node.attributes; c++) {
		Add(cn.name, cn.value);
	}

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:


	// child elements
	for (c = 0; cn = node.childNodes; c++) {
		if (cn.nodeType == 1) {
			if (cn.childNodes.length == 1 && cn.firstChild.nodeType == 3) {
				// text value
				Add(cn.nodeName, cn.firstChild.nodeValue);
			}
			else {
				// sub-object
				Add(cn.nodeName, XML2jsobj(cn));
			}
		}
	}

Finally, we return the data object to our calling function:


	return data;

}

Converting XML

Our Ajax call can retrieve XML from a web service:


// example XML feed
var url = "example.xml";

// AJAX request
var xhr = (window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP"));
xhr.onreadystatechange = XHRhandler;
xhr.open("GET", url, true);
xhr.send(null);

Our XMLHttpRequest onreadystatechange handler receives the XML data and converts it to JavaScript object:


// handle response
function XHRhandler() {

	if (xhr.readyState == 4) {
	
		var obj = XML2jsobj(xhr.responseXML.documentElement);
		
		// do something with our returned data...
		console.log(obj);
		
		xhr = null;
	
	}

}

So, if example.xml returned the following XML data:


<?xml version="1.0"?>
<statuses>
	<status id="one">
		<id>1</id>
		<text>Hello!</text>
	</status>
</statuses>

XML2jsobj(xhr.responseXML.documentElement) would return the following object:


{
	status: {
		id: ["one", 1],
		text: "Hello!"
	}
}

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 view the demonstration page or download the code and examples for your own projects.

    I hope you find it useful — let me know if eases a few XML headaches!

    Free book: Jump Start HTML5 Basics

    Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

    • Perry

      You could also take the jQuery route using the XML to JSON plugin.
      http://www.fyneworks.com/jquery/xml-to-json
      I know, this doesn’t do a lot in the way of honing your JavaScript skills but it’s a nice shortcut.

      • http://www.optimalworks.net/ Craig Buckler

        Thanks for the link, Perry. It looks as though it’s doing much the same – although there are a few more options, debugging messages and the code’s considerably longer.

    • http://sdussaut.com Sébastien

      You could also use a XSL stylesheet that will transform the XML (and take care of attributes and children) into a well-formatted JSON with ease (and very few lines), instantiate the DOM parser with Javascript to make the transformation happen and you are good to go.

      In some cases you won’t be able to use a XSL stylesheet, but when you can I think it’s much more appropriate to parse and transform XML than Javascript. Actually, Javascript isn’t the right tool for this particular case IMHO.

      • http://www.optimalworks.net/ Craig Buckler

        You could use XSL but, in my experience, it can fail in some browsers. Opera was always problematical for me, although later versions might be better. However, assuming it does work, I doubt it’ll be faster. As well as performing the transformation, the resulting string must be evaluated into a JavaScript object using JSON.parse or eval.

        In an ideal world you wouldn’t need JavaScript to do this since your web service would return JSON and everyone would be happy! Unfortunately, that’s not always the case. For example, many Microsoft systems use SOAP and don’t offer a JSON option.

    • http://www.joezimjs.com JoeZimJS

      Beautiful. I was actually thinking about something like this. I hate XML with a passion. Way too many characters to show data that JSON can show just as easily with fewer characters. But if you need to use it then this is a great way to get around its ugliness. I’ll have to make a mention of this on my JavaScript blog at http://www.joezimjs.com.

    • http://www.onlinekredite-guenstig.de/ Onlinekredite

      This is exactly I was looking for. Actually I use currently JQuery for the customers website. Therefore it would be better to use the jquery plugin. I will try both variants.