DTD для Python xml etree из источника StringIO? - PullRequest
4 голосов
/ 29 сентября 2010

Я адаптирую следующий код (созданный с помощью совета в этот вопрос ), который взял файл XML и его DTD и преобразовал их в другой формат.Для этой проблемы важен только раздел загрузки:

xmldoc = open(filename)

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

Это работало нормально при использовании файловой системы, но я конвертирую ее для запуска через веб-фреймворк, где два файла загружаются черезform.

Загрузка xml-файла работает нормально:

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

Но поскольку DTD связан с верхней частью xml-файла, следующий оператор завершается неудачно:

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

Через этот вопрос , я пытался:

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

В то время как первая строка не вызывает ошибку, вторая падает на юникодные объекты, которые DTD должен подобрать(и делает это в версии файловой системы):

XMLSyntaxError: Объект 'eacute' не определен, строка 4495, столбец 46

Как правильно выполнить загрузкуэто DTD?

Ответы [ 2 ]

5 голосов
/ 16 ноября 2010

Вот краткий, но полный пример использования упомянутой техники распознавателя @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
1 голос
/ 29 сентября 2010

Возможно, вы могли бы использовать пользовательский преобразователь . Документы фактически дают пример того, как это сделать, чтобы предоставить dtd.

...