Как я могу запретить 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, вы сможете получить именованные объекты и работу по проверке без доступа к сети.