2017-05-27 21 views
1

解析XML文件,我想按以下從XML文件中提取值:用Perl

<?xml version="1.0" encoding = "UTF-8" ?> 
    <!-- SAP Data Services generated XML --> 
    <!-- 2017-05-26.22:12:03(409,091)[1] --> 

<Root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
<CreatedAt>2017-05-26T22:12:11</CreatedAt> 
<CreateBy>BJOB_ODS_WF5MD_WEBSITE_FILES_5MIN_DATA</CreateBy> 
<StartDate>2017-05-21T00:00:00</StartDate> 
    <DataSet Series = "5_Minute" ><Data><Value>10875.60</Value> 
    </Data> 
.... 
<DataSet Series = "Actual" ><Data><Value>11150.00</Value> 
    </Data> 
<Data><Value>10700.00</Value> 
</Data> 
<Data><Value>10450.00</Value> 
</Data> 
    ... 
</Data> 
</DataSet> 
</Root> 

盼望以下輸出爲CSV,但沒有得到愛與下面的腳本:

11150.00

10700.00

10450.00

****SCRIPT 
use warnings; 
use strict; 
use XML::Twig; 
#<DataSet Series = "Actual" ><Data><Value>11112.60</Value 

my $file = '/var/data/Actual.xml' ||die $!; 

my $t=XML::Twig->new(); 
$t->parsefile($file); 

# my @sets = $t->findnodes('//DataSet[@seriesName= "Actual" ]/set'); 
# I CHANGED THE ABOVE AND MODIFIED AS SHOWN BELOW 

my @sets = $t->findnodes('//DataSet[@Series= "Actual" ]/Value');  
if (@sets) { 
    my $outfile = '/var/csv/actual.csv'; 
    open my $out, ">", $outfile or die "Could not open $outfile: $!"; 
    print { $out } $_->att('Value')."\n" for @sets; 
} 

任何幫助將不勝感激。

+1

XML中沒有'set'元素,但是你的xpath表達式要求輸入一個元素。我現在不能嘗試,但是你應該對DataSet [@ seriesName =「Actual」]/Data/Value'很好,然後不要使用'$ _-> att',因爲'Value'是不是屬性。有了上面的xpath,你將有節點,你可以訪問文本屬性。我不記得如何檢查文檔。 – simbabque

回答

2

這裏有一些誤解。首先,你的XML是無效的。我知道這僅僅是一個例子,但給我們一個有效的(如果是精簡的)例子還是不錯的。並且從第一個元素中省略開頭的<,這讓我覺得你並沒有在相當精準的水平上看待這個!

然後,XPath表達式與您正在解析的XML關係很小。正如他在評論中提到的simbabque,您指的是那些不會出現在您的XML中的元素,所以沒有任何內容匹配並不奇怪。

  • seriesName屬性被稱爲Series
  • 沒有set元素。你需要Data/Value

這似乎給你想要的東西(這是非常接近simbabque的建議,但他錯過了seriesName問題)。

my @sets = $t->findnodes('//DataSet[@Series="Actual"]/Data/Value'); 

程序員需要處理精度和準確性。也許你需要處理一點:-)

更新:這是我正在使用的測試XML。它基於你的XML,但我已經修復了一些明顯的錯誤。

<Root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
<CreatedAt>2017-05-26T22:12:11</CreatedAt> 
<CreateBy>BJOB_ODS_WF5MD_WEBSITE_FILES_5MIN_DATA</CreateBy> 
<StartDate>2017-05-21T00:00:00</StartDate> 
<DataSet Series = "5_Minute" > 
    <Data><Value>10875.60</Value></Data> 
</DataSet> 
<DataSet Series = "Actual" > 
    <Data><Value>11150.00</Value></Data> 
    <Data><Value>10700.00</Value></Data> 
    <Data><Value>10450.00</Value></Data> 
</DataSet> 
</Root> 

這裏是我測試過的代碼。我簡化了你的代碼,將文件名作爲參數並將輸出寫入STDOUT(我不明白爲什麼這麼多人會爲這麼多人拼寫文件名)。

#!/usr/bin/perl 

use warnings; 
use strict; 
use XML::Twig; 

my $file = shift or die "No file given\n"; 

my $t=XML::Twig->new(); 
$t->parsefile($file); 

my @sets = $t->findnodes('//DataSet[@Series="Actual"]/Data/Value'); 

if (@sets) { 
    print $_->text, "\n" for @sets; 
} 

請注意,我做了我不小心從我原來的職位省略另一個變化 - 「價值」不是一個屬性,我用$_->text而不是你的$_->att('Value')的。

+0

感謝您的評論(是的,我希望提高我的編程技能)我已經修改了腳本,如圖所示。但即使使用/ Data/Value或簡單/ Value,我也無法提取所需的數字。我已經添加了更多的XML,但它很瘋狂,所以我希望這次能抓到足夠多。 – BrianB

+0

您的示例XML仍然無效。有一個''元素沒有相應的''。請小心點。我已經更新了我的答案,包括我的測試XML以及我編寫的代碼。這給出了正確的輸出。 –

+0

我很感激幫助。我添加了文件的語法,我非常高興。 – BrianB