使用 XML::Simple 时如何删除 Magic Number?

发布于 2024-09-26 21:56:22 字数 2250 浏览 3 评论 0原文

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

我可以使用一些计数来替换幻数吗,有点像 person.counthobbie.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>

I did a exercise like this, how do I calculate the # of XML elements collapsed into an array by XML::Simple so I don't have to hard-code the # of elements?
I plan to use the code to parse a bigger xml file. I don't want to cout the elements by manual.

Can I use some count to replace the magic numbers, a little like person.count or hobbie.length etc. As I know, I can use this kind of statement in C# conveniently.

#!/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";
}

Out put:

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

My Xml source file as below

<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>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

灼痛 2024-10-03 21:56:22

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

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

  • 您可以通过首先将其取消引用到数组本身来获取其长度(使用 @{} 数组取消引用):@{ $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; 如果有 # 个元素,请根据需要使用 @ascalar(@a))。

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

Since XML::Simple will produce an array for you, it's easy to count its length.

E.g. $tree->{person} is an array - or rather an array reference (make sure it's one by using ForceArray option of XML::Simple even if there's only 1 person).

  • You can get its length by first de-referencing it into an array itself (using @{} array de-reference): @{ $tree->{person} }

  • Then you use the resulting array in a scalar context which evaluates to the # of elements in the array (In other words, a.lenth/a.count functions in other languages translate to Perl idiom scalar(@a) were the scalar() function is optional if scalar context already applies).

    In this case, the numeric comparison operator "<" will force the scalar context, but if that was not the case you could have used scalar() function.

Example:

# 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";
}

As a note, a somewhat different method of counting the length of a Perl array is the $#a construct, which returns the index of the last element of the array - e.g. 1 less than the amount of elements in the array. I'm not aware of any performance difference between using the two approaches, so if you find both equally readable, use them as appropriate (e.g. if you need to get index of the last element, use $#a; if # of elements, use @a or scalar(@a) as needed).

A good reference is Perl Data Structures Cookbook @perldoc

慕烟庭风 2024-10-03 21:56:22
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 选项中,否则如果您只有一个人或任何人只有一种爱好,事情就不会成功。

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

and as DVK says, make sure you have ForceArray => [qw/Person Hobby/] in your XMLin options or else things won't work out if you only have one person or any person only has one hobby.

沦落红尘 2024-10-03 21:56:22

如果您使用“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";
    }
}

为了更安全(并且可以说更具可读性),您可能需要检查 <在尝试循环之前, /code> 具有任何 元素:

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";
        }
    }
}

You only need to know the number of items in the array if you are using the 'C' style for loop. Instead, you could use the more perlish version: 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";
    }
}

To be safer (and arguably more readable), you might want to check that a <person> has any <hobbie> elements at all, before trying to loop through them:

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";
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文