2008-11-19 83 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 ⟩和享受!