2010-10-09 13 views
2

J'ai fait un exercice comme celui-ci, comment puis-je calculer le nombre d'éléments XML réduits dans un tableau par XML :: Simple, donc je n'ai pas besoin de coder en dur le # d'éléments? Je prévois d'utiliser le code pour analyser un plus grand fichier xml. Je ne veux pas couturer les éléments manuellement. Puis-je utiliser un certain nombre pour remplacer les nombres magiques, un peu comme person.count ou hobbie.length etc. Comme je sais, je peux utiliser ce type de déclaration en C# commodément.Comment puis-je supprimer Magic Number lors de l'utilisation de XML :: Simple?

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

eteint:

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 

Mon fichier source Xml comme ci-dessous

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

Si je vous, je reformuler votre question de « magie #s » à « comment puis-je calculer le # d'éléments XML effondrés dans un tableau par XML :: simple, donc je n'ont pas coder en dur le # d'éléments " – DVK

Répondre

5

Depuis XML :: Simple produira un tableau pour vous, il est facile de compter sa longueur.

E.g. $tree->{person} est un tableau - ou plutôt une référence de tableau (assurez-vous qu'il en est un en utilisant l'option ForceArray de XML :: Simple même s'il n'y a qu'une seule personne).

  • Vous pouvez obtenir sa longueur d'abord de-référencement dans un tableau lui-même (en utilisant @{} tableau de référence): @{ $tree->{person} }

  • Ensuite, vous utilisez le tableau résultant dans un contexte scalaire qui évalue à le # d'éléments dans le tableau (En d'autres termes, a.lenth/a.count fonctions dans d'autres langues traduisent en idiome Perl scalar(@a) où la fonction scalar() est facultative si le contexte scalaire s'applique déjà).

    Dans ce cas, l'opérateur de comparaison numérique "<" forcera le contexte scalaire, mais si ce n'était pas le cas, vous auriez pu utiliser la fonction scalar().

Exemple:

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

En remarque, un procédé quelque peu différent de compter la longueur d'une matrice Perl est la construction $#a, qui renvoie l'index du dernier élément du tableau - par exemple 1 inférieur à la quantité d'éléments dans le tableau. Je ne connais pas de différence de performance entre les deux approches, donc si vous trouvez les deux également lisibles, utilisez-les comme il convient (par exemple, si vous avez besoin d'indexer le dernier élément, utilisez $#a ou # @a ou scalar(@a) au besoin).

Une bonne référence est Perl Data Structures Cookbook @perldoc

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

et comme le dit DVK, assurez-vous que vous avez ForceArray => [qw/Person Hobby/] dans vos options de XMLIN ou bien les choses ne fonctionnera pas si vous avez une seule personne ou toute autre personne n'a qu'une seule loisir.

1

Vous n'avez besoin de connaître le nombre d'éléments de la matrice que si vous utilisez le style 'C' pour la boucle.Au lieu de cela, vous pouvez utiliser la version plus perlienne: 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"; 
    } 
} 

Pour être plus sûr (et sans doute plus facile à lire), vous pouvez vérifier que <person> a des <hobbie> éléments du tout, avant d'essayer de boucle à travers eux:

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