Как я могу запретить XML :: XPath извлекать DTD при обработке файла XML?
Вопрос
Мой 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, вы сможете получать именованные объекты и выполнять проверку без сетевого доступа.