1

I got the following (simplified) HTML:

    <ul>
        <li class="item c-MessageRow green">
            <div>Hello and </div>
            <div>welcome
                <div> to</div>
            </div>
            <div> my site</div>
        </li>
    </ul>

Now I'd like to select the li element which has the class "c-MessageRow" and contains the inner text "welcome to my site".

I've tried the following:

//li[contains(@class, 'c-MessageRow') and contains(text(), 'welcome to my site')]

But it returns nothing. What could I be doing wrong here?

1 Answer 1

3

When you e.g. change the Xpath to

//li[contains(@class, 'c-MessageRow') and contains(div/text(), 'Hello')]

or

//li[contains(@class, 'c-MessageRow') and 
     contains(div/following-sibling::div/text(), 'welcome')]

the li is returned. The issue with your Xpath is that the li with the class c-MessageRow does not contain the text 'welcome to my site', but a div with the text 'Hello', another div with the text 'welcome' etc. Question is if you have to check if the full text is contained in the li or if matching only a part of it is sufficient.

Update for the comment: Checking for the class and the complete text of the li could be done like this:

//li[contains(@class, 'c-MessageRow') and 
  contains(normalize-space(string(self::li)), 'welcome to my site')] 

The normalize-space() takes care about removing any trailing or leading whitespace and linebreaks. This is necessary as using the Xpath string(//li) (results may vary, tested with an online Xpath tester) looks like this:

Hello and 
        welcome
             to

         my site

while using normalize-space(string(//li)) results in:

Hello and welcome to my site
Sign up to request clarification or add additional context in comments.

3 Comments

Ahh I see. I thought text() returned the entire inner text of the node (with the inner texts of all subnodes) but am I right to assume it only returns the direct inner text of the first node?
@JensOlsen112 Yes, you got that right. And the li itself doesn't contain any text. You'll get the full text of the li using string - e.g. string(//li) (just as aside, as this might not be useful for your match pattern).
Ahh I didn't know about the string() method. Thanks a lot that's exactly what I was looking for!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.