2008-11-19 114 views
11

我的XML(a.xhtml)开始喜欢这个如何防止XML :: XPath在处理XML文件时获取DTD?

<!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副本。

回答

14

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

注意,在这种情况下,你将失去所有的实体,除了那些数值和默认的(>,<,&,'和")。解析器不会发出抱怨,但它们会自动消失(尝试包括&阿尔法;在表格中并打印它)。

事实上,你可能不应该使用XML :: XPath,它不会被主动维护。

尝试XML :: LibXML,如果您在安装libxml2时没有问题,那么它的接口与XML :: XPath非常相似,因为它们都实现了DOM。 XML :: LibXML也比XML :: XPath强大得多,而且启动速度更快。如果你想要一个基于expat/XML :: Parser的模块,你可能需要看看XML :: Twig(这是公然的自我推销,因为我是该模块的作者,对不起)。同样,对于HTML/dhttp XHTML,您可以使用HTML :: TreeBuilder,它通过添加HTML :: TreeBuilder :: XPath(也是我自己)支持XPath。

1

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

基于libxml的解析器支持它,所以如果遵循mirod的建议,您将能够获得命名实体和验证工作而无需网络访问。

+0

是。您大概可以使用XML :: Catalog将一个目录添加到XML :: Parser对象中,并在XML :: XPath的新对象中使用该解析器。但我从来没有测试过。 – mirod 2008-11-20 13:17:43

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 ⟩和享受!