Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XPath to find nearest ancestor element that contains an element that has an attribute with a certain value

Tags:

xpath

ancestor::foo[bar[@attr="val"]]

I thought this would work, but it's not. I need to find the nearest foo element going up in the tree that has a bar child element, which in turn has an attr attribute of val.

like image 365
Core Xii Avatar asked Jun 09 '10 11:06

Core Xii


2 Answers

This should work:

//*[ancestor::foo[bar[@attr="val"]]] 

or alternatively

root/foo/bar[ancestor::foo[bar[@attr="val"]]] 

matches the second <bar> element

<root>     <foo>         <bar attr="xxx"></bar>     </foo>     <foo>         <bar attr="val"></bar>     </foo>     <foo>         <bar attr="zzz"></bar>     </foo> </root> 
like image 144
Gordon Avatar answered Oct 01 '22 02:10

Gordon


Updated to reflect a solution intended by OP.

See @David's answer

For a sample xml below,

<root> <foo id="0">     <bar attr="val"/>     <foo id="1">         <bar attr="xxx"/>     </foo>     <foo id="2">         <bar attr="val">             <one>1</one>             <two>                 <three>3</three>             </two>         </bar>     </foo> </foo> 

a valid xpath on the reverse axis with <three> as the context node, a valid solution is

./ancestor::foo[bar[@attr='val']][position() = 1] 

"./" is optional. position() = 1 is not optional as otherwise the ancestor foo satisfying the predicates would also be returned.

Old answer:ignore

This is an old question. but anybody who is interested, the following should get you what the original question intended.

Reverse axis

//bar[@attr='val']/ancestor::*[position()=1] 

Forward axis

//*[child::bar[@attr='val']] 
like image 41
santon Avatar answered Oct 01 '22 03:10

santon