如何防止XML :: XPath在处理XML文件时获取DTD?

时间:2008-11-19 21:52:16

标签: xml perl dtd

我的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)。

有没有办法在Perl XML :: family中显式声明HTTP代理服务器?我讨厌修改原始的 a.xhtml 文档,比如拥有DTD的本地副本。

3 个答案:

答案 0 :(得分:15)

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");

请注意,在这种情况下,您将丢失除数字和默认实体之外的所有实体(&gt;,&lt;,&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。

答案 1 :(得分:3)

porneL的反应似乎是正确的事情。 (www.w3.org已经开始花30秒钟来回复我的每个查询(当它不只是放弃时),当XML :: XPath最终检索完整的XHTML集合时!...)此外,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);

从⟨URL添加“完整的DTD文件集以及XML声明和SGML开放目录”:http://www.w3.org/TR/xhtml1/dtds.html⟩并享受!

答案 2 :(得分:1)

通常是通过设置本地XML catalog来完成的。

基于libxml的解析器支持它,因此如果您遵循mirod的建议,您将能够在没有网络访问的情况下获得命名实体和验证。