2010-04-21 23 views
2

我發現這對http://www.perlmonks.org/?node_id=606909如何用Perl的XML :: LibXML編寫具有限定名稱的XPath?

由合格的名字看...
在這種情況下,你可以調用findnodes方法的任何節點上,你不需要XML ::的libxml :: XPathContext與其前綴=>名稱空間映射: $ doc-> findnodes('// /info/fooTransaction/transactionDetail/ [name()=「histFile:transactionSummary」]/*');

爲了讓我的腳本在沒有XPathContext的情況下工作,必須編輯我的xpath?

#!/usr/bin/env perl 
use warnings; use strict; 
use 5.012; 
use XML::LibXML; 


my $parser = XML::LibXML->new; 
$parser->recover_silently(1); 

my $doc = $parser->parse_file('http://www.heise.de/'); 

my $xc = XML::LibXML::XPathContext->new($doc->getDocumentElement); 
$xc->registerNs('xmlns', 'http://www.w3.org/1999/xhtml'); 

my $nodes = $xc->findnodes('//xmlns:h2/xmlns:a'); 
for my $node ($nodes->get_nodelist) { 
    say $_->getName, '=', $_->getValue for $node->attributes; 
} 

回答

1

請遵循文章中給出的相同型號。如果要測試節點的文本名稱,而不是考慮節點的名稱空間映射到的URI,請調用name並進行字符串比較。

 
//*[name() = "xmlns:h2"]/*[name() = "xmlns:a"] 

對於表達式匹配任何東西,不過,就必須從字面上命名的文檔中的節點。你需要有這樣一個文件:

<xmlns:h2> 
    <xmlns:a>header</xmlns:a> 
</xmlns:h2> 

雖然你鏈接到的頁面看起來不像那樣。它使用普通的HTML節點名稱,如h2a,而不是。簡單名稱的確位於xmlns名稱空間中,但只是因爲它被配置爲文檔的默認名稱空間。因爲節點不與命名空間前綴命名的,不包括在你的名字的字符串前綴:

 
//*[name() = "h2"]/*[name() = "a"] 

的進一步改變,你可以做,萬一一些節點使用xmlns前綴當別人不要't,將使用local-name而不是name;那麼它將剝離出現的任何名稱空間前綴。

 
//*[local-name() = "h2"]/*[local-name() = "a"] 
+0

我試過,但我想這不是它的工作方式: 我的$解析器= XML :: LibXML->新; my $ doc = $ parser-> parse_file('http://www.heise.de/'); my $ nodes = $ doc-> findnodes('// * [name()=「xmlns:h2」]'); 說$ _-> nodeName爲$ nodes-> get_nodelist; – 2010-04-21 17:46:43

+0

閱讀外語與閱讀第一語言不同: 「由於節點未命名爲名稱空間前綴,因此請勿在名稱字符串中包含該前綴」 – 2010-05-04 07:35:24

+0

網站中的節點名稱只是'a'和'html'。您正在解析的XML中的名稱不包含名稱空間前綴'xmlns'。原始XPath表達式檢查'name()'函數是否返回字符串'xmlns:a',但這不是節點的名稱,所以比較失敗。這個名字只是'a';它不包含XML名稱空間的前綴。 – 2010-05-04 12:23:16