For the example HTML below, an XPath query that returns the siblings of the "a" elements with class='A' that have class='B' can be written as: //a[@class='A']/following-sibling::a[@class='B']
. This query outputs 4 <a class="B"/>
elements.
However, I would only like the <a class="B"/>
elements that follow the current <a class="A"/>
element, and no others that follow other <a class="B"/>
elements/nodes. In other words, I only want the following <a class="B"/>
sibling elements until the next <a class="B"/>
element shows up.
Example HTML:
<a class='A' /> <a class='B' /> <a class='A' /> <a class='B' /> <a class='B' /> <a class='B' />
Any ideas on how to limit my current XPath query to just those siblings would be much appreciated :)
We can use the concept of following-sibling in xpath for identifying elements in Selenium. It identifies the siblings of the context node. The siblings should be located at the equal level of the existing node and should have the same parent.
In this diagram, the preceding:: nodes are circled, and the more specific preceding-sibling:: nodes are given a red border. The preceding-siblings are nodes that share the same parent node, and come before the current node in the document. The preceding:: node is any node that comes before the element in the document.
The following-sibling and preceding-sibling axes contain the siblings before or after the context node, and the following and preceding axes contain all nodes in the document before or after the context node, but: None of these axes contain attribute or namespace nodes.
To select all a
elements having a class
attribute of B
between some specific a
with a class
equal to A
and the next such occurrence:
/*/a[@class='A'][$n]/following-sibling::a[ @class='B' and count(preceding-sibling::a[@class='A'])=$n]
This selects everything between the nth a[@class='A']
and the next such element. For a specific example, consider the following input:
<r> <a class="A"/> <a class="B"/> <a class="A"/> <a class="B"/> <a class="B"/> <a class="A"/> <a class="B"/> <a class="B"/> <a class="B"/> </r>
To get the two elements between the second <a class="A"/>
and the third <a class="A"/>
:
/*/a[@class='A'][2]/following-sibling::a[ @class='B' and count(preceding-sibling::a[@class='A'])=2]
In English, this says:
Give me all of the
a
elements having aclass
attribute whose value is equal toB
that come after the seconda
having a class attribute equal toA
and that have only two preceding siblings having aclass
attribute equal toA
Similarly, and more generally, we can apply the Kayessian method for finding the intersection of two node sets. In the example given, we want the intersection of all the @class='B'
elements in 1) the set of siblings after the second <a class="A"/>
and 2) the set of siblings before the third <a class="A"/>
. The intersection of these two sets is precisely the nodes that come between those two divider elements and can be expressed like this:
/*/a[@class='A'][2]/following-sibling::a[@class='B'][ count(.|/*/a[@class='A'][3]/preceding-sibling::a[@class='B'])= count(/*/a[@class='A'][3]/preceding-sibling::a[@class='B'])]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With