如何从perl中的hash中深入获取值

时间:2016-04-08 09:28:14

标签: perl hash data-dumper

我正在读取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'
    };

谢谢,

约翰。

3 个答案:

答案 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)。

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

  1. 您不必要地在XMLin()电话中引用该变量。

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

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

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

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

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

  4. 更新:我不愿意为您提供解决方案以解决您添加的问题,因为(因为我们从不厌倦这里指出)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。