I have an xml file with the following format
<someXML>
<a>
<b></b>
<b test='someValue'></b>
</a>
<c>
<d test='someOtherValue'></d>
<d></d>
</c>
</someXML>
I'm trying to write C# code that will get me a node set containing only those nodes with the test attribute. I am trying to use an XPathExpression in this manner:
XDocument document = XDocument.Load("someXML");
XPathNavigator navigator = document.CreateNavigator();
XPathExpression expression = XPathExpression.Compile("//*[@test]");
object nodeSet = navigator.Evaluate(expression);
This doesn't seem to be working. When I debug, the nodeSet always contains the Root element. Is there something wrong with the expression or is this working correctly?
Thanks!
Do you assume that the nodeSet contains the “Root” element because the debugger displays its string representation as Position=0, Current={Root}? That may be misleading; the reason that the “Root” element appears is because the XPathNodeIterator (which is the actual type returned by Evaluate in your case) has not yet been positioned on the first node resulting from the query. Per the MSDN documentation for XPathNodeIterator:
An
XPathNodeIteratorobject returned by theXPathNavigatorclass is not positioned on the first node in a selected set of nodes. A call to theMoveNextmethod of theXPathNodeIteratorclass must be made to position theXPathNodeIteratorobject on the first node in the selected set of nodes.
You can retrieve your path items by iterating over your nodeSet:
XDocument document = XDocument.Load("someXML");
XPathNavigator navigator = document.CreateNavigator();
XPathExpression expression = XPathExpression.Compile("//*[@test]");
XPathNodeIterator nodeSet = (XPathNodeIterator)navigator.Evaluate(expression);
foreach (XPathItem item in nodeSet)
{
// Process item here
}
Or, if you want them converted to an array:
XDocument document = XDocument.Load("someXML");
XPathNavigator navigator = document.CreateNavigator();
XPathExpression expression = XPathExpression.Compile("//*[@test]");
XPathNodeIterator nodeSet = (XPathNodeIterator)navigator.Evaluate(expression);
XPathItem[] items = nodeSet.Cast<XPathItem>().ToArray();
Your XPath does work, it's just you need to retrieve nodes a bit differently:
XPathNavigator navigator = document.CreateNavigator();
XPathExpression expression = XPathExpression.Compile("//*[@test]");
var matchedNodes = navigator.Select(expression);
foreach (XPathNavigator node in matchedNodes)
{
Console.WriteLine(node.UnderlyingObject);
}
Snippet above will print the following:
<b test='someValue'></b>
<d test='someOtherValue'></d>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With