XPath Evaluate and XPathNavigator
XPath expressions as a string, or a compiled XPathExpression that return a W3C XPath type of boolean (System.Boolean), number (System.Double), string (System.String), or node set (System.Xml.XPath.XPathNodeIterator), can be passed to the Evaluate method. The Evaluate method takes the expression, evaluates it, and returns a typed result. This method could be used in a mathematical user defined method. For example, the following code calculates the total price of all item
elements that are inside an order
element in the current selection.
Dim doc as XmlDocument = new XmlDocument()
doc.Load("order.xml")
Dim nav as XPathNavigator = doc.CreateNavigator()
' Calculate the total of the order.
Dim expr as XPathExpression = nav.Compile("sum(//price/text())")
Dim total as double = CType(nav.Evaluate(expr), double)
[C#]
XmlDocument doc = new XmlDocument();
doc.Load("order.xml");
XPathNavigator nav = doc.CreateNavigator();
// Calculate the total of the order.
XPathExpression expr = nav.Compile("sum(//price/text())");
double total = (double) nav.Evaluate(expr);
position and last Functions in the Evaluate Method
The Evaluate method is overloaded. One Evaluate signature, public virtual object Evaluate(XPathExpression xpathexpr, XPathIterator nodeset);
, provides an XPathNodeIterator input argument for an XPathIterator. This particular Evaluate method is identical to the Evaluate(string xpathexpr)
method. However, it allows a node set argument to specify the current context to perform the evaluation on. This is required for the XPath last and position functions as they are relative to the current context node.
The XPath position and last functions, unless used as a predicate in a location step, require a reference to a node set in order to be evaluated. In this case, you must use the overload method that takes an XPathNodeIterator as an argument; otherwise, position and last return 0.
Also, since the XPath function returns the value of the context position, and the position function is evaluated with regards to the current node in a selected set of nodes, at least one node must have been selected with the Select method. That is, the query passed in through the Select and Evaluate methods are used as the context. Since the position function only makes sense for the current node, if the current node is not in the selected set of nodes (e.g. MoveToNext is called which moves to a node which is outside of the set of selected nodes), an exception is thrown. As an example the following XSLT creates a number based on the node position.
<xsl:number value='position()'>
The XPath last function also uses the XPathNodeIterator as the context. It returns the total number of nodes that have been selected with the Select or Evaluate methods. If no nodes were selected, it returns zero.
The following XML is called numbers.xml and is input to the following code sample.
Input
<mydoc>
<numbers>
<n>1</n>
<n>2</n>
<n>3</n>
</numbers>
<numbers>
<n>1</n>
<n>1</n>
<n>2</n>
<n>2</n>
<n>3</n>
<n>4</n>
</numbers>
<numbers>
<n>5</n>
<n>NaN</n>
<n>0</n>
</numbers>
</mydoc>
The following code example uses the Evaluate method with the position function, which returns a position of 0.
Dim strXmlFile As [String] = "numbers.xml"
Try
Dim oXDoc As New XPathDocument(strXmlFile)
' Define the context node expression.
Dim temp As String = "//n"
Dim oDNav As XPathNavigator = oXDoc.CreateNavigator()
Dim expr As XPathExpression = oDNav.Compile(temp)
Dim oIterator As XPathNodeIterator = oDNav.Select(expr)
' Move to context.
If Not oIterator.MoveNext() Then
Console.WriteLine("Could not move to context node")
Return
End If
Console.WriteLine(oIterator.Current.Evaluate("position()"))
Catch ex As Exception
Console.WriteLine(ex)
Return False
End Try
Return True
[C#]
String strXmlFile = "numbers.xml";
try
{
XPathDocument oXDoc = new XPathDocument(strXmlFile);
// Define the context node expression.
string temp = "//n";
XPathNavigator oDNav= oXDoc.CreateNavigator();
XPathExpression expr = oDNav.Compile(temp);
XPathNodeIterator oIterator = oDNav.Select(expr);
// Move to context.
if(!oIterator.MoveNext())
{
Console.WriteLine("Could not move to context node");
return;
}
Console.WriteLine(oIterator.Current.Evaluate("position()"));
}
catch(Exception ex)
{
Console.WriteLine(ex);
return false;
}
return true;
See Also
XPathNavigator in the .NET Framework | XPath Select and XPathNavigator | XPath Matches and XPathNavigator