使用lxml在XML文档中处理类似实体的最佳方法是什么?

Pro*_*ody 12 python lxml

考虑以下:

from lxml import etree
from StringIO import StringIO

x = """<?xml version="1.0" encoding="utf-8"?>\n<aa>&nbsp;&acirc;</aa>"""
p = etree.XMLParser(remove_blank_text=True, resolve_entities=False)
r = etree.parse(StringIO(x), p)
Run Code Online (Sandbox Code Playgroud)

这将失败:
lxml.etree.XMLSyntaxError: Entity 'nbsp' not defined, line 2, column 11

这是因为resolve_entities=False不会忽略它们,它只是不解决它们.

如果我使用etree.HTMLParser它,它会创建htmlbody标记,以及它试图做的许多其他特殊处理HTML.

使用lxml &nbsp;&acirc;aa标记下获取文本子项的最佳方法是什么?

小智 12

您不能忽略实体,因为它们是XML定义的一部分.如果您的文档没有DTD或独立="是",或者它包含DTD中没有实体定义的实体,则文档格式不正确.谎言并声称您的文档是HTML.

https://mailman-mail5.webfaction.com/pipermail/lxml/2008-February/003398.html

您可以尝试撒谎并在文档上放置XHTML DTD.例如

from lxml import etree
try:
    from StringIO import StringIO
except ImportError:
    from io import StringIO
x = """<?xml version="1.0" encoding="utf-8"?>\n<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" >\n<aa>&nbsp;&acirc;</aa>"""
p = etree.XMLParser(remove_blank_text=True, resolve_entities=False)
r = etree.parse(StringIO(x), p)
etree.tostring(r) # '<aa>&nbsp;&acirc;</aa>'
Run Code Online (Sandbox Code Playgroud)


Ned*_*der 6

@Alex是对的:您的文档不是格式良好的XML,因此XML解析器不会解析它.一种选择是预处理文档的文本以用utf-8字符替换伪造实体:

entities = [
    ('&nbsp;', u'\u00a0'),
    ('&acirc;', u'\u00e2'),
    ...
    ]

for before, after in entities:
    x = x.replace(before, after.encode('utf8'))
Run Code Online (Sandbox Code Playgroud)

当然,这也可以通过足够奇怪的"xml"来打破.

最好的办法是将输入的XML文档修复为格式良好的XML.