Как я могу запретить 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.

Ответ 1

XML:: XPath основан на XML:: Parser. В XML:: Parser есть опция НЕ использовать LWP для разрешения внешних объектов (например, DTD). И XML:: XPath позволяет передавать XML:: Parser objetc для использования в качестве синтаксического анализатора.

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

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

Обратите внимание, что в этом случае вы потеряете все объекты, кроме числовых, и значения по умолчанию ( > , <, &, & thetas;, "). Парсер не будет жаловаться, но они исчезнут молча (попробуйте включить & 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.

Ответ 2

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

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 и Open Open Catalog" из & lang; URL: http://www.w3.org/TR/xhtml1/dtds.html & звонил; и наслаждайтесь!

Ответ 3

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

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