Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the difference between using "../" and "parent" in an XPath query?

Tags:

c#

asp.net

xpath

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.

like image 899
Rob Segal Avatar asked Dec 29 '22 22:12

Rob Segal


2 Answers

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.

like image 83
brabster Avatar answered Jan 27 '23 17:01

brabster


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

like image 40
Bert F Avatar answered Jan 27 '23 17:01

Bert F