【问题标题】:How can I get lxml.Element.xpath to not expand entities?如何让 lxml.Element.xpath 不展开实体?
【发布时间】:2022-01-12 22:23:29
【问题描述】:

如果我使用 lxml.etree.XMLParser(resolve_entities=False) 解析 XML 内容,它会正确返回文本节点,而不会扩展实体。 (我希望它只是将实体的文本留在其中;而是在第一个实体处截断。

from io import BytesIO
from lxml import etree

xml_content = b"""<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
  <!ELEMENT foo ANY>
  <!ENTITY bar "benign">
]>
<body>
    <expansion>    This is    a &bar; entity expansion with weird spacing.   </expansion>
</body>"""

nonexpanding_parser = etree.XMLParser(resolve_entities=False)
unexpanded_tree = etree.parse(BytesIO(xml_content), nonexpanding_parser)
elements = unexpanded_tree.xpath('//expansion')
elements[0].text  # '    This is    a '

但是,当我尝试在其上调用 xpath function normalize-space 时,它会扩展实体,这是我试图避免的:

elements[0].xpath('normalize-space(.)')  # 'This is a benign entity expansion with weird spacing.'

我想我可以编写自己的规范化方法,但我宁愿避免这种情况,而且我不能 100% 确定该函数的确切规范是什么,我正在努力在我的代码中替换它,所以我希望它的行为相同。

真正的问题是:我可以得到类似elements[0].xpath('normalize-space(.)') 的东西,它会返回This is a

更好:

  • This is a entity expansion with weird spacing.(这是首选示例)
  • This is a &amp;bar; entity expansion with weird spacing.

【问题讨论】:

  • 我不想说这是我的问题的“答案”,因为我使用它的原因涉及代码的各个方面围绕这个最小的例子。无论如何,这就是我认为应该分享的内容:import re text = ' '.join(elements[0].itertext()) text = re.sub(r'\s+', ' ', text.strip()) 请注意,这会生成包含未扩展实体的示例,根据我的条件和权衡,这对我来说是可以接受的

标签: python xml xpath lxml


【解决方案1】:

这不是很优雅,但您可以提取所有文本节点,在 Python 中将它们连接起来,并对空间进行规范化。

(Pdb) text_fragments = unexpanded_tree.xpath('//expansion/text()')
(Pdb) text_fragments
['    This is    a ', ' entity expansion with weird spacing.   ']
(Pdb) ' '.join(''.join(text_fragments).split())
'This is a entity expansion with weird spacing.'

【讨论】:

    猜你喜欢
    • 2014-01-29
    • 2022-12-19
    • 2011-11-16
    • 2014-06-18
    • 2013-05-17
    • 2023-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多