2

このような演習を行いました。XML::Simple によって配列に折りたたまれた XML 要素の数を計算するにはどうすればよいので、要素の数をハードコードする必要はありませんか? このコードを使用して、より大きな xml ファイルを解析する予定です。手動で要素を数えたくありません。

いくつかのカウントを使用して、マジック ナンバーを置き換えることはできますperson.counthobbie.length?

#!/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}、配列、またはむしろ配列参照です (1 人しかいない場合でも、XML::Simple の ForceArray オプションを使用して配列であることを確認してください)。

  • 最初にそれを配列自体に逆参照することで、その長さを取得できます (@{}配列逆参照を使用)。@{ $tree->{person} }

  • 次に、配列内の要素の数に評価されるスカラー コンテキストで結果の配列を使用します (つまり、他の言語のa.lenth/関数は、スカラー コンテキストが既に適用されている場合、Perl のイディオムに変換されます)。a.countscalar(@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 少ないです。2 つのアプローチを使用した場合のパフォーマンスの違いについては認識していないため、両方が同等に読みやすい場合は、適切に使用してください (たとえば、最後の要素のインデックスを取得する必要がある場合は、を使用します。要素の数の場合は、またはを使用します)。必要)。$#a@ascalar(@a)

良いリファレンスは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";
}

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.

于 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 に答える