Python ElementTree支持解析未知的XML实体吗?
问题描述:
我有一组超级简单的XML文件来解析...但是...他们使用自定义的实体。我不需要将这些映射到角色,但我希望解析并针对每个角色进行操作。例如:Python ElementTree支持解析未知的XML实体吗?
<Style name="admin-5678">
<Rule>
<Filter>[admin_level]='5'</Filter>
&maxscale_zoom11;
</Rule>
</Style>
有一个在http://effbot.org/elementtree/elementtree-xmlparser.htm一个诱人的暗示,XMLParser的有限实体的支持,但我找不到提到的方法,一切都给人错误:这取决于你如何
#!/usr/bin/python
##
## Where's the entity support as documented at:
## http://effbot.org/elementtree/elementtree-xmlparser.htm
## In Python 2.7.1+ ?
##
from pprint import pprint
from xml.etree import ElementTree
from cStringIO import StringIO
parser = ElementTree.ElementTree()
#parser.entity["maxscale_zoom11"] = unichr(160)
testf = StringIO('<foo>&maxscale_zoom11;</foo>')
tree = parser.parse(testf)
#tree = parser.parse(testf,"XMLParser")
for node in tree.iter('foo'):
print node.text
调整的意见,得出:
xml.etree.ElementTree.ParseError: undefined entity: line 1, column 5
或
AttributeError: 'ElementTree' object has no attribute 'entity'
或
AttributeError: 'str' object has no attribute 'feed'
对于那些好奇的XML是从OpenStreetMap的Mapnik的项目。
答
我不确定这是ElementTree中的一个错误还是什么,但是您需要在expat解析器上调用UseForeignDTD(True)以表现它过去的行为。
这是一个有点哈克,但你可以通过创建自己的ElementTree.Parser实例,调用它的方法是xml.parsers.expat的实例,然后将它传递给ElementTree.parse()做到这一点:
from xml.etree import ElementTree
from cStringIO import StringIO
testf = StringIO('<foo>&moo_1;</foo>')
parser = ElementTree.XMLParser()
parser.parser.UseForeignDTD(True)
parser.entity['moo_1'] = 'MOOOOO'
etree = ElementTree.ElementTree()
tree = etree.parse(testf, parser=parser)
for node in tree.iter('foo'):
print node.text
此输出 “MOOOOO”
或者使用映射接口:
from xml.etree import ElementTree
from cStringIO import StringIO
class AllEntities:
def __getitem__(self, key):
#key is your entity, you can do whatever you want with it here
return key
testf = StringIO('<foo>&moo_1;</foo>')
parser = ElementTree.XMLParser()
parser.parser.UseForeignDTD(True)
parser.entity = AllEntities()
etree = ElementTree.ElementTree()
tree = etree.parse(testf, parser=parser)
for node in tree.iter('foo'):
print node.text
此输出 “moo_1”
一个更复杂的修复将是子类ElementTree.XMLParser并修复它。
答
正如@cnelson已经在评论中指出,这里选择的解决方案将无法工作在Python 3
我终于得到了它的工作。引自此Q&A。
受this post的启发,我们可以将一些XML定义添加到传入的原始HTML内容中,然后ElementTree将开箱即用。
这适用于Python 2.6,2.7,3.3,3.4。
import xml.etree.ElementTree as ET
html = '''<html>
<div>Some reasonably well-formed HTML content.</div>
<form action="login">
<input name="foo" value="bar"/>
<input name="username"/><input name="password"/>
<div>It is not unusual to see in an HTML page.</div>
</form></html>'''
magic = '''<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" [
<!ENTITY nbsp ' '>
]>''' # You can define more entities here, if needed
et = ET.fromstring(magic + html)
可能相关的问题:http://*.com/questions/2524299/entity-references-and-lxml – unutbu
没有关系的,因为在这种情况下,实体实际上是定义。删除实体定义,你回到我的问题。 – Bryce
fyi - 有人可能希望将/ usr/bin/python修复为/ usr/bin/env python,因为大多数系统的shebang行都是错误的。 –