Xpath: select div that contains class AND whose specific child element contains text

Xpath

Xpath Problem Overview


With the help of this SO question I have an almost working xpath:

//div[contains(@class, 'measure-tab') and contains(., 'someText')]

However this gets two divs: in one it's the child td that has someText, the other it's child span.

How do I narrow it down to the one with the span?

<div class="measure-tab">
  <!-- table html omitted -->
  <td> someText</td>
</div>

<div class="measure-tab">  <-- I want to select this div (and use contains @class)
  <div>
    <span> someText</span>  <-- that contains a deeply nested span with this text
  </div>
</div>

Xpath Solutions


Solution 1 - Xpath

To find a div of a certain class that contains a span at any depth containing certain text, try:

//div[contains(@class, 'measure-tab') and contains(.//span, 'someText')]

That said, this solution looks extremely fragile. If the table happens to contain a span with the text you're looking for, the div containing the table will be matched, too. I'd suggest to find a more robust way of filtering the elements. For example by using IDs or top-level document structure.

Solution 2 - Xpath

You can use ancestor. I find that this is easier to read because the element you are actually selecting is at the end of the path.

//span[contains(text(),'someText')]/ancestor::div[contains(@class, 'measure-tab')]

Solution 3 - Xpath

You could use the xpath :

//div[@class="measure-tab" and .//span[contains(., "someText")]]

Input :

<root>
<div class="measure-tab">
  <td> someText</td>
</div>
<div class="measure-tab">
  <div>
    <div2>
       <span>someText2</span>
   </div2>
  </div>
</div>
</root>

Output :

    Element='<div class="measure-tab">
  <div>
    <div2>
      <span>someText2</span>
    </div2>
  </div>
</div>'

Solution 4 - Xpath

You can change your second condition to check only the span element:

...and contains(div/span, 'someText')]

If the span isn't always inside another div you can also use

...and contains(.//span, 'someText')]

This searches for the span anywhere inside the div.

Categories
Recommended Xpath Solutions

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAndrejsView Question on Stackoverflow
Solution 1 - XpathnwellnhofView Answer on Stackoverflow
Solution 2 - XpathAlex PayneView Answer on Stackoverflow
Solution 3 - XpathSomeDudeView Answer on Stackoverflow
Solution 4 - XpathSami KuhmonenView Answer on Stackoverflow