What is the difference here between using "../" and "parent" to get the parent node in an XPath query. I had thought they were synonymous.
Given the following two XPath queries is there really any difference between these two?
//Node/id[@type='image']/id[@attr1='myVal']/../../*
//Node/id[@type='image']/id[@attr1='myVal']/parent::*/parent::*
I am working on a C#/ASP.net application and using the first XPath query I get back actually the first sibling previous to the Node element. What I am looking for is the Node element itself and all its children. The second XPath query will give me my expected result.
I am wondering why there is a difference here.
Quick answer; yes, ../ and parent::* are equivalent but you get different results because your XPath expressions are different.
Longer answer;
The expressions parent::node() and .. are equivalent, the latter being an abbreviated form of the former according to the W3C XPath Recommendation.
You will get similar behaviour from parent::*, because XML forms a tree, so any child can have at most one parent.
The reason you will get different results is because they are different queries. The first has an extra * on the end (../../*), which is probably returning the child item sequence of your Node.
The second gets specifically the parent of the parent of the context node (in abbreviated form ../..), which is your Node element of interest.
Example:
For the document
<?xml version="1.0" encoding="UTF-8"?>
<root>
<Node>
<id type="image">
<id attr1="myVal"> </id>
</id>
</Node>
</root>
The queries
//Node/id[@type='image']/id[@attr1='myVal']/../../*
and
//Node/id[@type='image']/id[@attr1='myVal']/parent::*/parent::*/*
return the node id[@type='image']
Whereas the queries
//Node/id[@type='image']/id[@attr1='myVal']/../..
and
//Node/id[@type='image']/id[@attr1='myVal']/parent::*/parent::*
return the node Node.
You aren't getting the same result set because *your expressions are not equivalent to each other.*
Consider:
1. The grandchild of target node
//Node/id[@type='image']/id[@attr1='myVal']
2. The child of target node (parent of grandchild) (equivalent exprs)
//Node/id[@type='image']/id[@attr1='myVal']/..
//Node/id[@type='image']/id[@attr1='myVal']/parent::*
3. The target node (grandparent of grandchild) (equivalent exprs)
//Node/id[@type='image']/id[@attr1='myVal']/../..
//Node/id[@type='image']/id[@attr1='myVal']/parent::*/parent::* <-- * * * YOUR 2ND EXPR * * *
4. All children of target node (equivalent exprs)
//Node/id[@type='image']/id[@attr1='myVal']/../../* <-- * * * YOUR 1ST EXPR * * *
//Node/id[@type='image']/id[@attr1='myVal']/parent::*/parent::*/*
Try the equivalent of your expressions (e.g. '//parent/child[@id="2"]/grandchild[@id="2.1"]/../../*') at the XPath testbed linked below. It highlights in red which nodes match the various XPath expressions you feed it.
http://www.whitebeam.org/library/guide/TechNotes/xpathtestbed.rhtm
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