在perl中,我如何循环这个结构?

时间:2016-12-19 19:31:38

标签: xml perl structure

我正在创建一个xml来传递给API,API返回它(数据转储):

    (
    "Data::Dump",
    {
      SiteDevices => {
        "device"  => {
                       1102   => { address => "1.2.3.4", riskfactor => "1.0", riskscore => "0.0" },
                       1136   => { address => "1.2.3.5", riskfactor => "1.0", riskscore => "0.0" },
                       20491  => { address => "1.2.3.6", riskfactor => "1.0", riskscore => "0.0" },
                       129644 => { address => "1.2.3.7", riskfactor => "1.0", riskscore => "0.0" },
                       129645 => { address => "1.2.3.8", riskfactor => "1.0", riskscore => "0.0" },
                       130408 => { address => "1.2.3.9", riskfactor => "1.0", riskscore => "0.0" },
                       135975 => { address => "1.2.3.10", riskfactor => "1.0", riskscore => "0.0" },
                       137642 => { address => "1.2.3.11", riskfactor => "1.0", riskscore => "0.0" },
                     },
        "site-id" => 27,
      },
      success => 1,
    },
)

我想循环并打印与它们相关的设备和IP,而我在生活中无法想出任何代码来实现它。我错过了什么?!我试图循环哈希,散列哈希等等。永远不能让它工作。如果你们中的任何人有一秒钟并且可以提供答案,那么我可以羞愧地摇头,那真是棒极了。

我试过了:

foreach my $key (keys %{ $output->{‘SiteDevices’}->{‘device’} }) {
         print $key 
         print $key->{‘address’} 
}

foreach my $key (keys %{ $output{‘SiteDevices’}{‘device’} }) {
         print $key 
         print $key{‘address’} 
}

但不起作用。

2 个答案:

答案 0 :(得分:5)

你提到这是解析的XML。看起来您已使用XML::Simplethat's just not a good idea.

对其进行了解析

为什么不改为:

#!/usr/bin/env perl
use strict;
use warnings;

use XML::Twig; 

## get xml somehow here. parsefile if it's a file already. 
my $twig = XML::Twig -> new -> parse ( $your_xml );

foreach my $device ( $twig -> get_xpath('//devices' ) ) {
   print $device -> att('name'), " => "; 
   print $device -> att('address'),"\n";
}

这里有用的是xpath - 它不是正则表达式,但它有点类似 - 它适用于XML。在这种情况下,//device说'在树中的任何位置找到<device>节点。 (然后我们提取属性)。

这可能适用于您的方案,但您可以通过指定更长的路径来更具体:

  • ./device - 直接位于当前节点下方。
  • .//device - 当前节点下方的任何位置。
  • /root/SiteDevices/device - 与此“树”特定匹配的节点。

您还可以使用xpath搜索属性:

  • .//device[@name="1136"]会找到具有适当值和属性的内容。

有关如何执行此操作的一些指南,请参阅XML Twig快速参考。

答案 1 :(得分:2)

我相信以下循环将完成您要完成的任务。它从树中获取每个设备,然后提取其地址,并打印:

for my $device (keys %{ $output->{SiteDevices}{device} }){
    print "$device: $output->{SiteDevices}{device}{$device}{address}\n";
}

在您的测试中,您尝试将密钥名称用作哈希/哈希引用,但这不会起作用。您需要将提取的密钥放回哈希中以执行进一步的提取。

输出,基于我从您的问题中提取的单个记录:

129644: 1.2.3.7
129645: 1.2.3.8
130408: 1.2.3.9
137642: 1.2.3.11
1136: 1.2.3.5
135975: 1.2.3.10
1102: 1.2.3.4
20491: 1.2.3.6