htmlxpathxpath-1.0

Xpath: Extract text between tags, but stop as soon as an embedded tag occurs


I would like to extract the text within the following HTML. However, everything that occurs within an enclosed HTML tag and everything that comes after it should be ignored.

The HTML appears in different forms.

<span class="classA">Text 1 <span class="classB">Text 2</span> Text 3 <span class="classC">Text 4</span> Text 5</span>

Desired result: "Text 1 Text 2 Text 3"

Other variants:

<span class="classA">Text 1 <span class="classC">Text 2</span></span>
<span class="classA">Text 1 <span class="classC">Text 2</span> Text 3</span>
<span class="classA">Text 1</span>

Desired result: "Text 1"

<span class="classA">Text 1 <span class="classB">Text 2</span> Text 3</span>

Desired result: "Text 1 Text 2 Text3"

So everything after the occurrence of a span element with class "classC" should be ignored. It's also possible that "classC" doesn't appear at all.

I already tried //span[@class="classA"]//text()[parent::*[not(@class="classC")]], this ignores "classC" content, but returns the text after <span class="classC"> (Text 5 from the first example).

How can I achieve this?

Update:

With //span[@class="classC"]//parent::*/preceding::text() I'm getting a little closer to the matter. However, it still doesn't work with <span class="classA">Text 1</span>, which returns noting.


Solution

  • Try this XPath:

    //text()[not(preceding::span[@class="classC"]|ancestor::span[@class="classC"])]
    

    but as Michael Kay said it could be very inefficient, depending on your source html.