Parsing XML in Javascript and AJAX


Lets say your AJAX call to a server side script fetches some books from a database:
<?xml version="1.0" encoding="UTF-8" ?>
<request>
      <book>To Kill a Mockingbird</book>
      <book>The Hobbit</book>
      <book>War and Peace</book>
</request>

Your ajax callback handler would probably look more like
function handleResponse(request)
{
    var xml = request.responseXML;
    var doc = (xml.firstChild.nextSibling)? xml.firstChild.nextSibling : xml.firstChild;
    for(var i=0; i<doc.childNodes.length; i++){
        if (doc.childNodes[i].nodeName.toLowerCase()=="book"){
            alert( doc.childNodes[i].firstChild.nodeValue );
        }
    }
}


Now, xml.firstChild should always refer to the xml document tag ( in our case), but if it has a nextSibling, then we can be sure its IE 6 screwing up again. IE 6 considers to be the first child and the to be the firstChild.nextSibling, so make sure to account for that like I did in the above code.

When you parse XML, avoid using getElementsByTagName(). It appears much easier to just do var booklist = xml.getElementsByTagName("book"); instead of iterating through the child nodes as above, however it can be error prone. Lets look at another example:
<?xml version="1.0" encoding="UTF-8" ?>
<request>
      <book>
<book>To Kill a Mockingbird</book>
<author>Harper Lee</author>
      </book>
      <book>
<book>The Hobbit</book>
<author>J.R.R. Tolkien</author>
      </book>
      <book>
<book>War and Peace</book>
<author>Leo Tolstoy</author>
      </book>
   </book>
</request>

In this case, var booklist = xml.getElementsByTagName("book"); returns a list of 6 xml tags: the 3 children of <request>, as well as the 3 nodes containing the book title text, and that probably isn't what you wanted to do.

To fetch the list of children by name use this function. It will only get one generation of children at a time. If you need to access the children's children, you can call this function again on its children.
function getChildrenByTagName(element,name)
{
    var list = new Array();
    name = name.toUpperCase();
    for(var i=0; i<element.childNodes.length; i++)
        if (element.childNodes[i].nodeName.toUpperCase()==name)
            list.push( element.childNodes[i] );
    return list;
}
//usage:
var childlist = getChildrenByTagName(doc,'book');
function getTextByTagName(element, name){
    name = name.toUpperCase();
    for(var i=0; i<element.childNodes.length; i++)
        if (element.childNodes[i].nodeName.toUpperCase()==name)
            return element.childNodes[i].firstChild.nodeValue;
    return '';
}//usage:
var text = getTextByTagName(booklist[i], 'author');





code snippets are licensed under Creative Commons CC-By-SA 3.0 (unless otherwise specified)