Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XML SelectNodes then SelectSingleNodes - only retrieves the first

Tags:

c#

xml

I have the following XML

<root>
<Operations>
    <OperationId>1</OperationId>
    <OtherFields>...</OtherFields>
</Operations>
<Operations>
    <OperationId>2</OperationId>
    <OtherFields>...</OtherFields>
</Operations>
<Operations>
    <OperationId>3</OperationId>
    <OtherFields>...</OtherFields>
</Operations>
</root>

Using C# and System.XML namespace I get all operations using this code:

XmlNodeList operations= doc.SelectNodes("/root/Operations");

Now I need to loop through each operation and reference the fields (OperationId, OtherFields).

I try this:

foreach (XmlNode node in xnodes)
{
    Console.WriteLine("Operation ID: {0}", node.SelectNodes("//OperationId")[0].InnerText);
}

However this just repeats the first OperationId - 1.

What is wrong?

Thanks, Andrew

like image 506
andrewb Avatar asked Oct 20 '25 22:10

andrewb


1 Answers

Your initial query selects all Operations nodes off the root like you're expecting. However your inner query in your loop does something different.

By starting your query with a //, you're querying relative to the root of the document. So you're actually selecting all OperationId nodes in the document, not just the descendant children of the current node. You then index the first node in that result for every iteration which is why you're seeing the first id repeating.

Since node refers to the current Operations node, to select the corresponding OperationId, your query should simply be:

OperationId

I should mention that since you're only trying to select the first element of the query, it would be better to use SelectSingleNode() instead of SelectNodes. If there are any nodes selected, the first will be returned.

node.SelectSingleNode("OperationId").InnerText

However since you're only trying to select an immediate child element, I wouldn't use an XPath query there, it's unnecessary. Just access the child element directly using the indexer.

var query = doc.SelectNodes("/root/Operations");
foreach (XmlNode node in query)
{
    Console.WriteLine("Operation ID: {0}", node["OperationId"].InnerText);
}
like image 58
Jeff Mercado Avatar answered Oct 22 '25 12:10

Jeff Mercado