« first  « prev  » next  » last 

Jump to:


The XML Parsing Class

1. XML Walker


I created the XmlWalker class for various bits and bobs on my website (especially in the Google Maps area) that involve AJAX technology. It takes some of the pain out of iterating through an XML document.

The class walks through nodes in an XML document recursively, in the style of a depth-first search. Callbacks are registered for XML elements with given names, these callback functions are called either before or after the children of the matched element are parsed. A "done" callback is also provided so that control can be returned to the main application.

Examples of the use of the XmlWalker are plentiful in the first part of this article. Here is the code for the walker class.
function XmlWalker(document)
{   
  // Arrays to store "before" and "after" callbacks

  var entryCallbacks = new Array();
  var exitCallbacks = new Array();
 
  // The "done" callback and setter

  var doneCallback = 0;
  this.setDoneCallback = function(dcb)
  {
    doneCallback = dcb;
  }
 
  // Add "before" and "after" callbacks for a given element name

  this.addCallback = function(name, entryFunc, exitFunc)
  {
    entryCallbacks[name] = entryFunc;
    exitCallbacks[name] = exitFunc;
  }
 
  // Remove callbacks associated with a given element name

  this.removeCallback = function(name)
  {
    entryCallbacks[name] = 0;
    exitCallbacks[name] = 0;
  }
 
  // "public" function to start parsing

  this.walkXmlDocument = function()
  {
    walkXmlFragment(document.documentElement);
   
    if(doneCallback)
      doneCallback();
  }

  // Recursive function to walk a given subtree

  function walkXmlFragment(element)
  {     
    while(element)
    {
      // Fire "before" callback if element name matches

      if(entryCallbacks[element.nodeName])
        entryCallbacks[element.nodeName](element);
   
      // Walk children

      walkXmlFragment(element.firstChild);
     
      // Fire "after" callback if element name matches

      if(exitCallbacks[element.nodeName])
        exitCallbacks[element.nodeName](element);
     
      // Move to next element

      element = element.nextSibling;
    }
  }
}

You are free to use this code anywhere and for any purpose (except maybe international terrorism). Note that the code comes with no warranty or guarantees - but I've found it to work very nicely.

If you do use the code, please credit LogicalGenetics.com smilie

« first  « prev  » next  » last 

Jump to: