防止 lxml 在匹配元素后选择下一个文本节点

Prevent lxml selecting next text node after matched element

我需要在一些 HTML 字符串模板中找到 <div>id="XXX":

from lxml import html

template = '''
Text node 1
<div id="XXX">XXX content</div>
Text node 2
'''

tree = html.fromstring(template)
element = tree.get_element_by_id('XXX')
result = html.tostring(element).decode('utf-8')

print(result)

>>> <div id="XXX">XXX content</div>
>>> Text node 2

它 selects <div> 和下一个 Text node 1 由于一些奇怪的原因


如果我用另一个 <div> 包裹 <div id="XXX">XXX content</div> 到:

Text node 1
<div>
    <div id="XXX">XXX content</div>
</div>
Text node 2

一切都更好了,它打印匹配的 <div id="XXX"> 和一个空行(已解码 \n):

>>> print(result)
<div id="XXX">XXX content</div>
\n

如果我在 <div id="XXX"> 之后添加一些 <div> 到:

Text node 1
<div id="XXX">XXX content</div>
<div></div>
Text node 2

一切也更好,它打印匹配的 <div id="XXX"> 和一个空行(已解码 \n):

>>> print(result)
<div id="XXX">XXX content</div>
\n

以前的 Text node 1 从未受影响 - 至少这没问题)

那么,是否可以指定某些内容不用于 select 下一个文本节点? 太棒了,如果 \n 也不会匹配,但我可以接受

请告诉我,如果这个问题与 lxml 无关,而是与 XPath 相关

P.S。 BeautifulSoup 没有这个问题,即使使用相同的 lxml 模块作为解析器,它甚至不匹配下一个 \n

版本:

>>> python
Python 3.7.3

>>> pip show lxml
Version: 4.3.4

看来有时候只能使用蛮力了:

tree = html.fromstring(template)
element = tree.get_element_by_id('XXX')

element.tail = None #brute force in action....

result = html.tostring(element).decode('utf-8')
print(result)

输出想要的

<div id="XXX">XXX content</div>

现在轮到比我聪明的人来解释为什么我们需要求助于此...