请考虑以下事项:
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)
这会失败:
lxml.etree.XMLSyntaxError: Entity 'nbsp' not defined, line 2, column 11
这是因为resolve_entities=False
不会忽略它们,它只是不解决它们。
如果我改为使用etree.HTMLParser
,则会创建html
和body
标记,以及它为HTML
尝试执行的许多其他特殊处理。
使用lxml在 â
标记下获取aa
文本子项的最佳方法是什么?
答案 0 :(得分:12)
您不能忽略实体,因为它们是XML定义的一部分。如果您的文档没有DTD或独立=“是”,或者它包含DTD中没有实体定义的实体,则文档格式不正确。谎言并声称您的文档是HTML。
https://mailman-mail5.webfaction.com/pipermail/lxml/2008-February/003398.html
您可以尝试撒谎并在文档上放置XHTML DTD。 e.g。
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>'
答案 1 :(得分:6)
@Alex是对的:您的文档格式不是格式良好的XML,因此XML解析器不会对其进行解析。一种选择是预处理文档的文本,用utf-8字符替换虚假实体:
entities = [
(' ', u'\u00a0'),
('â', u'\u00e2'),
...
]
for before, after in entities:
x = x.replace(before, after.encode('utf8'))
当然,这也可以通过足够奇怪的“xml”打破。
最好的办法是将输入的XML文档修复为格式良好的XML。
答案 2 :(得分:-2)
当我尝试做类似的事情时,我在解析字符串之前只使用了x.replace('&', '&')
。