0

我正在阅读一个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'};
}

但是,如果 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'
    };

谢谢,

约翰。

4

3 回答 3

2

您已经有了如何使用 XML::Simple 执行此操作的答案。但我建议不要使用XML::Twig,而是使用它,这样更不讨厌。

为什么 XML::Simple “不鼓励”?

我将假设您的 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";
}
于 2016-04-08T14:49:49.757 回答
0

这是XML::Simple 被强烈弃用的原因之一- 当您期望哈希引用时,它偶尔会抛出数组引用。

您可以看到 的值$rulesxml->{'Roots'}->{'Root'}是一个数组 ref,而不是一个哈希 ref,因为它以 a[而不是 a开头{

如果数据正是您在此处显示的,那么您需要做的就是在您的代码中插入一个数组查找。

Dumper($myxml->{'Roots'}->{'Root'}->[0]->{'Profiles'}->{'Profile'}); 

我使用了 0,因为(目前?)该数组中只有一个元素。如果您的数据更复杂并且数组中有多个元素,那么您将需要使用循环。

对于这样的工作,我强烈建议花时间学习XPath并使用支持它的模块(我喜欢XML::LibXML)。

简化代码的其他几种方法:

  1. XMLin()您在调用中不必要地引用了变量。

    $myxml = XMLin($configfile); # Works fine without quotes

  2. 您可以在多级查找中省略中间箭头。

    $myxml->{'Roots'}{'Root'}[0]{'Profiles'}{'Profile'}

  3. 您还可以省略散列键名称周围的大多数引号。

    $myxml->{Roots}{Root}[0]{Profiles}{Profile}

更新:我不愿意为您添加的问题提供解决方案,因为(正如我们在这里从不厌倦指出的那样)XML::Simple 是大多数 XML 问题的糟糕解决方案。

但是,给定您的数据结构(或者更确切地说,我已经清理过的数据结构的一个版本,因此它实际上可以编译!)这就是您遍历它的方式(是的,它是一个嵌套循环)。

for my $root (@{ $myxml->{Roots}{Root} }) {
  for my $profile (@{ $root->{Profiles}{Profile} }) {
    if ($profile->{Name} eq 'Bob') {
      say $profile->{Status};
    }
  }
}

但请不要使用这种方法。Sobrique 建议的XML::Twig 方法是一个更好的答案。基于 XML::LibXML 的 XPath 方法也类似。

无论何时从 XML 文档中提取数据,XPath 都可能是最好的解决方案。如果您正在处理 XML,那么您确实需要在您的工具包中包含 XPath。

于 2016-04-08T09:58:46.800 回答
0

Root 的值是一个ArrayRef。您忽略了数组并将其视为其中的 HashRef 之一。您需要遍历数组或使用特定索引访问它。

于 2016-04-08T09:32:15.310 回答