【问题标题】:Not an Array reference navigating XML::Simple structure不是导航 XML::Simple 结构的数组引用
【发布时间】:2015-12-16 09:37:23
【问题描述】:

我是 Perl 的新手。我正在尝试为 xml 文件中的每个条目循环以执行一项任务,但它因“不是第 9 行的数组引用”而死。

我的脚本是

#!/usr/bin/perl
# use module
use XML::Simple;
# create object
$xml = new XML::Simple;
# read XML file
$data = $xml->XMLin("data.xml");
# access XML data
foreach my $entry (@{$data->{entry}}){
print $entry->{'source-translation'}->{'static-ip'}-{'translated-address'};
}

我的 XML 文件数据是

<?xml version="1.0"?>
<config version="6.0.0" urldb="paloaltonetworks">
  <entry name="DROP NAT">
    <source-translation>
      <static-ip>
        <bi-directional>yes</bi-directional>
        <translated-address>192.91.75.129</translated-address>
      </static-ip>
    </source-translation>
    <to>
      <member>Outside</member>
    </to>
    <from>
      <member>DROP</member>
    </from>
    <source>
      <member>192.91.66.72</member>
    </source>
    <destination>
      <member>any</member>
    </destination>
    <service>any</service>
    <description>NAT for DROP FTP Server</description>
    <to-interface>ethernet1/1</to-interface>
    <nat-type>ipv4</nat-type>
  </entry>
  <entry name="SDROP NAT">
    <source-translation>
      <static-ip>
        <bi-directional>yes</bi-directional>
        <translated-address>192.91.75.154</translated-address>
      </static-ip>
    </source-translation>
    <to>
      <member>Outside</member>
    </to>
    <from>
      <member>DROP</member>
    </from>
    <source>
      <member>192.91.66.79</member>
    </source>
    <destination>
      <member>any</member>
    </destination>
    <service>any</service>
    <description>NAT for SFTP server SDROP</description>
    <to-interface>ethernet1/1</to-interface>
    <nat-type>ipv4</nat-type>
  </entry>
</config>

我想在每个条目中列出已翻译的地址。假设有很多这样的条目。请帮帮我。

【问题讨论】:

  • use Data::Dumper; print Dumper $data;
  • 您的脚本只有 11 行。 13号线是哪一条?
  • 注意:'translated-address'前面有一个减号可能你的意思是-&gt;

标签: arrays xml perl


【解决方案1】:

KeyAttr 选项的默认值为

KeyAttr => [qw( name key id )]

这意味着 XML::Simple 将转换

 [ { name => $name1, ... }, { name => $name2, ... }, ... ]

进入

 { $name1 => { ... }, $name2 => { ... }, ... }

您可以使用以下选项来获得您期望的结构。

KeyAttr => []

如果您希望代码在仅存在一个条目时工作,请不要忘记提供以下选项:

ForceArray => [qw( entry )]

XML::Simple 的用法是discouraged,即使它自己的文档也是如此。


XML::LibXML 解决方案:

use XML::LibXML qw( );
my $parser = XML::LibXML->new();
my $doc = $parser->parse_file('data.xml');
for my $node ($doc->findnodes(
   '/config/entry/source-translation/static-ip/translated-address'
)) {
   print($node->textContent(), "\n");
}

【讨论】:

    【解决方案2】:

    正如您所说,$data-&gt;{entry} 不是您的数据结构中的数组引用;它是一个哈希引用。

    检查下面的脚本,它访问哈希中的数据:

    #!/usr/bin/perl
    use v5.10; use strict; use warnings;
    use XML::Simple;
    
    my $xml = new XML::Simple;
    my $data = $xml->XMLin("data.xml");
    for my $entry (keys %{$data->{entry}}){
      say $data->{entry}->{$entry}->{'source-translation'}->{'static-ip'}->{'translated-address'};
    }
    

    正如 Сухой27 指出的那样;如果您使用 Data::Dumper,您将能够看到数据结构,并且您会看到哈希而不是假设的数组。

    【讨论】:

      【解决方案3】:

      这是你的问题:

      use XML::Simple;
      

      XML::Simple 误导你。这一点都不简单。除非您绝对别无选择(您可能会这样做 - 它不是核心),否则使用另一个解析器会减轻痛苦。

      喜欢:

      use XML::Twig;
      print $_ -> trimmed_text,"\n" for  XML::Twig -> new -> parsefile ( 'data.xml') -> get_xpath ( '//translated-address');
      

      展开后更像:

      use strict ;
      use warnings;
      my $twig = XML::Twig -> new;
      $twig -> parsefile ( 'data.xml');
      foreach my $entry ( $twig -> findnodes ('//entry'))  {
          print $entry -> first_child('source-translation') -> first_child('static-ip') -> first_child_text('translated-address');
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-01-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-06-07
        • 2012-05-12
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多