Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Python: анализ XML-документа при сохранении сущностей

Автор вопроса: VultaireОтветов: 4

Я хотел спросить, какие известные существующие библиотеки Python 2.x существуют для синтаксического анализа XML-документа со встроенным DTD без автоматического расширения сущностей. (Файл для любопытных: JMdict.)

Кажется, в lxml есть некоторая возможность не анализировать объекты, но в последний раз, когда я пытался, объекты просто были преобразованы в пустые. Я только что погуглил и нашел pxdom в качестве еще одной альтернативы, которую я могу попробовать, но, поскольку это чистый Python, он кажется намного медленнее, чем мне хотелось бы.

Что-нибудь еще там?

  • Я думал, что xml.parsers.expat.XML_PARAM_ENTITY_PARSING_NEVER в expat сделает это, но это не имело никакого эффекта. Чем он хорош, интересно. melissa_boiko 20.02.2013

pythonxmlparsingentity

Ответы

Ответ 1 · рейтинг 3 · mzjn

lxml упоминается в вопросе, и, насколько я могу судить, он делает то, что вы хотите. Тестовый код:

from lxml import etree

XML = """
<!DOCTYPE root [
<!ENTITY abc "123">
]>
<root>
&abc;
</root>"""

parser = etree.XMLParser(resolve_entities=False)

root = etree.fromstring(XML, parser)
print "Entity not resolved:"
print etree.tostring(root)
print

print "Entity resolved:"
root = etree.fromstring(XML)
print etree.tostring(root)

Выход:

Entity not resolved:
<root>
&abc;
</root>

Entity resolved:
<root>
123
</root>

Ответ 2 · рейтинг 1 · Vultaire

Кажется, что вариант использования довольно ненормальный; нерасширение объектов, кажется, идет вразрез с тем, как парсеры обычно должны работать в соответствии со спецификацией XML.

Итак, я думаю, что проще всего просто забить это, возможно. Я вручную извлек теги с помощью re.finditer и составил словарь сопоставлений. Отсюда нужно просто сканировать проанализированный вывод и делать правильные вещи для моего приложения. Я думаю, достаточно хорошо для моего варианта использования.

Ответ 3 · рейтинг 1 · Jukka Matilainen

Во-первых, BeautifulStoneSoup из BeautifulSoup по умолчанию не расширяет объекты.

Вероятно, это не будет быстрым или эффективным для вашего варианта использования, поскольку он ориентирован на другой вид использования (обработка всех видов неправильно сформированной и сломанной разметки).

Ответ 4 · Swen Vermeul

У меня была аналогичная проблема, которую нужно было решить. Мне нужно было прочитать XML-файл TEI, содержащий такие объекты, как

&some_exotic_char;

которые были объявлены в отдельном файле DTD. Задача заключалась в том, чтобы добавить какой-либо атрибут в определенные теги и записать измененный файл, сохранив при этом специальные сущности и не испортив XML-макет.

BeautifulSoup работал хорошо, пока я не захотел снова записать XML-файл:

with open('outfile.xml','w') as outfile:
    outfile.write(soup.prettify())

Тогда он не оставил бы сущности "как есть", а вместо этого расширил бы их до символов utf8, чего я не хотел. Кроме того, он испортил исходную разметку XML независимо от prettify-метода (без него еще хуже).

В конце концов я сдался и нашел хорошее решение с использованием Perl и XML::LibXML. Методом

$parser->expand_entities(0);

объекты не будут расширены. А запись XML обратно в файл сохранит исходный макет нетронутым.

use XML::LibXML;
my $parser = new XML::LibXML;
$parser->validation(0);
$parser->load_ext_dtd(1);
$parser->expand_entities(0);
my $doc  = $parser->parse_file('infile.xml');

... # do whatever you need to do

open my $out, '>', 'outfile.xml';
binmode $out;
print $out $doc->toString();
close $out;

Perl XML::LibXML спас меня.

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы