Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XPath SelectNodes in .NET

Tags:

c#

xml

xpath

<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?

like image 916
Gordon Thompson Avatar asked Feb 17 '09 21:02

Gordon Thompson


People also ask

What is XmlNode in C#?

XmlNode is the base class in the . NET implementation of the DOM. It supports XPath selections and provides editing capabilities. The XmlDocument class extends XmlNode and represents an XML document. You can use XmlDocument to load and save XML data.

How do you select nodes?

Click a node. On the property bar, choose Rectangular from the Selection mode list box, and drag around the nodes that you want to select. On the property bar, choose Freehand from the Selection mode list box, and drag around the nodes you want to select. Hold down Shift, and click each node.

Does XPath use dom?

The XPath DOM extends the document order of the DOM Core to include the XPathNamespace nodes. Element nodes occur before their children. The attribute nodes and namespace nodes of an element occur before the children of the element. The namespace nodes are defined to occur before the attribute nodes.


4 Answers

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
like image 189
Marc Gravell Avatar answered Oct 13 '22 11:10

Marc Gravell


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.

like image 44
Jeff Yates Avatar answered Oct 13 '22 10:10

Jeff Yates


//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

like image 6
slf Avatar answered Oct 13 '22 11:10

slf


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"

like image 3
flq Avatar answered Oct 13 '22 10:10

flq