Reputation: 150
I need to find a child node in a xml file which is inside a recursive parent-child attribute. Here is an xml sample:
<root>
<element>
<nodeA>
<nodeB>
<nodeA>
<nodeB>
<nodeA>
<nodeB></nodeB>
<nodeB></nodeB>
<nodeB></nodeB>
</nodeA>
</nodeB>
<nodeB>
<nodeA>
<nodeB></nodeB>
<nodeB></nodeB>
</nodeA>
</nodeB>
<nodeB>
<nodeA>
<nodeB></nodeB>
</nodeA>
</nodeB>
</nodeA>
</nodeB>
<nodeB>
<nodeA>
<nodeB>
<nodeA>
<nodeB></nodeB>
</nodeA>
</nodeB>
</nodeA>
</nodeB>
</nodeA>
</element>
</root>
I can find all nodes without a nodeA child with:
//nodeB[not(nodeA)]
but I need to select the first (and only the first) nodeB
group without a nodeA
child, practically the first three occurences of nodeB
in the example above.
Upvotes: 1
Views: 967
Reputation: 616
Here is
(//nodeA)[nodeB[not(nodeA)]][1]/nodeB
Your XPath is almost right - you just need to UP on one level (to nodeA group) and choose first one. Note that XPath collection are 1-indexed instead of classic 0-indexed.
UPD: And round brackets to correctly control the priority of operators.
Upvotes: 1
Reputation: 6449
With the query you've already got you're only a couple steps away from what you want.
Starting with //nodeB[not(nodeA)]
you want to go up one level to the parents /..
, but you only want the parent of the first group (//nodeB[not(nodeA)]/..)[1]
and of course you want the nodeBs without child nodeAs for the final result of:
(//nodeB[not(nodeA)]/..)[1]/nodeB[not(nodeA)]
Upvotes: 1