15
votes

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?

4
Your XPath is correct. Which processor are you using, either it does have some serious bug or you might be calling it wrong. As a side note, I think /li[contains(span, 'Text1')] Is a bit more elegant and shorter. You certainly con't need the text(), just use . as it will be automatically converted to an atomic value. - dirkk
Your second XPath does appear correct. Perhaps a namespace issue? Is your XML actually in a namespace? - adamretter
Just for clarification, because it got a few upvotes over the years: it's been a namespace problem. - D.R.

4 Answers

22
votes

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

/root/li[span[contains(text(), "Text1")]]
17
votes
//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

1
votes

Try this XPath

li/*[@innertext='text']
1
votes

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