我正在尝试按照以下方式从XML文件中提取值:
<?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;
}
非常感谢任何帮助。
答案 0 :(得分: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;
}
请注意,我在原始帖子中意外省略了另一项更改 - 因为&#39;价值&#39;我不是$_->text
而是使用$_->att('Value')
。