Flutter Shy
Flutter Shy

Reputation: 51

XPath: Select first element with specific attribute

The XPath //img[contains(@class, 'check')]/ancestor::tr//span[contains(@class, 'date-display-single')] works, but the problem I have is there is two <span> with that class in each row.

Which results in:

[nodeValue] => Friday 7 October 2016
[nodeValue] => Fri 7 Oct 2016
[nodeValue] => Friday 21 October 2016
[nodeValue] => Fri 21 Oct 2016
[nodeValue] => Friday 4 November 2016
[nodeValue] => Fri 4 Nov 2016

What I want is the first <span>:

[nodeValue] => Friday 7 October 2016
[nodeValue] => Friday 21 October 2016
[nodeValue] => Friday 4 November 2016

How can I do this?

Edit: HTML

<table class="views-table cols-6">
    <thead>
        <tr>
            <th class="a" scope="col"></th>
            <th class="a" scope="col"></th>
            <th class="a" scope="col">1</th>
            <th class="a" scope="col">2</th>
            <th class="a" scope="col">3</th>
            <th class="a" scope="col">4</th>
        </tr>
    </thead>
    <tbody>
        <tr class="odd views-row-first">
            <td class="a"><span class="date-display-single">Friday 7
            October 2016</span></td>
            <td class="a"><span class="date-display-single">Fri 7 Oct
            2016</span></td>
            <td class="a"><img alt="Yes" class="check" src="image.png"
            title="Yes"></td>
            <td class="a"></td>
            <td class="a"></td>
            <td class="a"></td>
        </tr>
        <tr class="even">
            <td class="a"><span class="date-display-single">Friday 14
            October 2016</span></td>
            <td class="a"><span class="date-display-single">Fri 14 Oct
            2016</span></td>
            <td class="a"></td>
            <td class="a"><img alt="Yes" class="check" src="image.png"
            title="Yes"></td>
            <td class="a"><img alt="Yes" class="check" src="image.png"
            title="Yes"></td>
            <td class="a"><img alt="Yes" class="check" src="image.png"
            title="Yes"></td>
        </tr>
    </tbody>
</table>

Upvotes: 0

Views: 439

Answers (2)

kjhughes
kjhughes

Reputation: 111491

This XPath, based on your original XPath,

//img[contains(@class, 'check')]/ancestor::tr/td[1]/span[contains(@class, 'date-display-single')]

will select only the stated span elements that are in the first td within each stated tr:

<span class="date-display-single">Friday 7
            October 2016</span>
<span class="date-display-single">Friday 14
            October 2016</span>

as requested.

Note, however, this shorter XPath will also select the same elements:

//tr[.//img[@class='check']]/td[1]/span[@class='date-display-single']

This is fine as long as you can assume single-values for @class attributes. If you cannot, your solution has a serious substring problem whose standard solution involves concatenating spaces around the targeted class value:

[contains(concat(' ',@class,' '), ' check ')]

This technique could be applied to the above XPath for both the check and date-display-single tests.

Upvotes: 1

Kirill Polishchuk
Kirill Polishchuk

Reputation: 56162

You can use index, e.g.:

(your XPath here)[1]

Upvotes: 0

Related Questions