我正在尝试解析包含以下格式的服务器列表的xml文件(serverslist2.xml):
<?xml version="1.0"?>
<servers>
<aplication name="App1">
<env name="Test">
<appliance alias="app1t1" conname="10.0.0.10:80" />
<appliance alias="app1st1" conname="10.0.0.10:443" />
</env>
<env name="Prod">
<appliance alias="app1p1" conname="10.0.1.10:80" />
<appliance alias="app1sp1" conname="10.0.1.10:443" />
<appliance alias="app1p2" conname="10.0.1.11:80" />
<appliance alias="app1sp2" conname="10.0.1.11:443" />
</env>
</aplication>
<aplication name="App2">
<env name="Test">
<appliance alias="app2t1" conname="10.0.0.20:80" />
<appliance alias="app2st1" conname="10.0.0.20:443" />
</env>
<env name="Prod">
<appliance alias="app2p1" conname="10.0.1.20:80" />
<appliance alias="app2sp1" conname="10.0.1.20:443" />
<appliance alias="app2p2" conname="10.0.1.21:80" />
<appliance alias="app2sp2" conname="10.0.1.21:443" />
</env>
</aplication>
</servers>
我可能会收到&#34;别名&#34;变量中的值(我知道它是唯一的),需要检索&#34; conname&#34;值。
到目前为止,我的代码(testxpath.pl)看起来像:
#!/usr/bin/perl
use XML::XPath;
my $file = 'serverslist2.xml';
my $xp = XML::XPath->new(filename => $file);
my $server = app2st1;
print "Starting Test1:\n";
foreach my $test1 ($xp->find('//appliance[@alias="' . $server . '"]')->get_nodelist) {
print "Test1 output: " , $test1->find('@conname') , "\n";
} ;
print "Starting Test2:\n";
my $test2 = $xp->find('//appliance[@alias="' . $server . '"]')->get_nodelist ;
print "Test2 output: " , $test2->find('@conname') , "\n";
奇怪的是,使用foreach分支的Test1可以工作,但没有它,即使使用基本相同的命令也会失败。
输出结果为:
$ ./testxpath.pl
Starting Test1:
Test1 output: 10.0.0.20:443
Starting Test2:
Can't call method "find" without a package or object reference at ./testxpath.pl line 16.
有人可以澄清错误以及如何解决问题吗? 此外,如果有更好的方法使用这个或其他一些perl XML处理lib,那将是值得赞赏的。 (P.S。:我可能不会简单地使用一些正则表达式,因为xml将始终符合此标准,但不一定是&#34;打印良好&#34;)
此致 雷纳托
答案 0 :(得分:0)
->get_nodelist
会返回一个列表。
因此,您必须将您的变量放在括号中,否则只会为其分配列表计数而不是第一个值:
my ($test2) = $xp->find(qq{//appliance[\@alias="$server"]})->get_nodelist;
或者,由于您只是在寻找单个值,因此可以使用findvalue
方法:
print "Starting Test3:\n";
my $conname = $xp->findvalue(qq{//appliance[\@alias="$server"]/\@conname});
print "Test3 output: $conname\n";
这是一个完整的工作脚本:
#!/usr/bin/perl
use strict;
use warnings;
use XML::XPath;
my $file = 'serverslist2.xml';
my $xp = XML::XPath->new(xml => do { local $/; <DATA> });
my $server = 'app2st1';
print "Starting Test1:\n";
foreach my $test1 ( $xp->find(qq{//appliance[\@alias="$server"]} )->get_nodelist ) {
print "Test1 output: ", $test1->find('@conname'), "\n";
}
print "Starting Test2:\n";
my ($test2) = $xp->find( qq{//appliance[\@alias="$server"]} )->get_nodelist;
print "Test2 output: ", $test2->find('@conname'), "\n";
print "Starting Test3:\n";
my $conname = $xp->findvalue(qq{//appliance[\@alias="$server"]/\@conname});
print "Test3 output: $conname\n";
__DATA__
<?xml version="1.0"?>
<servers>
<aplication name="App1">
<env name="Test">
<appliance alias="app1t1" conname="10.0.0.10:80" />
<appliance alias="app1st1" conname="10.0.0.10:443" />
</env>
<env name="Prod">
<appliance alias="app1p1" conname="10.0.1.10:80" />
<appliance alias="app1sp1" conname="10.0.1.10:443" />
<appliance alias="app1p2" conname="10.0.1.11:80" />
<appliance alias="app1sp2" conname="10.0.1.11:443" />
</env>
</aplication>
<aplication name="App2">
<env name="Test">
<appliance alias="app2t1" conname="10.0.0.20:80" />
<appliance alias="app2st1" conname="10.0.0.20:443" />
</env>
<env name="Prod">
<appliance alias="app2p1" conname="10.0.1.20:80" />
<appliance alias="app2sp1" conname="10.0.1.20:443" />
<appliance alias="app2p2" conname="10.0.1.21:80" />
<appliance alias="app2sp2" conname="10.0.1.21:443" />
</env>
</aplication>
</servers>
输出:
Starting Test1:
Test1 output: 10.0.0.20:443
Starting Test2:
Test2 output: 10.0.0.20:443
Starting Test3:
Test3 output: 10.0.0.20:443