尝试使用ElementTree解析包含未定义实体(即
)的XML:
ParseError: undefined entity
在Python 2.x中,可以通过创建解析器(documentation)来更新XML实体dict:
parser = ET.XMLParser()
parser.entity["nbsp"] = unichr(160)
但是如何使用Python 3.x做同样的事情?
parser.parser.UseForeignDTD(1)
,这导致了解析器的错误。幸运的是,@ m.brindley耐心地指出XML实体dict仍然存在于Python 3.x中,可以像在Python 2.x中那样进行更新
答案 0 :(得分:18)
这里的问题是XML中唯一有效的助记符实体是quot
,amp
,apos
,lt
和gt
。这意味着必须使用entity declaration markup中定义的XML 1.1 spec在DTD中定义几乎所有(X)HTML命名实体。如果文档是独立的,则应使用内联DTD来完成,如下所示:
<?xml version="1.1" ?>
<!DOCTYPE naughtyxml [
<!ENTITY nbsp " ">
<!ENTITY copy "©">
]>
<data>
<country name="Liechtenstein">
<rank>1 ></rank>
<year>2008©</year>
<gdppc>141100</gdppc>
<neighbor name="Austria" direction="E"/>
<neighbor name="Switzerland" direction="W"/>
</country>
</data>
XMLParser
中的xml.etree.ElementTree
使用xml.parsers.expat
进行实际解析。在XMLParser
的init参数中,有一个“predefined HTML entities”的空格,但该参数尚未实现。在init方法中创建了一个名为entity
的空dict,这是用于查找未定义实体的。
我不认为expat(通过扩展,ET XMLParser)能够处理切换命名空间到类似XHMTL的东西来解决这个问题。可能是因为它不会获取外部命名空间定义(我尝试将xmlns="http://www.w3.org/1999/xhtml"
作为数据元素的默认命名空间,但它没有很好地发挥作用)但我无法确认。默认情况下,expat会针对非XML实体引发错误,但您可以通过定义外部DOCTYPE来解决此问题 - 这会导致expat解析器将未定义的实体条目传递回ET.XMLParser
的{{1}}方法
_default()
方法查找_default()
实例中的entity
dict,如果找到匹配的密钥,它将用相关值替换该实体。这维护了问题中提到的Python-2.x语法。
<强>解决方案:强>
XMLParser
- chr()
不再是有效名称
unichr()
更新XMLParser.entity
,将所有有效的HTML5助记符实体映射到其字符。html.entities.html5
来处理助记符实体,但这不会根据需要返回HTMLParser
。以下是我使用的代码段 - 它使用外部DOCTYPE通过ElementTree
解析XML(以演示如何通过子类化添加实体处理),HTMLParser
使用实体映射和ET.XMLParser
(由于外部DOCTYPE,它将默默地忽略未定义的实体)。有一个有效的XML实体(expat
)和一个未定义的实体(>
),我使用©
映射到chr(0x24B4)
。
ET.XMLParser
答案 1 :(得分:2)
我遇到了类似的问题,并使用lxml解决了这个问题。它的etree.XMLParser
有一个recover
关键字参数,迫使它试图忽略损坏的XML。