【问题标题】:Parsing and iterating through an XML structure where each entry has multiple attributes解析和迭代每个条目具有多个属性的 XML 结构
【发布时间】:2014-06-06 04:49:10
【问题描述】:

我正在尝试处理项目的 XML 列表(在本例中为图像)并遍历每个项目。我不太了解 Perl 或哈希,但我找到了一些解释和示例(这里有很多)并写了一些似乎有效的东西。 XML 是一个元素列表,每个元素都包含一个唯一的“id”属性。

我正在使用 XML::Simple 中的 XMLin 来解析 XML。

当列表包含多个元素时,它会通过 'id' 进行迭代。但是好像只有一个的时候会混淆,把元素的每个属性都当作自己的值,导致运行时出错。

在使用“strict refs”时不能使用字符串(“0”)作为 HASH ref

我猜问题在于哈希键并不是唯一键,至少当只有一个条目时。所以我添加了代码来转储密钥。我还添加了一行来打印$imageforeach 循环中的内容。在中断的情况下,print "In loop; image ID=$image\n"; 行显示In loop; image ID=Serial 由于Serial 是与id 处于同一级别的属性,我猜这是问题所在(未正确使用id 作为键) .

这是我的代码:

    #!/usr/bin/perl
    use strict;
    use warnings;
    use XML::Simple;

    my $album_data_file = $ARGV[0];
    my $album_file_list = $ARGV[1];
    my $do_dump_data    = $ARGV[2];

    my $album_data = XMLin ( $album_data_file );
    my $LIST_FILE;

    if ( defined $album_file_list && "$album_file_list" ne "" )
    {
        if ( open ( $LIST_FILE, ">", "$album_file_list" ) )
        {
            print "Opened file $album_file_list as $LIST_FILE\n";
        }
    }

    if ( defined $do_dump_data && $do_dump_data eq "true" )
    {
        use Data::Dumper;
        print "data:\n\n";
        print Dumper ( $album_data );
        print "\n\n\n\n";

        print "keys:\n\n";
        print Dumper ( keys %{$album_data->{Images}->{Image}} );
        print "\n\n\n\n";
    }

    foreach my $image ( keys %{$album_data->{Images}->{Image}} )
    {
        print "In loop; image ID=$image\n";

        my $ref = $album_data->{Images}->{Image}->{$image};

        #
        # Write to files list: file name, ID, key, size, MD5
        #
        print $LIST_FILE ( "$ref->{FileName}\t$image\t$ref->{Key}"
                 . "\t$ref->{Size}\t$ref->{MD5Sum}\n" );
    }

    close ( $LIST_FILE );

这是一个破坏它的示例 XML 文件:

<?xml version="1.0" encoding="utf-8"?>
<rsp stat="ok">
  <method>images.get</method>
  <Images>
    <Image id="123" Key="xyz" Type="Album" Caption="Room 5083" FileName="MVI_2838.AVI" Format="MP4" Height="480" Keywords="China; Suite" LastUpdated="2014-04-19 11:49:45" Position="1" Serial="0" Size="116033" Width="640" Date="2014-04-19 11:46:24" Hidden="0" MD5Sum="6151e20053eeda87c688f8becae0d402" Watermark="0">
      <Album id="345" Key="zzy" />
    </Image>
  </Images>
</rsp>

这是转储完整 $album_data 的结果:

$VAR1 = {
      'method' => 'images.get',
      'Images' => {
                  'Image' => {
                             'Serial' => '0',
                             'Format' => 'MP4',
                             'Keywords' => 'China; Suite',
                             'Type' => 'Album',
                             'Size' => '116033',
                             'MD5Sum' => '6151e20053eeda87c688f8becae0d402',
                             'id' => '123',
                             'Key' => 'xyz',
                             'LastUpdated' => '2014-04-19 11:49:45',
                             'Album' => {
                                        'id' => '345',
                                        'Key' => 'zzy'
                                      },
                             'Position' => '1',
                             'Height' => '480',
                             'Date' => '2014-04-19 11:46:24',
                             'Caption' => 'Room 5083',
                             'FileName' => 'MVI_2838.AVI',
                             'Hidden' => '0',
                             'Width' => '640',
                             'Watermark' => '0',
                           }
                },
      'stat' => 'ok'
    };

这是转储键 %{$album_data->{Images}->{Image}} 构造的结果:

$VAR1 = 'Serial';
$VAR2 = 'Format';
$VAR3 = 'Keywords';
$VAR5 = 'Type';
$VAR6 = 'Size';
$VAR7 = 'MD5Sum';
$VAR9 = 'id';
$VAR10 = 'Key';
$VAR11 = 'LastUpdated';
$VAR12 = 'Album';
$VAR14 = 'Position';
$VAR15 = 'Height';
$VAR16 = 'Date';
$VAR17 = 'Caption';
$VAR19 = 'FileName';
$VAR20 = 'Hidden';
$VAR23 = 'Width';
$VAR24 = 'Watermark';
$VAR27 = 'Duration';

【问题讨论】:

    标签: perl hash foreach xml-parsing key


    【解决方案1】:

    我很欣赏 MillerXML::Simple 不鼓励使用的警告,以及他的警告,即由于有太多选项以难以定义和管理的方式交互,因此难以使用。在查看他建议的替换模块时,我偶然发现了一些在使用 XML::Simple 之前我应该​​知道的信息。特别是,我的脚本在 XML 中有多个图像时有效,但在只有一个图像时失败这一事实指出,如果使用XML::Simple,则将ForceArray 选项设置为元素(s ) 总是应该在一个数组中,即使一个特定的 XML 文件恰好包含一个。否则,元素有时会是一个数组,有时是一个标量,这会导致我看到的确切运行时错误。

    所以,在我的例子中,设置forcearray =&gt; [ 'Image' ] 使代码工作(通过强制所有&lt;image&gt; 元素进入一个数组,即使只有一个),比​​试图弄清楚如何使用不同的 XML 解析模块(尽管我毫不怀疑这样做会在将来节省时间)。

    【讨论】:

      【解决方案2】:

      根据XML::Simple #Status of this Module

      不鼓励在新代码中使用此模块。其他模块也可以提供更直接和一致的接口。特别推荐XML::LibXML

      这个模块的主要问题是大量的选项以及这些选项交互的任意方式 - 通常会产生意想不到的结果。

      欢迎使用带有错误修复和文档修复的补丁,但不太可能添加新功能。

      XML::Simple 如果您熟悉 perl 复杂的数据结构,那么它是一个用于快速解析 xml 的有用模块。然而,每当 xml 变得过于复杂时,模块就会失去它的用处,因为它是根据大量配置变量解析某些结构的任意方法。

      我仍然在极少数情况下使用XML::Simple,但我建议您查看XML::Twig 或上述XML::LibXML 以避免此类问题。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-07-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-11-27
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多