'Select a node with XPath whose child node contains a specific inner text

Given the following XML:

<root>
    <li><span>abcText1cba</span></li>
    <li><span>abcText2cba</span></li>
</root>

I want to select all li elements having a span child node containing an inner text of Text1 - using an XPath.

I started off with /root/li[span] and then tried to further check with: /root/li[span[contains(text(), 'Text1')]]

However, this does not return any nodes. I fail to see why, can somebody help me out?



Solution 1:[1]

Just for readers. The xpath is correct. OP: Perhaps xpath parser didnt support the expression?

/root/li[span[contains(text(), "Text1")]]

Solution 2:[2]

//li[./span[contains(text(),'Text1')]] - have just one target result
//li[./span[contains(text(),'Text')]] - returns two results as target

This approach is using something that isn't well documented anywhere and just few understands how it's powerful

enter image description here

Element specified by Xpath has a child node defined by another xpath

enter image description here

Solution 3:[3]

Try this XPath

li/*[@innertext='text']

Solution 4:[4]

Your current xpath should be correct. Here is an alternative but ugly one.

XmlNodeList nodes = doc.SelectNodes("//span/parent::li/span[contains(text(), 'Text1')]/parent::li");

We find all the span-tags. Then we find all the li-tags that has a span-tag as child and contains the 'Text1'.

OR simply:

//span[contains(text(), 'Text1')]/parent::li

Solution 5:[5]

the xpath Kent Kostelac provided:

//span[contains(text(), 'Text1')]/parent::li

could be also be presented as so:

//li[span[contains(text(), 'Text1')]]

which is a bit shorter and provides improved readability by saying "give me the li that contains the span that displays 'Text1'"; instead of saying "can you see that span that dispalys 'Text1'? ok, so give me its li parent", which is what the original phrasing is actually saying.

Solution 6:[6]

To check things in deeply nested children use .//* in your Xpath expression.

<div class="foo h1">
    <p>
      <span>
         <b>bar</b>
      </span>
    </p>
</div>

To find a div with class .foo which also contains a child with text bar just use the following xpath expression

$x('//div[contains(@class, "foo") and .//*[contains(text(), "bar")]]')

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Daniel Kereama
Solution 2 Adeel
Solution 3 Valiantsin Lopan
Solution 4
Solution 5
Solution 6 supersan