来自StringIO源的pythonxml etree DTD?

2024-04-26 00:10:54 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在修改下面的代码(通过this question中的advice创建),它接受一个XML文件和它的DTD并将它们转换成不同的格式。对于这个问题,只有加载部分很重要:

xmldoc = open(filename)

parser = etree.XMLParser(dtd_validation=True, load_dtd=True)    
tree = etree.parse(xmldoc, parser)

在使用文件系统时,这个方法运行得很好,但我将其转换为通过web框架运行,在web框架中,这两个文件是通过表单加载的。在

加载xml文件可以正常工作:

^{pr2}$

但是,由于DTD链接到xml文件的顶部,以下语句将失败:

parser = etree.XMLParser(dtd_validation=True, load_dtd=True)
tree = etree.parse(StringIO(data['xml_file'], parser)

通过this question,我试图:

etree.DTD(StringIO(data['dtd_file'])
tree = etree.parse(StringIO(data['xml_file'])

虽然第一行没有导致错误,但第二行却落在DTD要拾取的unicode实体上(在文件系统版本中是这样做的):

XMLSyntaxError: Entity 'eacute' not defined, line 4495, column 46

如何正确加载此DTD?在


Tags: 文件truetreeparserdataparsexmlthis
2条回答

您可以使用custom resolver。文档实际上给出了这样做的一个示例,以提供dtd。在

下面是一个简短但完整的示例,使用@Steven提到的定制解析器技术。在

from StringIO import StringIO
from lxml import etree

data = dict(
    xml_file = '''<?xml version="1.0"?>
<!DOCTYPE x SYSTEM "a.dtd">
<x><y>&eacute;zz</y></x>
''',
    dtd_file = '''<!ENTITY eacute "&#233;">
<!ELEMENT x (y)>
<!ELEMENT y (#PCDATA)>
''')

class DTDResolver(etree.Resolver):
     def resolve(self, url, id, context):
         return self.resolve_string(data['dtd_file'], context)

xmldoc = StringIO(data['xml_file'])
parser = etree.XMLParser(dtd_validation=True, load_dtd=True)
parser.resolvers.add(DTDResolver())
try:
    tree = etree.parse(xmldoc, parser)
except etree.XMLSyntaxError as e:
    # handle xml and validation errors

相关问题 更多 >