XPath SelectNodes in .NET
Asked Answered
R

4

19
<Document>
  <A> 
    <B> 
      <C></C>
    </B>
  </A>
  <E>
   <F>
    <C></C>
   </F>
   <G>
    <C></C>
  </G>
 </E>
</Document>

If i load the above XML into an XmlDocument and do a SelectSingleNode on A using the XPath query //C

XmlNode oNode = oDocument.SelectSingleNode("E");
XmlNodeList oNodeList = oNode.SelectNodes("//C");

why does it return nodes from Under B when what I would expect to happen would that it only return nodes from under E

Make sense?

Edit : How would i make it only return from that node onwards?

Rosecan answered 17/2, 2009 at 21:49 Comment(0)
M
29

Simply: a leading // means "at any level" in the same document as the selected node.

From the spec:

  • //para selects all the para descendants of the document root and thus selects all para elements in the same document as the context node
  • .//para selects the para element descendants of the context node
Moderator answered 17/2, 2009 at 21:55 Comment(0)
P
11

Specifying .//C will achieve what you want, otherwise, the XPath starts from the document root rather than the current node.

The confusion is in the definition of // from the XPath standard as follows:

// is short for /descendant-or-self::node()/. For example, //para is short for /descendant-or-self::node()/child::para and so will select any para element in the document (even a para element that is a document element will be selected by //para since the document element node is a child of the root node); div//para is short for div/descendant-or-self::node()/child::para and so will select all para descendants of div children.

Because // is short for /descendant-or-self::node()/ it starts at the document level unless you specify a node at the start.

Perpetrate answered 17/2, 2009 at 21:56 Comment(3)
No, the spec says "//" is "of the document root", and ".//" is of the context node. The implementation is correct.Moderator
Re the W3 Schools ref: read carefully : "in the document from the current node" - the context node is used (only) to obtain the document; then the entire document is scanned.Moderator
Yes, I updated it to reference the XPath standard and highlight where the confusion lies. Thanks. :)Perpetrate
O
6

//C is all C nodes in the entire document

/E//C would be only C nodes under E

/C would be only the root C node

See the xpath syntax reference

Obligato answered 17/2, 2009 at 21:58 Comment(0)
P
3

In the XPATH Specification you will find under 2.5 the following statement:

//para selects all the para descendants of the document root and thus selects all para elements in the same document as the context node

i.e. the behaviour you observe is valid. You should do something like "/E//C"

Pegu answered 17/2, 2009 at 21:58 Comment(2)
What if i didn't know how many nodes deep C was ? It could well be /E/D/G/C ?Rosecan
@Gordon - "/E//C" will cope with any number of levels between the E and C.Moderator

© 2022 - 2024 — McMap. All rights reserved.