tags:

views:

410

answers:

2

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.

+4  A: 

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.

Brabster
Huh? Doesn't your quick answer basically say: yes they are the same, but no, they are different?
Bert F
Updated to make it clearer
Brabster
This is great Brabster. Seems most of my confusion came from the use of "*" on the end of the XPath query and what exactly that is returning.
Rob Segal
+4  A: 

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

Bert F
Great description Bert. The XPath test page link was great for testing out some searches and viewing the results. Helped alot.
Rob Segal
+1 for the useful link!
Dror