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.
2
Answers
You haven’t said which XPath version you are using. This is quite hard to achieve using XPath 1.0 which is all that PHP’s DOMXPath supports.
Logically you can do
but the
except
operator requires XPath 2.0. A workaround is that in XPath 1.0 you can rewrite(A except B)
asA[count(.|B)!=count(B)]
but it’s potentially very inefficient.