tags:

views:

66

answers:

1

Hello, 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

+2  A: 

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. ;-)

Tomalak
Hm, never crossed my mind, thanks!
bisko