[英]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.