andrewb
andrewb

Reputation: 3095

XML SelectNodes then SelectSingleNodes - only retrieves the first

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

Upvotes: 4

Views: 3934

Answers (1)

Jeff Mercado
Jeff Mercado

Reputation: 134591

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);
}

Upvotes: 7

Related Questions