[英]Parse XHTML5 with undefined entities
请考虑一下:
import xml.etree.ElementTree as ET
xhtml = '''<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html lang="en" xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head><title>XHTML sample</title></head>
<body>
<p> Sample text</p>
</body>
</html>
'''
parser = ET.XMLParser()
parser.entity['nbsp'] = ' '
tree = ET.fromstring(xhtml, parser=parser)
print(ET.tostring(tree, method='xml'))
它呈现了xhtml
字符串的漂亮文本表示。
但是,对于具有HTML5 doctype的相同XHTML文档:
xhtml = '''<!DOCTYPE html>
<html lang="en" xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head><title>XHTML sample</title></head>
<body>
<p> Sample text</p>
</body>
</html>
'''
我得到例外:
xml.etree.ElementTree.ParseError: undefined entity: line 5, column 19
所以解析器不能处理它,虽然我加nbsp
到实体字典。
如果我使用lxml
也会发生同样的情况:
from lxml import etree
parser = etree.XMLParser(resolve_entities=False)
tree = etree.fromstring(xhtml, parser=parser)
print etree.tostring(tree, method='xml')
提出:
lxml.etree.XMLSyntaxError: Entity 'nbsp' not defined, line 5, column 26
虽然我已将解析器设置为忽略实体。
为什么会这样,以及如何使用HTML5 doctype声明解析XHTML文件?
lxml的部分解决方案是使用recoverer:
parser = etree.XMLParser(resolve_entities=False, recover=True)
但我还在等待更好的一个。
这里的问题是,幕后使用的Expat解析器通常不会报告未知实体 - 它会抛出错误,因此您尝试触发的xml.etree.ElementTree
的回退代码甚至不会运行。 您可以使用UseForeignDTD
方法更改此行为,它将使Expat忽略doctype声明并将所有实体声明传递给xml.etree.ElementTree
。 以下代码正常工作:
import xml.etree.ElementTree as ET
xhtml = '''<!DOCTYPE html>
<html lang="en" xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head><title>XHTML sample</title></head>
<body>
<p> Sample text</p>
</body>
</html>
'''
parser = ET.XMLParser()
parser._parser.UseForeignDTD(True)
parser.entity['nbsp'] = u'\u00A0'
tree = ET.fromstring(xhtml, parser=parser)
print(ET.tostring(tree, method='xml'))
这种方法的副作用:正如我所说,doctype声明完全被忽略了。 这意味着您必须声明所有实体,甚至是doctype所涵盖的实体。
请注意,您放入ElementTree.XMLParser.entity
字典的值必须是常规字符串,实体将被替换的文本 - 您不能再引用其他实体。 所以它应该是u'\ '
为
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.