XmlNode

XmlNode defines two methods, with two overloads each, to allow navigation via XPath. SelectSingleNode( ) returns a single XmlNode that matches the given XPath, and SelectNodes( ) returns an XmlNodeList.

Selecting a single node

SelectSingleNode( ) returns a single XmlNode that matches the given XPath expression. If more than one node matches the expression, the first one is returned; the definition of “first” depends on the order of the axis used. The context node of the XPath query is set to the XmlNode instance on which the method is invoked.

One overload of SelectSingleNode( ) takes just the XPath expression. The other one takes the XPath expression and an XmlNamespaceManager. The XmlNamespaceManager is used to resolve any prefixes in the XPath expression.

Example 6-2 shows a simple program that selects a single node from an XML document and writes it to the console, with human-readable formatting.

Example 6-2. Program to execute an XPath query on a document
using System;
using System.Xml;
using System.Xml.XPath;

public class XPathQuery {

  public static void Main(string [ ] args) {

    string filename = args[0];
    string xpathExpression = args[1]; 

    XmlDocument document = new XmlDocument( );
    document.Load(filename);

    XmlTextWriter writer = new XmlTextWriter(Console.Out);
    writer.Formatting = Formatting.Indented;

    XmlNode node = document.SelectSingleNode(xpathExpression);
    node.WriteTo(writer);

    writer.Close( );
  }
}

Because SelectSingleNode( ) is called on the XmlNode instance that represents the entire document, the context node in this case is the document, and the XPath query will be executed relative to the entire document. However, the context node could be any other XmlNode in the document, depending on which XmlNode instance’s SelectSingleNode( ) method is invoked.

If you need to use a specific XmlNode subclass’s methods or properties on the resulting XmlNode instance, it is up to the calling code to cast the XmlNode instance to the appropriate type. For example, if the XPath expression were to return an XmlElement instance, the code would explicitly have to cast the XmlNode to XmlElement in order to call, for example, GetAttribute( ) on it. But then you could also construct your XPath expression to just go ahead and select the attribute in question directly.

Warning

Casting an XmlNode to the incorrect type will cause an InvalidCastException to be thrown. You should be sure you know what type of XmlNode is returned by SelectSingleNode( ) before casting. Two ways to determine an object instance’s actual type are the typeof operator and the GetType( ) method. You can also use the as operator to perform a typesafe cast. For more information on determining an instance’s type at runtime, see C# Essentials, 2nd Edition (O’Reilly).

Selecting multiple nodes

SelectNodes( ) is similar to SelectSingleNode( ), except that it returns an XmlNodeList rather than an XmlNode. XmlNodeList implements IEnumerable, so you can use any of the techniques commonly used to manage a collection. For example, you can interrogate the XmlNodeList’s Count property to discover how many elements it contains, access each element with its array indexer, or use a foreach statement to iterate through the elements in order.

I’ve modified the SelectSingleNode( ) example to select a list of nodes. The changed lines are highlighted:

XmlDocument document = new XmlDocument( );
Document.Load(filename);

XmlTextWriter writer = new XmlTextWriter(Console.Out);
writer.Formatting = Formatting.Indented;

XmlNodeList nodeList = document.SelectNodes(xpathExpression);
Console.WriteLine("{0} nodes matched.", nodeList.Count);
foreach (XmlNode node in nodeList) {
  node.WriteTo(writer);
}

writer.Close( );

As with SelectSingleNode( ), it is up to the calling code to ensure that any casts are correct; this includes the implicit cast in the foreach statement. In this example, however, the foreach will always succeed, because each element of an XmlNodeList is, by definition, an instance of XmlNode.

Also like SelectSingleNode( ), one overload of SelectNodes( ) takes an XmlNamespaceManager parameter.

Creating an XPathNavigator

In addition to the SelectSingleNode( ) and SelectNodes( ) methods, XmlNode implements the IXPathNavigable interface. The only method that IXPathNavigable requires is CreateNavigator( ). CreateNavigator( ) returns an XPathNavigator, which provides an efficient, read-only, random-access model of the XmlNode. Once you have an XPathNavigator, you can call its Select( ) method to navigate to a node or set of nodes using an XPath expression.

The following code produces the same output as the SelectNodes( ) example above:

XmlDocument document = new XmlDocument( );
document.Load(filename);

XmlTextWriter writer = new XmlTextWriter(Console.Out);
writer.Formatting = Formatting.Indented;
                
XPathNavigator navigator = document.CreateNavigator( );
XPathNodeIterator iterator = navigator.Select(xpathExpression);
Console.WriteLine("{0} nodes matched.", iterator.Count);
while (iterator.MoveNext( )) {
  XmlNode node = ((IHasXmlNode)iterator.Current).GetNode( );
  node.WriteTo(writer);
}
writer.Close( );

A couple of lines in this example bear closer investigation:

XPathNodeIterator iterator = navigator.Select(xpathExpression);

XPathNavigator has a Select( ) method that returns an XPathNodeIterator. Select( ) itself has two overloads, one that takes a string XPath expression, and one that takes a precompiled XPathExpression. A compiled XPathExpression can be obtained by passing a textual XPath expression to the XPathNavigator.Compile( ) method.

If you were going to select the same XPath expression multiple times or from different context nodes, it would be more efficient to use a compiled XPathExpression. In the previous example, I used the version of Select( ) that takes a string parameter.In the following example, I’m using a compiled XPathExpression:

XPathExpression expression = navigator.Compile(xpathExpression);
XPathNodeIterator iterator = navigator.Select(expression);

Other useful methods that XPathExpression provides include AddSort( ), whose two overloads allow you to sort the set of nodes resulting from the expression, and SetContext( ), which allows you to set the XmlNamespaceManager used to look up namespace prefixes.

In addition to the two Select( ) overloads, XPathNavigator provides a set of selector methods, including SelectAncestors( ), SelectChildren( ), and SelectDescendants( ), each of which returns an XPathNodeIterator ready for use in navigating the set of results.

Tip

SelectChildren( ) selects only from among the direct child nodes of the context node, while SelectDescendants( ) selects from among the context node’s direct children, plus their children, and so on.

Each of these methods has two overloads; one of which takes an XPathNodeType, while the other takes a string local name and namespace URI. In all these methods, the parameters determine which nodes will be selected, relative to the XPathNavigator’s context node:

while (iterator.MoveNext( )) {

XPathNodeIterator represents a set of nodes returned from an XPath expression. Its interesting methods include Clone( ) and MoveNext( ). Clone( ), which implements the .NET Framework’s ICloneable interface, returns a new XPathNodeIterator whose state is the same as the original one, but further changes to either the original or the clone will not affect the other. Thus, cloning an XPathNodeIterator allows you to work with XPath query results by allowing you to navigate through different branches of the XML tree. MoveNext( ) moves the XPathNodeIterator’s position to the next node.

XPathNodeIterator ’s interesting properties include Count, Current, and CurrentPosition. Current returns a new XPathNavigator whose context node is the XPathNodeIterator’s current node. Like cloning an XPathNodeIterator, this allows you to navigate through XML branches. Count and CurrentPosition return the number of nodes selected and the XPathNodeIterator’s current position, respectively:

XmlNode node = ((IHasXmlNode)iterator.Current).GetNode( );

Since the XPathNavigator in this example was obtained by calling XmlNode.GetNavigator( ), it implements the IHasXmlNode interface. IHasXmlNode’s sole method, GetNode( ), returns the XPathNodeIterator’s context node. So this line of code gets an XPathNavigator whose context node is the same as the XPathIterator instance’s current node and casts it to an IHasXmlNode in order to get its current XmlNode.

It’s important to remember the distinction between the XPathNodeIterator.Current property, which returns a new XPathNavigator positioned at the context node, and the IHasXmlNode.GetNode( ) method, which returns the context node as an XmlNode. By casting an XPathNavigator to an IHasXmlNode, you can get access to the current XmlNode itself.

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

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