Using XML Data Traversal

Tweet

In this article, we’ll take a look at an XML-based, client-side JavaScript that reads data from an external XML file, traverses the XML data, and displays it in a tree format.

I’ll use the XMLDOM ActiveX object built into Microsoft Internet Explorer to achieve this.

Consider the following XML file:

<?xml version="1.0"?> 
<personal>Personal Details
 <name>Premshree Pillai</name>
 <sex>male</sex>
 <websites>Websites
   <ws1>http://www.sitepoint.com</ws1>
   <ws2>http://sitepointforums.com</ws2>
 </websites>
</personal>

What we want the script to do is to display the above XML data like this:

  • personal : Personal Details
  • name : Premshree Pillai
  • sex : male
  • websites : Websites
    • ws1 : http://www.sitepoint.com
    • ws2 : http://sitepointforums.com
The Algorithm

Here’s the process we’ll use to achieve this goal:

  1. Read the XML file
  2. Point a variable, tree, to the first node (XML tag) of the XML data.
  3. If the node has child nodes:
    • Print "<ul><li>";
    • For each child node, traverse(tree.childNodes(nodeNum))
    • Print "</li></ul>";

  4. If the node does not have any child:
    • Print the node’s value.
Script and Explanation

Let’s take a look at the script:

var xmlDoc=new ActiveXObject("Microsoft.XMLDOM");

The above code creates a new instance of the Microsoft.XMLDOM ActiveX object.

function loadXML(xmlFile) { 
 xmlDoc.async="false";
 xmlDoc.onreadystatechange=verify;
 xmlDoc.load(xmlFile);
}

The loadXML() function is used to load a particular .xml file. This function makes reference to the verify() function, which is as follows:

function verify() {  
 if(xmlDoc.readyState!=4)
   return false;  
}

The loading of a XML file occurs in 5 stages:

  • 0 – Object is not initialized
  • 1 – Loading object is loading data
  • 2 – Loaded object has loaded data
  • 3 – Data from object can be worked with
  • 4 – Object completely initialized

The loading state of an XML file can be accessed through the XMLDOM’s readyState property: if a file (object) is not initialized, xmlDoc.readyState will return 0, and so on. Thus, through the loadXML() function, we can verify the loading status of the XML document — obviously, we don’t want to use a partially or completely uninitialized object.

Now, let’s take a look at the function that does the XML data traversal, traverse():

function traverse(tree) { 
 if(tree.hasChildNodes()) {
   document.write('<ul><li>');
   document.write('<b>'+tree.tagName+' : </b>');
   var nodes=tree.childNodes.length;
   for(var i=0; i<tree.childNodes.length; i++)
     traverse(tree.childNodes(i));
   document.write('</li></ul>');
 }
 else
   document.write(tree.text);
}

The traverse() function is a recursive function that takes a node as its argument.

As explained earlier in the algorithm, the function first checks whether the node has any children. If the node does have children, necessary indentation is implemented using HTML lists (<ul>, <li> tags). Next, for each of this node’s child nodes, the function traverse() is called (recursively), with the argument as that child node.

If the node (argument passed to traverse()) has no child nodes, the function prints the value held by that node (tag). In this way, the tree structure for the XML file is generated. Now, let’s take a look at the initTraverse() function:

function initTraverse(file) { 
loadXML(file);
var doc=xmlDoc.documentElement;
traverse(doc);
}

The initTraverse() function takes an XML filename as its argument. This function first loads the XML file, sets the variable doc to the root node of the XML data, and then traverses the XML data using the traverse() function, with argument as the root node (i.e. doc).

This is the function that’s called when you want to generate the tree structure of a XML file.

All the above code may be place in an external .js file. The following code must be placed in the location where the tree form of the XML file has to be generated:

initTraverse("anyXMLfile.xml");

Here’s the complete script.

<script language="JavaScript"> 

var xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
function loadXML(xmlFile) {
 xmlDoc.async="false";
 xmlDoc.onreadystatechange=verify;
 xmlDoc.load(xmlFile);
}

function verify() {  
 if(xmlDoc.readyState!=4)
   return false;  
}

function traverse(tree) {
 if(tree.hasChildNodes()) {
   document.write('<ul><li>');
   document.write('<b>'+tree.tagName+' : </b>');
   var nodes=tree.childNodes.length;
   for(var i=0; i<tree.childNodes.length; i++)
     traverse(tree.childNodes(i));
   document.write('</li></ul>');
 }
 else
   document.write(tree.text);
}

function initTraverse(file) {
 loadXML(file);
 var doc=xmlDoc.documentElement;
 traverse(doc);
}
</script>

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.

No Reader comments