在Perl中,XML :: Simple无法取消引用由Data :: Dumper解析的多维关联数组 [英] In Perl, XML::Simple is not able to dereference multi dimensional associative array parsed by Data::Dumper

查看:79
本文介绍了在Perl中,XML :: Simple无法取消引用由Data :: Dumper解析的多维关联数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下是我要解析的xml文件:

Following is the xml file that I want to parse:

<?xml version="1.0" encoding="UTF-8"?>

<topic id="yerus5" xmlns:ditaarch="http://dita.oasis-open.org/architecture/2005/">



<title/>
  <shortdesc/>
  <body>
<p><b>CCU_CNT_ADDR: (Address=0x004 Reset=32'h1)</b><table id="table_r5b_1xj_ts">
<tgroup cols="4">
  <colspec colnum="1" colname="col1"/>
  <colspec colnum="2" colname="col2"/>
  <colspec colnum="3" colname="col3"/>
  <colspec colnum="4" colname="col4"/>
  <tbody>
        <row>
          <entry>Field</entry>
          <entry>OFFSET</entry>
          <entry>R/W Access</entry>
          <entry>Description</entry>
        </row>
        <row>
          <entry>reg2sm_cnt</entry>
          <entry>15:0</entry>
          <entry>R/W</entry>
          <entry>Count Value to increment in the extenral memory at the specified location.
            Default Value of 1. A Count value of 0 will clear the counter value</entry>
        </row>
        <row>
          <entry>ccu2bus_endianess</entry>
          <entry>24</entry>
          <entry>R/W</entry>
          <entry>Endianess of the data structure bit</entry>
        </row>
        <row>
          <entry>ccu_lane_sel</entry>
          <entry>25</entry>
          <entry>R/W</entry>
          <entry>ccu_lane_sel bit. Indicates the lane selection bit of the 32-bit location to
            update</entry>
        </row>
        <row>
          <entry>ccu_rdinvalid</entry>
          <entry>26</entry>
          <entry>R/W</entry>
          <entry>ccu_rdinvalid bit. Indicates if the read value from the bus needs to be stored
            or not.</entry>
        </row>
      </tbody>
    </tgroup>
  </table></p>


</body>
</topic>

运行以下代码后:

#!/usr/bin/perl


# use module
use XML::Simple;
use Data::Dumper;

# create object
$xml = new XML::Simple(); #(KeyAttr=>[]);

# read XML file
$data = $xml->XMLin("test.xml");

# access XML data
print Dumper($data);



# dereference hash ref



    # foreach $b (@{$p->{b}})
    # {

# }
foreach $body (@{$data->{body}})
{
 foreach $p (@{$body->{p}})
 {
     foreach $table (@{$p->{table}})
     {

        foreach $tgroup (@{$table->{tgroup}})
        {

            foreach $tbody (@{$tgroup->{tbody}})
            {

                foreach $row (@{$tbody->{row}})
                {
                    foreach $entry ((@{$row->{entry}})->[3])
                    {
                    print $entry,"\n";
                    }

                }
            }
        }
    }
}

}

我遇到此错误:在ppfe.pl第28行处没有数组引用.(在foreach $body (@{$data->{body}}))

我想访问<entry></entry>的每个数据.以上代码仅用于访问说明"列.该怎么做?

I want to access each data of the <entry></entry>. Above code only is only accessing the 'Description' column. How to do that?

关于上述问题,

我无法提取每个<b></b>文本的详细信息.以下是示例输出:

I am not able to extract details particularly for each <b></b> text. Following is sample output:

Name: CCU_CNT_ADDR: (Address=0x004 Reset=32'h1)
Field: reg2sm_cnt 
OFFSET: 15:0 
Access: R/W 
Description: Count Value to increment in the extenral memory at the specified location. Default Value of 1. A Count value of 0 will clear the counter value 
Filed: ccu2bus_endianess 
OFFSET: 24 
Access: R/W 
Description: Endianess of the data structure bit 
 .
 .
 .
 .
 .
 .
 .
Name: CCU_STAT_ADDR: (Address=0x008 Reset=32'h0) 
Field: fifo_cnt 
.
 .
 .
 .
 .
 .
 .

推荐答案

请勿使用即使XML::Simple说不要使用XML::Simple".

不建议在新代码中使用此模块.提供了其他模块,它们提供了更直接,更一致的界面.

The use of this module in new code is discouraged. Other modules are available which provide more straightforward and consistent interfaces.

请尝试以下类似方法:

use strict;
use warnings;
use XML::Twig;

XML::Twig->new(
    'twig_handlers' => {
        'entry' => sub { print $_ ->text, "\n" }
    }
)->parsefile ('your_file.xml');

这将打印所有entry元素的文本内容,这似乎是您要尝试执行的操作?

This will print the text content of all the entry elements, which appears to be what you're trying to do?

XML::Twig有两种非常方便的机制-一种使用twig_handler查找并打印符合规范的节点-这种按需使用"的功能在处理大型XML或要进行编辑时特别有用处理之前.

XML::Twig has two really handy mechanisms - one of using a twig_handler to find and print nodes matching a spec - this works 'as you go' which is particularly useful when handling large XML, or if you want to edit it before processing.

但是,它还允许您随后处理"数据:

However, it also allows you to 'handle' data afterwards:

my $twig = XML::Twig->new( 'pretty_print' => 'indented_a' )->parsefile('your_xml_file');

foreach my $element ( $twig -> get_xpath ("//entry") )
{
    print $element ->text, "\n";
}

或者您可以像上面一样使用节点的完整路径:

Or you could use a full path to the node as you're doing above:

$twig->root->get_xpath("body/p/table/tgroup/tbody/row/entry") )

不过是针对您的问题:

仅上述代码仅访问说明"列.该怎么做?

Above code only is only accessing the 'Description' column. How to do that?

那是因为您正在这样做:

That's because you're doing this:

foreach $entry ((@{$row->{entry}})->[3])

例如尝试获取entry数组中的第4个元素,即Description.

E.g. trying to get the 4th element in the entry array, which is Description.

参考注释-我建议您将条目"转换为XML数据结构之外的哈希.

With reference to the comments - I'd suggest you convert your 'entries' into a hash outside the XML data structure.

赞:

use strict;
use warnings;
use XML::Twig;

use Data::Dumper;

my @headers;

my $column_to_show = 'Field';

sub process_row {
    my %entries;

    my ( $twig, $row ) = @_;
    my @row_entries = map { $_->text } $row->children;
    if (@headers) {
        @entries{@headers} = @row_entries;
        print $column_to_show, " => ", $entries{$column_to_show}, "\n";
    }
    else {
        @headers = @row_entries;
    }
}

my $twig = XML::Twig->new(
    'pretty_print' => 'indented_a',
    twig_handlers  => { 'row' => \&process_row }
)->parsefile ( 'your_file.xml' ); 

这是什么:

  • 在每个row元素上触发该处理程序.
  • entry子元素(及其文本)提取到数组中. @row_entries.
  • 使用标题"行将其转换为哈希.
  • 打印与特定键$column_to_show匹配的哈希值.
  • fire that handler on each row element.
  • extract the entry subelements (and their text) into an array. @row_entries.
  • Use the "header" row to turn that into a hash.
  • Print the hash value that matches a specific key $column_to_show.

根据是否要处理数据而不是打印数据,可以将其转换为数组或类似的哈希.

Depending on whether you're doing any more with the data than print it, you can turn that into a hash of arrays or similar.

或者您可以只打印$row_entries[3]而不是当然;).

Or you could just print $row_entries[3] instead of course ;).

这篇关于在Perl中,XML :: Simple无法取消引用由Data :: Dumper解析的多维关联数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆