Compile, Select, Evaluate, and Matches with XPath and XPathExpressions

An XPathExpresion object represents an XPath expression that is returned from the Compile method. The Compile method is useful if the same query is being used more than once. If the expression given to the Compile method is not valid, an exception is thrown. The only instance where an exception is not thrown for an invalid expression is if the XPathExpression is a user-defined function. In this case, an exception is thrown at run-time when the expression is evaluated and found to be bad.

If there is a Select method that you call repeatedly, instead of using a string value each time, use the Compile method to compile and cache the XpathExpression object for reuse for improved performance.

Dim xpeCache As Object = Nothing
xpeCache = nav.Compile("//book[@author="smith"//BookPrice[.>50]")
nav.Select(xpeCache)
[C#]
object xpeCache = null;
xpeCache = nav.Compile("//book[@author="smith"//BookPrice[.>50]");
nav.Select(xpeCache);

Once compiled, the XPathExpression can be used as input to the Select, Evaluate, and Matches methods, depending on the type returned from an XPath expression or the compiled XPath expression. The table below shows the return type of expressions, a description, and what methods the expression can be used in.

W3C XPath Return Type Equivalent .NET Class (Type) Description Methods Used in
node set System.Xml.XPath.XPathNodeIterator An unordered collection of nodes, without duplicates, created in document order. Select or Evaluate
Boolean System.Boolean A true or false value. Evaluate
number System.Double A floating-point number. Evaluate
string System.String A sequence of UCS characters. Evaluate

The Matches method uses XSLT patterns as its argument.

If you compile an XPath query and need to know what it returns, you can use the ReturnType property. The table below shows the XPathResultType enumeration returned, and a description of what kind of XPath expression type the enumeration represents.

XPathResultType Enumeration Description of W3C XPath Type
0 String
1 Boolean
2 Number
3 Node set
5 Any

The following code sample shows how the return type enumeration can be used to check the return type of an XPath expression or compiled XPathExpression properly.

Dim doc As New XPathDocument("books.xml")
Dim nav As XPathNavigator = doc.CreateNavigator()
' The following line returns a number.
Dim Expr As XPathExpression = nav.Compile("/Price/text()*10")
' The following line returns a node set.
Dim Expr2 As XPathExpression = nav.Compile("books/book/price")

Select Case Expr.NodeType
    Case XPathResultType.Number
        nav.Evaluate(Expr)
    Case XPathResultType.Nodeset
        Dim iterator as XPathNodeIterator
        iterator = nav.Select(Expr)
        If iterator.MoveNext() Then
        End If
    Case XPathResultType.Boolean
        nav.Evaluate(Expr)
    Case XPathResultType.String
        nav.Evaluate(Expr)
    Case Else
        Throw New Exception("Invalid XpathResultType")
   
End Select
[C#]
XPathDocument doc = new XPathDocument("books.xml");
XPathNavigator nav = doc.CreateNavigator();
// The following line returns a number.
XPathExpression Expr = nav.Compile("/Price/text()*10"); 
// The following line returns a node set.
XPathExpression Expr2 = nav.Compile("books/book/price"); 

switch(Expr.ReturnType)
{
case XPathResultType.Number:
    nav.Evaluate(Expr);
    break;

case XPathResultType.Nodeset:
    XPathNodeIterator iterator = nav.Select(Expr);
    if (iterator.MoveNext()) {}
    break;    

case XPathResultType.Boolean:
    nav.Evaluate(Expr);
    break;

case XPathResultType.String:
    nav.Evaluate(Expr);
    break;

case default:
    throw new Exception("Invalid XPathResultType");
    break;
}

When instantiating the XPathDocument, various objects can be used to supply the source XML, including a string, stream, TextReader, and XmlReader. When using an XmlReader to supply the source XML, if the reader is positioned on a node, the data is loaded from the current position of the reader through all its siblings. This enables you to load only a portion of the document. If the reader is positioned on a leaf node that is invalid as a root for the document, for example a white space or attribute node type, the reader continues to read until it is positioned on a node that can be used as the root. The document begins loading at this point.

Also, for better performance, use the most specific expression possible. If the book node occurs under the bookstore node, and the bookstore node is the top-most element, using /bookstore/book will be faster than //book, as the latter will scan every node in the XML data hierarchy to identify the matching nodes. Additionally, using Select for performance gain is scenario-dependent. But, if your selection is simple enough that a few move methods will return the data and there is no need to track state information, the Move methods may be faster than using Select. For example, if you need the first child of the current node, it is faster to use MoveToFirst than to issue a Select("child::*[1]") call.

For more information on selecting and iterating over nodes from a data store, see XPath Select and XPathNavigator.

For more information on evaluating an expression on a node, see XPath Evaluate and XPathNavigator.

For more information on verifying if the current node matches an XPath expression, see XPath Matches and XPathNavigator.

See Also

XPathNavigator in the .NET Framework