如何使用 Python 从 lxml 元素获取原始文本
How to get the raw text from lxml element with Python
我想从根元素中获取以下内联文本字符串。
from lxml import etree
root = root = etree.fromstring(
'''<p>
text-first
<span>
Child 1
</span>
text-middle
<span>
Child 2
</span>
text-last
</p>''')
root.text
仅 returns "text-first" 包括换行符
>>> build_text_list = etree.XPath("//text()")
>>> texts = build_text_list(root)
>>>
>>> texts
['\n text-first\n ', '\n Child 1\n ', '\n text-middle\n ', '\n Child 2\n ', '\n text-last\n']
>>>
>>> for t in texts:
... print t
... print t.__dict__
...
text-first
{'_parent': <Element p at 0x10140f638>, 'is_attribute': False, 'attrname': None, 'is_text': True, 'is_tail': False}
Child 1
{'_parent': <Element span at 0x10140be18>, 'is_attribute': False, 'attrname': None, 'is_text': True, 'is_tail': False}
text-middle
{'_parent': <Element span at 0x10140be18>, 'is_attribute': False, 'attrname': None, 'is_text': False, 'is_tail': True}
Child 2
{'_parent': <Element span at 0x10140be60>, 'is_attribute': False, 'attrname': None, 'is_text': True, 'is_tail': False}
text-last
{'_parent': <Element span at 0x10140be60>, 'is_attribute': False, 'attrname': None, 'is_text': False, 'is_tail': True}
>>>
>>> root.xpath("./p/following-sibling::text()") # following
[]
那么,我怎样才能从中得到 text-first/middle/last
部分呢?
我的错,xpath
最后救了我
>>> root.xpath('child::text()')
['\n text-first\n ', '\n text-middle\n ', '\n text-last\n']
print(root.xpath('normalize-space(//*)'))
etree 完全有能力做到这一点:
from lxml import etree
root: etree.Element = etree.fromstring(
'''<p>
text-first
<span>
Child 1
</span>
text-middle
<span>
Child 2
</span>
text-last
</p>''')
print(
root.text,
root[0].tail,
root[1].tail,
)
所有元素都是其子元素的列表,所以这里的索引指的是2个<span>
元素。任何元素的 tail 属性包含紧跟在该元素之后的文本。
它当然会包括换行符,所以你可能想要 strip() 结果:root.text.strip()
您的初步猜测,//text()
表示:select 所有文本节点,无论它们在文档中的哪个位置。如果它们是 p
的直接子节点,或者如果它们不是 span
.
的子节点,那么您实际上想要 select 的是文本节点
根据您显示的输入文档,最准确的答案是 /p/text()
:
>>> root = etree.fromstring(
'''<p>
text-first
<span>
Child 1
</span>
text-middle
<span>
Child 2
</span>
text-last
</p>''')
>>> etree.XPath("/p/text()")(root)
['\n text-first\n ', '\n text-middle\n ', '\n text-last\n']
您自己的解决方案 child::text()
表示:select 个文本节点,如果它们是当前上下文节点的子节点。它之所以有效,是因为在这种情况下,XPath 表达式是使用根元素 p
作为上下文来求值的。这就是为什么 text()
也有效的原因。
>>> etree.XPath("text()")(root)
['\n text-first\n ', '\n text-middle\n ', '\n text-last\n']
我想从根元素中获取以下内联文本字符串。
from lxml import etree
root = root = etree.fromstring(
'''<p>
text-first
<span>
Child 1
</span>
text-middle
<span>
Child 2
</span>
text-last
</p>''')
root.text
仅 returns "text-first" 包括换行符
>>> build_text_list = etree.XPath("//text()")
>>> texts = build_text_list(root)
>>>
>>> texts
['\n text-first\n ', '\n Child 1\n ', '\n text-middle\n ', '\n Child 2\n ', '\n text-last\n']
>>>
>>> for t in texts:
... print t
... print t.__dict__
...
text-first
{'_parent': <Element p at 0x10140f638>, 'is_attribute': False, 'attrname': None, 'is_text': True, 'is_tail': False}
Child 1
{'_parent': <Element span at 0x10140be18>, 'is_attribute': False, 'attrname': None, 'is_text': True, 'is_tail': False}
text-middle
{'_parent': <Element span at 0x10140be18>, 'is_attribute': False, 'attrname': None, 'is_text': False, 'is_tail': True}
Child 2
{'_parent': <Element span at 0x10140be60>, 'is_attribute': False, 'attrname': None, 'is_text': True, 'is_tail': False}
text-last
{'_parent': <Element span at 0x10140be60>, 'is_attribute': False, 'attrname': None, 'is_text': False, 'is_tail': True}
>>>
>>> root.xpath("./p/following-sibling::text()") # following
[]
那么,我怎样才能从中得到 text-first/middle/last
部分呢?
我的错,xpath
最后救了我
>>> root.xpath('child::text()')
['\n text-first\n ', '\n text-middle\n ', '\n text-last\n']
print(root.xpath('normalize-space(//*)'))
etree 完全有能力做到这一点:
from lxml import etree
root: etree.Element = etree.fromstring(
'''<p>
text-first
<span>
Child 1
</span>
text-middle
<span>
Child 2
</span>
text-last
</p>''')
print(
root.text,
root[0].tail,
root[1].tail,
)
所有元素都是其子元素的列表,所以这里的索引指的是2个<span>
元素。任何元素的 tail 属性包含紧跟在该元素之后的文本。
它当然会包括换行符,所以你可能想要 strip() 结果:root.text.strip()
您的初步猜测,//text()
表示:select 所有文本节点,无论它们在文档中的哪个位置。如果它们是 p
的直接子节点,或者如果它们不是 span
.
根据您显示的输入文档,最准确的答案是 /p/text()
:
>>> root = etree.fromstring(
'''<p>
text-first
<span>
Child 1
</span>
text-middle
<span>
Child 2
</span>
text-last
</p>''')
>>> etree.XPath("/p/text()")(root)
['\n text-first\n ', '\n text-middle\n ', '\n text-last\n']
您自己的解决方案 child::text()
表示:select 个文本节点,如果它们是当前上下文节点的子节点。它之所以有效,是因为在这种情况下,XPath 表达式是使用根元素 p
作为上下文来求值的。这就是为什么 text()
也有效的原因。
>>> etree.XPath("text()")(root)
['\n text-first\n ', '\n text-middle\n ', '\n text-last\n']