ChatGPT解决这个技术问题 Extra ChatGPT

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

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>
YOu need to post input xml atleast a part of what you want to write xpath for ?
Do you mean ...and contains(span, 'someText')]?
That's what I thought, but then I get "no matching nodes" in FirePath validator
@SamiKuhmonen - Close. It would be ` and contains(div/span, 'someText')]`
Yes, seeing the example it would be div/span

C
Community

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.


Screen-scraping is always by its nature pretty fragile.
is there any way to select an element whose child's class contains specific text?
D
DowntownDev

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')]

More info on "axes" (of which ancestor is one): w3schools.com/xml/xpath_axes.asp
S
SomeDude

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>'

That would select the span and not the div.
I thought OP wanted span
I tried to make it as explicit as possible with the <-- comment :)
S
Sami Kuhmonen

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.


Accepting nwellnhof's answer as he got it first, but +1 for the alternative. cheers.