tags:

views:

62

answers:

2

for example, i have this xml

<elements>
<a>
     <b>6</b> 
     <b>5</b>
     <b>6</b>
</a>
<a>
     <b>5</b>
     <b>5</b>
     <b>6</b>
</a>
<a>
     <b>5</b>
     <b>5</b>
     <b>5</b>
     <b>5</b>
</a>
</elements>

i need a xpath query, which must return me parent tag, only if all its children are equal to 5 (a[3] in this case). Something like that

//b[text()="5"]/..

but with check of all children's tags. Please note that number of children tags can be different from node to node.

It's possible with only xpath query?

thanks

+4  A: 
/elements/a[count(b) = count(b[.="5"])]
Pavel Minaev
awesome! thanks!
cru3l
@Pavel. Good to know. I know the count() function but what is this "."?
Syd
`.` is "itself", the current context item - an element in this case. In this case, since there is a string on the left, the element will be stringified.
Pavel Minaev
@cru3l: Josh's answer below is likely to yield better results, by the way, and is simpler to boot, so you might want to accept it.
Pavel Minaev
+2  A: 

Instead of looking for elements where all <b/> equal 5, you can look for elements that do not have any <b/> not equal 5. It is semantically the same thing but it's more performant because you don't have to consider all the children, if any of them are not "5" the XPath engine can bail early without evaluating the rest.

In other words, "all b are 5" is the same as "there is no b that isn't 5."

/elements/a[not(b != "5")]

Note that both expressions are true if there is no <b/> at all, you'd have to add another predicate for that.

Josh Davis
great idea! thanks!
cru3l