Reputation: 4078
today I stumbled upon a very interesting case (at least for me). I am messing around with Selenium and xPath and tried to get some elements, but got a strange behaviour:
<div class="resultcontainer">
<div class="info">
<div class="title">
<a>
some text
</a>
</div>
</div>
</div>
<div class="resultcontainer">
<div class="info">
<div class="title">
<a>
some other text
</a>
</div>
</div>
</div>
<div class="resultcontainer">
<div class="info">
<div class="title">
<a>
some even unrelated text
</a>
</div>
</div>
</div>
This is my data. When i run the following xPath query:
//div[@class="title"][1]/a
I get as a result ALL instead of only the first one. But if I query:
//div[@class="resultcontainer"][1]/div[@class="info"]/div[@class="title"]/a
I get only the first , not all.
Is there some divine reason behind that?
Best regards, bisko
Upvotes: 1
Views: 403
Reputation: 338326
I think you want
(//div[@class="title"])[1]/a
This:
//div[@class="title"][1]/a
selects all (<a>
elements that are children of) <div>
elements that have a @class
of 'title'
, that are the first children of their parents (in this context). Which means: it selects all of them.
The working XPath selects all <div>
elements that have a @class
of 'title'
- and of those it takes the first one.
The predicates (the expressions in square brackets []
) are applied to each element that matched the preceding location step (i.e. "//div"
) individually. To apply a predicate to a filtered set of nodes, you need to make the grouping clear with parentheses.
Consequently, this:
//div[1][@class="title"]/a
would select all <div>
elements, take the first one, and then filter it down futher by checking the @class
value. Also not what you want. ;-)
Upvotes: 2