2

我做了一个这样的练习,我如何计算 XML::Simple 折叠成数组的 XML 元素的数量,这样我就不必对元素的数量进行硬编码?我打算使用代码来解析更大的 xml 文件。我不想手动计算元素。

我可以用一些计数来代替幻数吗,有点像person.count等等hobbie.length。据我所知,我可以在 C# 中方便地使用这种语句。

#!/usr/bin/perl -w
use strict;
use XML::Simple;
use Data::Dumper;

my $tree = XMLin('./t1.xml');

print Dumper($tree);
print "\n";
for (my $i = 0; $i < 2; $i++) # magic number '2'
{
    print "$tree->{person}->[$i]->{first_name} $tree->{person}->[$i]->{last_name}\n";
    print "\n";
    for (my $j = 0; $j < 3; $j++) # magic number '3'
    {
        print $tree->{person}->[$i]->{hobbie}->[$j], "\n";
    }
    print "\n";
}

输出:

could not find ParserDetails.ini in C:/Perl/site/lib/XML/SAX
$VAR1 = {
          'person' => [
                      {
                        'hobbie' => [
                                    'bungy jumping',
                                    'sky diving',
                                    'knitting'
                                  ],
                        'last_name' => 'Bloggs',
                        'first_name' => 'Joe'
                      },
                      {
                        'hobbie' => [
                                    'Swim',
                                    'bike',
                                    'run'
                                  ],
                        'last_name' => 'LIU',
                        'first_name' => 'Jack'
                      }
                    ]
        };

Joe Bloggs

bungy jumping
sky diving
knitting

Jack LIU

Swim
bike
run

我的 Xml 源文件如下

<Document>
  <person>
    <first_name>Joe</first_name>
    <last_name>Bloggs</last_name>
    <hobbie>bungy jumping</hobbie>
    <hobbie>sky diving</hobbie>
    <hobbie>knitting</hobbie>
  </person>
  <person>
    <first_name>Jack</first_name>
    <last_name>LIU</last_name>
    <hobbie>Swim</hobbie>
    <hobbie>bike</hobbie>
    <hobbie>run</hobbie>
  </person>
</Document>
4

3 回答 3

5

由于 XML::Simple 将为您生成一个数组,因此很容易计算它的长度。

例如$tree->{person},是一个数组 - 或者更确切地说是一个数组引用(通过使用 XML::Simple 的 ForceArray 选项确保它是一个,即使只有 1 个人)。

  • 您可以通过首先将其取消引用到数组本身来获取其长度(使用@{}数组取消引用):@{ $tree->{person} }

  • 然后,您在标量上下文中使用结果数组,该数组的计算结果为数组中的元素数(换句话说,如果标量上下文已经应用,其他语言中的a.lenth/a.count函数转换为 Perl 习惯用法scalar(@a),该scalar()函数是可选的)。

    在这种情况下,数字比较运算符"<"将强制使用标量上下文,但如果不是这种情况,您可以使用scalar()函数。

例子:

# Don't forget ForceArray option of XML::Simple to ensure person and hobbie are array refs
for (my $i = 0; $i < scalar( @{ $tree->{person} } ); $i++) { # scalar() is optional here
    print "$tree->{person}->[$i]->{first_name} $tree->{person}->[$i]->{last_name}\n";
    print "\n";
    for (my $j = 0; $j < @{ $tree->{person}->[$i]->{hobbie} }; $j++) {
        print $tree->{person}->[$i]->{hobbie}->[$j], "\n";
    }
    print "\n";
}

需要注意的是,计算 Perl 数组长度的另一种方法是$#a构造,它返回数组最后一个元素的索引- 例如,比数组中元素的数量少 1。我不知道使用这两种方法之间的任何性能差异,所以如果你发现它们同样具有可读性,请酌情使用它们(例如,如果你需要获取最后一个元素的索引,使用$#a; 如果元素 #,使用@aor scalar(@a)as需要)。

一个很好的参考是Perl Data Structures Cookbook @perldoc

于 2010-10-09T03:54:52.810 回答
3
for my $person (@{ $tree->{person} }) {
    print "$person->{first_name} $person->{last_name}\n\n";
    for my $hobby (@{ $person->{hobbie} }) {
      print $hobby, "\n";
    }
    print "\n";
}

正如 DVK 所说,请确保您ForceArray => [qw/Person Hobby/]的 XMLin 选项中有,否则如果您只有一个人或任何人只有一个爱好,事情就不会成功。

于 2010-10-09T05:12:09.060 回答
1

如果您使用“C”样式的 for 循环,您只需要知道数组中的项目数。相反,您可以使用更糟糕的版本:foreach my $val ( @list )

#!/usr/bin/perl

use strict;
use warnings;

use XML::Simple qw(:strict XMLin);
use Data::Dumper;

my $tree = XMLin('./t1.xml', KeyAttr => { }, ForceArray => [ 'person', 'hobbie' ]);

foreach my $person ( @{ $tree->{person} } ) {
    print "$person->{first_name} $person->{last_name}\n";
    foreach my $hobbie ( @{ $person->{hobbie} } ) {
        print "$hobbie\n";
    }
}

为了更安全(并且可以说更具可读性),您可能需要检查 a<person>是否有任何<hobbie>元素,然后再尝试遍历它们:

foreach my $person ( @{ $tree->{person} } ) {
    print "$person->{first_name} $person->{last_name}\n";
    if(my $hobbies = $person->{hobbie}) {
        foreach my $hobbie ( @$hobbies ) {
            print "$hobbie\n";
        }
    }
}
于 2010-10-11T00:32:36.117 回答