XPath: Get parent node from child node

I need get the parent node for child node title 50

At the moment I am using only

//*[title="50"]

How could I get its parent? Result should be the store node.


<?xml version="1.0" encoding="utf-8"?>
<d:data xmlns:d="defiant-namespace" d:mi="23"> <store d:mi="22"> <book price="12.99" d:price="Number" d:mi="4"> <title d:constr="String" d:mi="1">Sword of Honour</title> <category d:constr="String" d:mi="2">fiction</category> <author d:constr="String" d:mi="3">Evelyn Waugh</author> </book> <book price="8.99" d:price="Number" d:mi="9"> <title d:constr="String" d:mi="5">Moby Dick</title> <category d:constr="String" d:mi="6">fiction</category> <author d:constr="String" d:mi="7">Herman Melville</author> <isbn d:constr="String" d:mi="8">0-553-21311-3</isbn> </book> <book price="8.95" d:price="Number" d:mi="13"> <title d:constr="String" d:mi="10">50</title> <category d:constr="String" d:mi="11">reference</category> <author d:constr="String" d:mi="12">Nigel Rees</author> </book> <book price="22.99" d:price="Number" d:mi="18"> <title d:constr="String" d:mi="14">The Lord of the Rings</title> <category d:constr="String" d:mi="15">fiction</category> <author d:constr="String" d:mi="16">J. R. R. Tolkien</author> <isbn d:constr="String" d:mi="17">0-395-19395-8</isbn> </book> <bicycle price="19.95" d:price="Number" d:mi="21"> <brand d:constr="String" d:mi="19">Cannondale</brand> <color d:constr="String" d:mi="20">red</color> </bicycle> </store>
</d:data>

4 Answers

Use the parent axes with the parent node's name.

//*[title="50"]/parent::store

This XPath will only select the parent node if it is a store.

But you can also use one of these

//*[title="50"]/parent::*
//*[title="50"]/..

These xpaths will select any parent node. So if the document changes you will always select a node, even if it is not the node you expect.

EDIT

What happens in the given example where the parent is a bicycle but the parent of the parent is a store?

Does it ascent?

No, it only selects the store if it is a parent of the node that matches //*[title="50"].

If not, is there a method to ascent in such cases and return None if there is no such parent?

Yes, you can use ancestor axes

//*[title="50"]/ancestor::store

This will select all ancestors of the node matching //*[title="50"] that are ` stores. E.g.

<data xmlns:d="defiant-namespace" d:mi="23"> <store mi="1"> <store mi="22"> <book price="8.95" d:price="Number" d:mi="13"> <title d:constr="String" d:mi="10">50</title> <category d:constr="String" d:mi="11">reference</category> <author d:constr="String" d:mi="12">Nigel Rees</author> </book> </store> </store>
</data>

XPath selection result

7

Just as an alternative, you can use ancestor.

//*[title="50"]/ancestor::store

It's more powerful than parent since it can get even the grandparent or great great grandparent

3

You can use the two dots at the end of expression, too. See this example:

//*[title="50"]/..

New, improved answer to an old, frequently asked question...

How could I get its parent? Result should be the store node.

Use a predicate rather than the parent:: or ancestor:: axis

Most answers here select the title and then traverse up to the targeted parent or ancestor (store) element. A simpler, direct approach is to select parent or ancestor element directly in the first place, obviating the need to traverse to a parent:: or ancestor:: axes:

//*[book/title = "50"]

Should the intervening elements vary in name:

//*[*/title = "50"]

Or, in name and depth:

//*[.//title = "50"]
0

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

You Might Also Like