XPath Iterators

When the XPath expression originates a node-set, the navigator object always returns it using a new breed of object—the node iterator. The node iterator is a relatively simple object that provides an agile, common interface to navigate an array of nodes. The base class for XPath iterators is XPathNodeIterator.

The node iterator does not cache any information about the identity of the nodes involved. It simply works as an indexer on top of the navigator object that operated the XPath query. All the functionalities you might find in the implementation of any XPathNodeIterator classes could have been easily packed into the navigator itself. Why then does the .NET Framework provide the navigation and the iteration API as distinct components?

First, decoupling data containers from navigators, and navigators from iterators, represents a good bargain from the software standpoint. The ultimate reason for keeping the navigation and the iteration API distinct, however, is that in this way the results of any XPath query can be easily accessed and processed from different programming environments—XML DOM, XPath, and, last but not least, XSLT.

The XPathNodeIterator Class

The XPathNodeIterator class has no public constructor and can be created only by the parent navigator object. The iterator provides forward-only access to the nodes selected by XPath query. Callers use the iterator’s methods and properties to access all the nodes included in the node-set. Figure 6-7 illustrates the relationship between callers, navigators, and iterators. A caller passes an XPath expression. The navigator executes the command and gets a node-set. The caller then receives an iterator object to access the members of the node-set. Current, Count, and MoveNext are the key members of the iterator’s programming interface.

Figure 6-7. The relationship between callers, navigators, and iterators.


Properties of the Iterator Object

Table 6-10 summarizes the properties exposed by the XPathNodeIterator class.

Table 6-10. Properties of the XPathNodeIterator Class
Property Description
Count Returns the number of elements in the node-set. This value refers to the top-level nodes and does not consider child nodes.
Current Returns a reference to a navigator object rooted in the iterator’s current node.
CurrentPosition Gets the index of the currently selected node.

The Current property is the key property for callers to drill down into the structure of the selected node. In the XPath Evaluator sample application we discussed earlier in this chapter, at a certain point we had to examine the subtree of each node included in the node-set. The code in Figure 6-4 uses a recursive routine (named LoopThroughChildren) to navigate the subtree of a given node.

The navigator/iterator pair makes that task quite straightforward to accomplish. The Current property already returns a reference to the XPathNavigator object rooted in the currently selected node. Pay attention to the fact that what you get is not a copy of the navigator but a simple reference. If you need to dig into the node structure, make a deep copy of the navigator first. For the purpose, you can use the navigator’s Clone method.

Methods of the Iterator Object

Table 6-11 lists the public methods of an iterator object.

Table 6-11. Methods of the XPathNodeIterator Class
Method Description
Clone Makes a deep copy of the current XPathNodeIterator object
MoveNext Moves to the next node in the navigator’s selected node-set

When MoveNext is called, the iterator adjusts some internal pointers and refreshes its Current and CurrentPosition properties. When the iterator is first returned to the caller, there is no currently selected node. Only after the first call to MoveNext does the Current property point to a valid navigator object.

Visiting the Selected Nodes

Let’s review the typical way in which an XPath iterator works. Suppose that you just executed an XPath command using an XPathNavigator object, as shown here:

XPathDocument doc = new XPathDocument(fileName);
XPathNavigator nav = doc.CreateNavigator(); 
XPathNodeIterator iterator = nav.Select(expr);

To visit all the selected nodes, you set up a loop controlled by the iterator’s MoveNext method, as follows:

while (iterator.MoveNext())
{
   XPathNavigator nav2 = iterator.Current.Clone();
   ⋮
}

In real-world applications, you need to drill down into the subtree of each node referenced in the XPath node-set. You should not use the navigator returned by the Current property to move away from the node-set. Instead, you should clone the object and use the cloned navigator to perform any additional moves. The following code snippet generates the output shown in Figure 6-6:

while (iterator.MoveNext())
{
   XPathNavigator _copy = iterator.Current.Clone();            
   string buf = "";

   // Select the <employeeid> node and read the current value
   _copy.MoveToFirstChild();   
   buf += _copy.Value + ". ";

   // Select the <lastname> node and read the current value
   _copy.MoveToNext();      
   buf += _copy.Value;

   // Select the <firstname> node and read the current value
   _copy.MoveToNext(); 
   buf += ", " + _copy.Value;

   // Select the <title> node and read the current value
   _copy.MoveToNext();       
   buf += "   	[" + _copy.Value + "]";

   // Write out the final result
   Console.WriteLine(buf);
}

Of course, the cloned and the original XPathNavigator objects are totally distinct and independent objects, and the clone is not affected by any subsequent changes made to the original navigator.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.17.74.227