我正在读取xml文件,
$myxml = XMLin("$configfile");
当我使用Dumper打印它时(print Dumper($ myxml);)我得到了这个......
$VAR1 = {
'Timeout' => 5,
'Roots' => {
'Root' => [
{
'Name' => 'Sales',
'Level' => 'Indeterminate',
'Profiles' => {
'Profile' => [
{
'Name' => 'Bill',
'Age' => '50',
'Status' => Active
},
{
'Name' => 'Bob',
'Age' => '24',
'Status' => Inactive
}
]
},
'Interval' => 'Order',
'Action' => 'Reject'
},
{
'Name' => 'User',
'Level' => 'Indeterminate',
'Profiles' => {
'Profile' => [
{
'Name' => 'User',
'Action' => 'Reject',
'User' => 'acount'
},
{
'Name' => 'Admin',
'Action' => 'Accept',
'User' => 'acount'
},
]
}
};
我想阅读此哈希并获取所有不活动状态'状态'或者获得鲍勃的状态..
{
'Name' => 'Bob',
'Age' => '24',
'Status' => Inactive
}
所以要获取一个人的个人资料信息..
Dumper($myxml->{'Roots'}->{'Root'}[0]{'Profiles'}{'Profile'}[2]);
例如,获取Bob的状态
if ($myxml->{'Roots'}->{'Root'}[0]{'Profiles'}{'Profile'}[1]{'Name'} eq "Bob") {
$status = $myxml->{'Roots'}->{'Root'}[0]{'Profiles'}{'Profile'}[1]{'Status'};
}
但是,如何循环浏览此xml,以便继续检查{' Roots'} - > {' Root'}和{'个人资料'如果Bob不在[0]和[1]位置,则{'个人资料'}。一个双foreach循环?
我已经包含了xml的一个例子..
<Root Name="Sales" Level="Indeterminate" Profile="Order" Interval="Order" Action="Reject">
<Profiles>
<Profile Name="Bill" Age="50" Status=Active />
<Profile Name="Bob" Age="24" Status=InActive />
<Profile Name="Ben" Age="45" Status=Active />
</Profiles>
</Root>
产生这个:
$VAR1 = {
'Name' => 'Sales',
'Type' => 'Indeterminate',
'Profiles' => {
'Profile' => [
{
'Name' => 'Bill',
'Age' => '50',
'Status' => Active
},
{
'Name' => 'Bob',
'Age' => '24',
'Status' => InActive
},
{
'Name' => 'Ben',
'Age' => '45',
'Status' => Active
}
]
},
'Interval' => 'Order',
'Action' => 'Reject'
};
谢谢,
约翰。
答案 0 :(得分:2)
您已经回答了如何使用XML :: Simple完成此操作。但我建议不要,而是使用XML::Twig
代替,这不是那么令人讨厌。
Why is XML::Simple "Discouraged"?
我将假设您的XML看起来有点像这样:
<opt Timeout="5">
<Roots>
<Root Action="Reject" Interval="Order" Level="Indeterminate" Name="Sales">
<Profiles>
<Profile Age="50" Name="Bill" Status="Active" />
<Profile Age="24" Name="Bob" Status="Inactive" />
</Profiles>
</Root>
</Roots>
</opt>
我无法确定,因为这是XML::Simple
的喜悦。但是:
#!/usr/bin/env perl
use strict;
use warnings;
use XML::Twig;
my $twig = XML::Twig -> new -> parsefile ( $configfile );
print $twig -> get_xpath ( '//Profile[@Name="Bob"]',0 ) -> att('Status')
这使用xpath
找到您想要的属性 - //
表示“树中的任意位置”搜索。
但你可以改为:
print $twig -> get_xpath ( '/opt/Roots/Root/Profiles/Profile[@Name="Bob"]',0 ) -> att('Status')
很多更简单你不同意吗?
或者迭代所有'个人档案':
foreach my $profile ( $twig -> get_xpath ('//Profile' ) ) {
print $profile -> att('Name'), " => ", $profile -> att('Status'),"\n";
}
答案 1 :(得分:0)
Root的值是 ArrayRef 。您忽略了数组并将其视为内部的HashRef之一。您需要遍历数组或使用特定索引访问它。
答案 2 :(得分:0)
这是XML::Simple is strongly deprecated的原因之一 - 当您期望哈希引用时,它偶尔会引入数组引用。
您可以看到$rulesxml->{'Roots'}->{'Root'}
的值是数组引用,而不是哈希引用,因为它以[
而不是{
开头。
如果数据与您在此处显示的完全相同,那么您需要做的就是在代码中插入数组查找。
Dumper($myxml->{'Roots'}->{'Root'}->[0]->{'Profiles'}->{'Profile'});
我使用0,因为(当前?)该数组中只有一个元素。如果您的数据更复杂并且阵列中有多个元素,那么您将需要使用循环。
对于这样的工作,我强烈建议您花时间学习XPath并使用支持该模块的模块(我喜欢XML::LibXML)。
其他几种简化代码的方法:
您不必要地在XMLin()
电话中引用该变量。
$myxml = XMLin($configfile); # Works fine without quotes
您可以在多级查找中省略中间箭头。
$myxml->{'Roots'}{'Root'}[0]{'Profiles'}{'Profile'}
您还可以省略散列键名称周围的大多数引号。
$myxml->{Roots}{Root}[0]{Profiles}{Profile}
更新:我不愿意为您提供解决方案以解决您添加的问题,因为(因为我们从不厌倦这里指出)XML :: Simple是解决大多数XML问题的可怕解决方案
但是,考虑到你的数据结构(或者更确切地说,是我已经清理过的数据结构的一个版本,所以它实际编译了!)这就是你如何遍历它(是的,它是一个嵌套循环)。 / p>
for my $root (@{ $myxml->{Roots}{Root} }) {
for my $profile (@{ $root->{Profiles}{Profile} }) {
if ($profile->{Name} eq 'Bob') {
say $profile->{Status};
}
}
}
但请不要使用这种方法。 Sobrique提出的XML::Twig approach是一个更好的答案。基于XML :: LibXML的XPath方法也是类似的。
无论何时从XML文档中提取数据,XPath都可能是最佳解决方案。如果你正在处理XML,那么你真的需要在你的工具包中使用XPath。