Как я могу запретить XML :: XPath извлекать DTD при обработке файла XML?

StackOverflow https://stackoverflow.com/questions/303510

  •  08-07-2019
  •  | 
  •  

Вопрос

Мой XML ( a.xhtml ) начинается следующим образом

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
...

Мой код начинается так

use XML::XPath;

use XML::XPath::XMLParser;

my $xp = XML::XPath->new(filename => "a.xhtml");

my $nodeset = $xp->find('/html/body//table'); 

Это очень медленно, и оказывается, что он тратит много времени на получение DTD ( http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd ).

Есть ли способ явно объявить прокси-сервер HTTP в семействе Perl XML ::? Я ненавижу изменять исходный документ a.xhtml , например, иметь локальную копию DTD.

Это было полезно?

Решение

XML :: XPath основан на XML :: Parser. В XML :: Parser есть опция НЕ использовать LWP для разрешения внешних сущностей (таких как DTD). А XML :: XPath позволяет передавать объект XML :: Parser для использования в качестве анализатора.

Так что вы можете написать это:

my $p = XML::Parser->new( NoLWP => 1);
my $xp= XML::XPath->new( parser => $p, filename => "a.xhtml");

Обратите внимание, что в этом случае вы потеряете все сущности, кроме числовых и стандартных (> ;, < ;, & amp ;, 'и "). Синтаксический анализатор не будет жаловаться, но он исчезнет без предупреждения (попробуйте включить & Amp; alpha; в таблицу и напечатать его, например).

На самом деле вам, вероятно, не следует использовать XML :: XPath, который активно не поддерживается.

Попробуйте XML :: LibXML, если у вас нет проблем с установкой libxml2, его интерфейс очень похож на XML :: XPath, поскольку они оба реализуют DOM. XML :: LibXML также намного мощнее XML :: XPath и быстрее загружается. Если вам нужен модуль на основе expat / XML :: Parser, вы можете захотеть взглянуть на XML :: Twig (это откровенная самореклама, так как я являюсь автором модуля, извините). Также для HTML / dodgy XHTML вы можете использовать HTML :: TreeBuilder, который с добавлением HTML :: TreeBuilder :: XPath (также мной) поддерживает XPath.

Другие советы

PorneL ответ, кажется, здесь правильно. (www.w3.org начал отвечать на каждый из моих запросов в течение 30 секунд (когда он просто не сдается), и когда XML :: XPath завершает получение полного набора XHTML & # 8230 ;!) Кроме того, идея Мирода тоже работает:

use XML::XPath;
use XML::Catalog;

my $parser = new XML::Parser;
my $catalog_handler = new XML::Catalog("xhtml1-20020801/DTD/xhtml.soc")->get_handler($parser);
$parser->setHandlers("ExternEnt" => $catalog_handler);
my $xp = new XML::XPath(xml => $xml, parser => $parser);

Добавить копию " Полный набор файлов DTD вместе с декларацией XML и SGML Open Catalog " от & # 10216; URL: http://www.w3.org/TR/ XHTML1 / dtds.html # 10217 &; и наслаждайтесь!

Обычно это делается путем настройки локального каталога XML .

синтаксические анализаторы на основе libxml поддерживают его, поэтому, если вы последуете совету mirod, вы сможете получать именованные объекты и выполнять проверку без сетевого доступа.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top