Reputation: 14682
best shown by a simplified example:
<?xml version="1.0" encoding="utf-8"?>
<root>
<A name="wrong"></A>
<B>not this</B>
<A name="right">
<subA></subA>
</A>
<B>yes, this</B> <!-- I want only this one -->
<A name="right">
<subA></subA>
</A>
<C>dont want this</C>
<B>not this either</B> <!-- not immediately following -->
</root>
I want all <B>
nodes that are immediately following an <A>
node with name
attribute equals "right"
.
What I tried:
//A[@name="right"]/following-sibling::*[1]
which selects any node immediately following the "right" <A>
(i.e. including <C>
). I don't see how to make it only <B>
. This didn't work:
//A[@name="right"]/following-sibling::*[1 and B]
This one:
//A[@name="right"]/following-sibling::B[1]
would select the first <B>
after the "right" <A>
, but not necessarily the immediately following one.
Upvotes: 17
Views: 27601
Reputation: 3451
You can try this //B[preceding-sibling::A[1][@name='right']]
This returns you node which you are interested in.
Hope this helps
Upvotes: 0
Reputation: 63338
You were nearly there:
//A[@name='right']/following-sibling::*[position()=1 and self::B]
gives exactly one node on your sample.
To refer to the element name in a condition, you need self
. Simply [B]
would mean an element with text exactly equal to B
.
Upvotes: 10
Reputation: 24826
Just to point out that you were not so far with the first XPath shown in your question:
//A[@name='right']/following-sibling::*[1][local-name()='B']
position()
is not indispensable here.
Upvotes: 3