DekGenius.com
[ Team LiB ] Previous Section Next Section

Recipe 19.7 Reading Elements in an XML Tree

19.7.1 Problem

You want to extract the child elements of an XML or XMLnode object.

19.7.2 Solution

Use the firstChild, lastChild, nextSibling, and previousSibling properties to read the elements one at a time. Alternatively, use the childNodes property to extract all the child elements as an array.

19.7.3 Discussion

You'll often want to "walk" (traverse) an XML tree to extract or examine one or more elements. This is convenient for searching for a given element or processing elements in which you know (or don't care about) their precise order.

All the child elements of an XML or XMLnode object fall into one of three possible categories: the first child, the last child, or some other sibling. Working from this premise, you can extract the child elements of a node using the firstChild, lastChild, nextSibling, and previousSibling properties. The firstChild and lastChild properties return the first and last child elements of an XML or XMLnode object, respectively. Assuming that there are no whitespace nodes in an XML object, the root element is returned by the firstChild property of that object.

my_xml = new XML("<sections><a /><b /><c /><d /></sections>");

// Extract the root element (<sections>).
rootElement = my_xml.firstChild;

// Extract the first child element of the root element (<a>).
aElement = rootElement.firstChild;

// Extract the last child element of the root element (<d>).
dElement = rootElement.lastChild;

You can access a child element's sibling nodes using the nextSibling and previousSibling properties:

// Extract the next sibling to the <a> element (<b>).
bElement = aElement.nextSibling;

// Extract the previous sibling to the <d> element (<c>).
cElement = dElement.previousSibling;

Another way to extract the child elements of an XML or XMLnode object is to work with them as elements of an array. The childNodes property returns such an array:

children = rootElement.childNodes;

// Displays:
// <a />
// <b />
// <c />
// <d />
for (var i = 0; i < children.length; i++) {
  trace(children[i]);
}

Using the aforementioned properties, you can walk through an XML tree structure recursively, as shown in the following example. The search( ) method we create here can be useful in simple situations in which you want to find all the elements with a particular name regardless of their contents or location in the tree's hierarchy. For more advanced and complex searches, use XPath (see Recipe 19.15).

We'll add the search( ) method to the XMLNode class, and the method should accept a single parameter: the node name for which to search. You can add this custom function to your XML.as file for easy inclusion in other projects:

XMLNode.prototype.search = function (searchName) {

  // Create an array in which to store the matching elements.
  var matches = new Array(  );

  // If the current node has children, loop through all elements to find matches.
  if (this.hasChildNodes(  )) {
    for (var i = 0; i < this.childNodes.length; i++) {
      // For each child node, invoke the search(  ) method recursively. Concatenate the
      // results with the current matches array.
      matches = matches.concat(this.childNodes[i].search(searchName));
    }
  }

  // If the current node is a match, add it to the matches array. For more
  // information on the nodeName property, see Recipe 19.8.
  if (this.nodeName == searchName) {
    matches.push(this);
  } 

  // Return the matches.
  return matches;
};

Here is an example of how you might use this method:

#include "XML.as"

// Set ignoreWhite to true for the XML class. See Recipe 19.12 for more information
// on the ignoreWhite property.
XML.prototype.ignoreWhite = true;

// Create an XML object and load data from an external document named books.xml.
my_xml = new XML(  );
my_xml.load("books.xml");
my_xml.onLoad = function (success) {
  if (success) {
    // When the document loads, use the search(  ) method to find all the <author> 
    // elements. Display the results in the Output window. We join all the elements
    // of the resulting array together with a newline so that each one appears on its
    // own line.
    trace(this.search("author").join("\n"));
  }
};

19.7.4 See Also

Recipe 19.15, Recipe 19.12, and Recipe 19.8

    [ Team LiB ] Previous Section Next Section