簡體   English   中英

使用未定義的實體解析XHTML5

[英]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>&nbsp;Sample text</p>
            </body>
        </html>
'''
parser = ET.XMLParser()
parser.entity['nbsp'] = '&#x00A0;'
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>&nbsp;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>&nbsp;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'\ '&nbsp;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM