2015-10-27 19 views
8

XMLファイルからいくつかの情報を使いたいと思っています。私はこれらのファイルを読み込んでいくつかの条件を探し出すコードを書いています。名前空間を使用するXML文書からデータを抽出する

問題は、これらのXMLファイルは

<SquishReport version="2.1" xmlns="http://www.froglogic.com/XML2"> 

で始まることで、Perlは(少なくとも私のコードで!)それらを読むことができませんでした。しかし、ときに私は非常にうまく機能

XMLファイル

<?xml version="1.0" encoding="UTF-8"?> 
    <?xml-stylesheet type="text/xsl"?> 
の1行目にこれらの行を追加しています。私のXMLファイル test.xmlから

一部の行:

<SquishReport version="2.1" xmlns="http://www.froglogic.com/XML2"> 
    <test name="TEST"> 
     <prolog time="2015-10-01T03:45:22+02:00"/> 
     <test name="tst_start_app"> 
      <prolog time="2015-02-01T03:45:23+02:00"/> 
      <message line="38" type="LOG" file="C:\squish\test\sources.py" time="2015-02-01T03:45:23+02:00"> 
       <description> 
       <![CDATA[>> >> >> start: init (global) - testcase C:\squish\test\tst_start_app]]></description> 
      </message> 
     </test> 
    </test> 
</SquishReport> 

とXMLファイルを読み込むためのPerlコードは次のとおりです。

use strict; 
use warnings; 
use feature 'say'; 
use XML::LibXML; 

# Parse the XML 
my $xml = XML::LibXML->load_xml(location => 'test.xml'); 

# Iterate the entries 
for my $entry ($xml->findnodes('/SquishReport/test/test')) { 
    my $key = $entry->findvalue('@name'); 
    say "$key"; 
} 
+0

[なぜXがするのが重複する可能性ML :: LibXMLは、ネームスペースを使用するとき、このxpathクエリのノードを見つけません。](http:// stackoverflow。com/questions/4083550/why-does-xmllibxml-find-no-nodes-for-this-xpath-query-when-using-namespace) – nwellnhof

+0

この質問の重複として閉じないでください。その質問のXMLは違法であり、問​​題を複雑にし、その質問に対する解決策をこの質問と無関係にします。この質問をきれいな例として利用したいと思います。 – ikegami

答えて

11

その文書のルート・ノードは、名前SquishReportを持つ要素でありますhttp://www.froglogic.com/XML2名前空間にあります。簡潔に、我々は1つがnullの名前空間で名前SquishReportを持つ要素を一致させようとするXPath、中SquishReportprefix:SquishReportと対照的に)を使用すると、ルートノードが

{http://www.froglogic.com/XML2}SquishReport 


であると言うことができます。

use strict; 
use warnings; 
use feature qw(say); 

use XML::LibXML    qw(); 
use XML::LibXML::XPathContext qw(); 

my $xpc = XML::LibXML::XPathContext->new(); 
$xpc->registerNs(sr => 'http://www.froglogic.com/XML2'); 

my $doc = XML::LibXML->load_xml(location => 'test.xml'); 
for my $entry ($xpc->findnodes('/sr:SquishReport/sr:test/sr:test', $doc)) { 
    my $key = $entry->findvalue('@name'); 
    say $key; 
} 


注::XPathのに使用される接頭辞を簡潔に、我々はそれが次のように1は、contextで定義された接頭辞を使用して、名前空間を指定するには

{}SquishReport 


を一致させようと言うことができますXML文書で使用されている接頭辞(存在する場合)とは関係がありません。検索対象の要素が存在するネームスペースは知っているが、特定のドキュメントで使用されているプレフィックスは認識していないことが予想されます。

+0

ありがとう、素晴らしい答えがたくさん! – Royeh

+0

これは本当にきれいでクリアです!私は 'XML :: LibXML'から構築されたモジュールを使う傾向がありますが、あなたはここを見やすくしています。 XMLは決して消え去ることはなく、perlには本当に強力なツールがあります。 –

0

Perlは非常に多くの優れたXMLツールがある - すべてのモジュール開発者とlibxml2のおかげで、XMLはほとんど簡単なようです。これらのツールの1つはXML::Datasetです。XML::LibXML上に構築され、XMLソース(NB:の空白と行の終わりに敏感です)からデータを取得するために「プロファイル」マークアップ言語を使用する便利な「足場」モジュールです。

例えば:

use XML::Dataset; 
use DDP; 

my $xml = "Squish.xml" ; 
open my $fh, "<", $xml or die "aiiieee!"; 
my $test_data = do { local $/; <$fh> }; 

# describe the data using XML::Dataset simplified markup: 
my $data_profile 
    = q(
      SquishReport 
      test 
       test 
       name = dataset:name); 

# parse it with XML::Dataset profile 
my $parsed_data = parse_using_profile($test_data, $data_profile); 

# view the element with Data::Printer 
foreach my $element ($parsed_data->{name}){ 
    p $element ; 
}; 

Squish.xml

<SquishReport version="2.1" xmlns="http://www.froglogic.com/XML2"> 
    <test name="TEST"> 
     <prolog time="2015-10-01T03:45:22+02:00"/> 
     <test name="tst_start_app"> 
      <prolog time="2015-02-01T03:45:23+02:00"/> 
      <message line="38" type="LOG" file="C:\squish\test\sources.py" time="2015-02-01T03:45:23+02:00"> 
       <description> 
       <![CDATA[>> >> >> start: init (global) - testcase C:\squish\test\tst_start_app]]></description> 
      </message> 
     </test> 
    </test> 
</SquishReport> 

出力:

\ [ 
    [0] { 
     name "tst_start_app" 
    } 
] 
関連する問題