12

我的 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:: 系列中显式声明 HTTP 代理服务器?我讨厌修改原始的a.xhtml文档,就像拥有 DTD 的本地副本一样。

4

3 回答 3

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

请注意,在这种情况下,您将丢失除数字实体和默认实体(>、<、&、' 和“)之外的所有实体。解析器不会抱怨,但它们会默默消失(尝试在表中包含 α 并打印例如)。

事实上,您可能不应该使用未积极维护的 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。

于 2008-11-20T10:08:59.793 回答
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: http ://www.w3.org/TR/xhtml1/dtds.html ⟩添加一份“完整的 DTD 文件集以及 XML 声明和 SGML 开放目录”的副本⟩,尽情享受吧!

于 2011-03-08T02:26:57.557 回答
1

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

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

于 2008-11-19T22:22:54.993 回答