Reputation: 24930
I'm confused about what must be something basic, and previous questions (and the documentation) don't really help.
Say we have these 6 siblings:
<a_tag>... a1 ...</a_tag>
<b_tag>... b1 ...</b_tag>
<a_tag>... a2 ...</a_tag>
<b_tag>... b2 ...</b_tag>
<a_tag>... a3 ...</a_tag>
<b_tag>... b3 ...</b_tag>
Some xpath expressions work as I expect. For example, //a_tag
selects all 3 a_tags
; //a_tag[2]
selects only a2
.
Using //a_tag[following-sibling::b_tag]
selects, again, all 3 a_tags
.
Getting a little fancier, //a_tag[following-sibling::b_tag[2]]
correctly selects a1
and a2
. However, using //a_tag[following-sibling::b_tag[3]]
, selects only a1
, while I expected it to select all 3 a_tags
(because they are all followed by b_tag[3]
.
And then //a_tag[preceding-sibling::b_tag[1]][following-sibling::b_tag[2]]
selects a2
, as expected, but //a_tag[preceding-sibling::b_tag[2]][following-sibling::b_tag[3]]
, which I expected to select a3
comes up empty.
If you throw at it something which I would expect to select nothing, like //a_tag[preceding-sibling::b_tag[2]][following-sibling::b_tag[1]]
, selects a3
instead.
There are more like these, but I believe the problem is clear enough. Any light thrown on this would be appreciated.
Upvotes: 1
Views: 410
Reputation: 111541
However, using
//a_tag[following-sibling::b_tag[3]]
, selects onlya1
, while I expected it to select all 3a_tags
(because they are all followed byb_tag[3]
).
Here's how to adjust your model to match XPath's actual behavior:
//a_tag
a_tag
elements (as you mentioned).//a_tag[following-sibling::b_tag[3]]
a_tag
elements, select only those that have a third following sibling b_tag
element, which is only the single <a_tag>a1</a_tag>
, as observed.Upvotes: 1
Reputation: 14135
Ok, Let me explain how this works.
//a_tag[following-sibling::b_tag[$n]]
In general language this means get me all a_tag
s which have $n of following-siblings.
Consider the below example:
//a_tag[following-sibling::b_tag[1]]
This says get me all the a_tag
s which have 1 b_tag
after. Now, that all the a_tag
s in the example have 1 b_tag
after a_tag
s, you will see all 3 a_tag
s selected.
You will see only the first a_tag
selected when used below xpath, because that's the only tag which have 3 b_tag
s after.
//a_tag[following-sibling::b_tag[3]]
Coming to the below xpath
//a_tag[preceding-sibling::b_tag[1]][following-sibling::b_tag[2]]
When you have multiple conditions []
in xpath, it will execute from left to right meaning it will complete the left side condition then apply the next condition. So, the meaning of above xpath is get me all a_tag
s which have b_tag
s 1 before and 2 after, so a2
is the only node which have b1
(1 b_tag) before and b2 and b3
(2 b_tags) after.
//a_tag[preceding-sibling::b_tag[2]][following-sibling::b_tag[3]]
give you empty because you don't have a_tag
which have 2 b_tag
s before and 3 b_tags
after.
Now you should under why //a_tag[preceding-sibling::b_tag[2]][following-sibling::b_tag[1]]
selected a3
.
Hope I am clear.
Upvotes: 2