考虑以下:
from lxml import etree
from StringIO import StringIO
x = """<?xml version="1.0" encoding="utf-8"?>\n<aa> â</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它,它会创建html和body标记,以及它试图做的许多其他特殊处理HTML.
使用lxml â在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> â</aa>"""
p = etree.XMLParser(remove_blank_text=True, resolve_entities=False)
r = etree.parse(StringIO(x), p)
etree.tostring(r) # '<aa> â</aa>'
Run Code Online (Sandbox Code Playgroud)
@Alex是对的:您的文档不是格式良好的XML,因此XML解析器不会解析它.一种选择是预处理文档的文本以用utf-8字符替换伪造实体:
entities = [
(' ', u'\u00a0'),
('â', u'\u00e2'),
...
]
for before, after in entities:
x = x.replace(before, after.encode('utf8'))
Run Code Online (Sandbox Code Playgroud)
当然,这也可以通过足够奇怪的"xml"来打破.
最好的办法是将输入的XML文档修复为格式良好的XML.