При проверке XML с DTD не удается импортировать сущность с использованием lxml - PullRequest
3 голосов
/ 06 октября 2010

У меня есть инструмент для создания файлов XML типа NewsML, и я хочу проверить их после создания файлов. Я получаю сообщение об ошибке:

Attempt to load network entity <a href="http://www.w3.org/TR/ruby/xhtml-ruby-1.mod" rel="nofollow">http://www.w3.org/TR/ruby/xhtml-ruby-1.mod</a>

Вызов Python:

parser = etree.XMLParser(load_dtd=True, dtd_validation=True)
treeObject = etree.parse(f, parser)

Во-первых, я не уверен, нужно ли мне оба "load_dtd = True, dtd_validation = True", но я все равно использую его. Вторая ошибка, кажется, исходит от импортированного nitf-3-4.dtd, который определен как:

<!ENTITY % xhtml-ruby.mod PUBLIC 
    "-//W3C//ELEMENTS XHTML Ruby 1.0//EN" "http://www.w3.org/TR/ruby/xhtml-ruby-1.mod">
%xhtml-ruby.mod;

Будет ли lxml выходить и извлекать этот xhtml-ruby-1.mod или мне нужно, чтобы все файлы DTD были локально.

1 Ответ

4 голосов
/ 06 октября 2010

Попробуйте создать парсер с no_network=False. Как указано в документации :

no_network - запретить доступ к сети при поиске внешних документов (по умолчанию включено)

Импортированные модули dtd должны извлекаться с помощью lxml, но он не сможет этого сделать, если доступ к сети не разрешен (это не относится к самому документу, только для загрузки документов с внешними ссылками. На самом деле, я ожидал бы вы получаете ошибки при загрузке самого dtd, поэтому я предполагаю, что документ ссылается на локально доступную копию этого dtd, и что только dtd ссылается на удаленный ресурс?)

Вы также можете использовать каталог для использования локально доступных копий (не только обойти эту проблему, но и сделать ее более производительной и дружественной к серверам w3c ;-)). Libxml2 (используется lxml) проверит наличие каталога в /etc/xml/catalog и переменную среды XML_CATALOG_FILES (см. Libxml2 docs )

(также можно написать свои распознаватели для lxml для перехвата и обработки запросов, но в этом случае это, вероятно, было бы излишним)

Обратите внимание, что кроме проверки времени разбора есть и другая опция: используйте класс DTD для отдельной загрузки dtd и используйте его в качестве средства проверки.

Это будет проверять проанализированный документ с предоставленной dtd независимо от того, на какую dtd (если есть) ссылается объявление doctype (что может быть удобно: не каждый действительный xml-файл обязательно является действительным в соответствии с dtd you хочу).

Поскольку dtd нужно будет извлечь и проанализировать только один раз, это должно быть быстрее, если вы проверяете много документов), и (если я не ошибаюсь) вы не столкнетесь с проблемой no_network .

Приближается еще один бонус: вы даже можете проверить ваши элементы / деревья элементов перед тем, как их сериализовать (если ваш инструмент создания использует lxml).

Последнее замечание: некоторые документы могут быть проанализированы, только если у вас есть доступ к dtd во время анализа (неразрешимые объекты ...). Избегайте этого, если можете. (и, хотя не все с этим согласятся: по возможности избегайте объявлений типа документа).

...