2014-07-11 8 views
-2

Je dois analyser plusieurs fichiers XML en utilisant Perl et stocker des variables dans un hachage. J'aimerais filtrer certains attributs si possible. Plus tard dans mon code, je tire des données du hachage et les insère dans une base de données.Meilleure façon d'analyser XML compliqué avec Perl?

J'ai utilisé XML::Parser mais je préférerais analyser un hachage plutôt que de gérer chaque étiquette comme elle a rencontré. Aucune suggestion?

Je souhaite ignorer tout chemin ayant l'attribut kind="dir". J'ai besoin de l'auteur, la date, msg, et les types de fichiers (les extensions de fichier) des chemins. Les balises <path> peuvent avoir n'importe quel nombre et sont soit kind "fichier" ou "dir". Il peut également y avoir plusieurs étiquettes <logentry>.

<?xml version="1.0" encoding="UTF-8"?> 
<log> 
    <logentry revision="3989"> 
     <author>cergyl</author> 
     <date>2013-07-19T05:31:01.212620Z</date> 
     <paths> 
      <path action="M" kind="dir">/team.admin/trunk/auth.conf</path> 
     </paths> 
     <path action="M" kind="file">/team.admin/trunk/file.cpp</path> 
     <msg>Whitespace change to verify repository synchronization</msg> 
    </logentry> 
</log> 

my $XML_Parser = XML::Parser->new(
            Handlers => { 
               Start => \&hdl_xml_tag_start, 
               End  => \&hdl_xml_tag_end, 
               Char => \&hdl_xml_nonmarkup_char, 
               Default => \&hdl_xml_default 
               } 
           ); 

# This event is generated when an XML start tag is recognized. Parser is an XML::Parser::Expat instance. 
sub hdl_xml_tag_start 
{ 
    my ($parser, $element, %attributes) = @_; 
    $attributes{ '_str' } = "$element:"; 
    $XML_Attributes_Hash_Ref = \%attributes; 
    return; 
} 

# This event is generated when an XML end tag is recognized. Note that an XML empty tag (<foo/>) generates both a start and an end event. 
sub hdl_xml_tag_end 
{ 
    my ($parser, $element) = @_; 

    #format_message($XML_Attributes_Hash_Ref); 
    format_svn_history($XML_Attributes_Hash_Ref); 
    return; 
} 


# This event is generated when non-markup is recognized. The non-markup sequence of characters is in String. 
# A single non-markup sequence of characters may generate multiple calls to this handler. 
sub hdl_xml_nonmarkup_char 
{ 
    my ($parser, $string) = @_; 
    $XML_Attributes_Hash_Ref->{ '_str' } .= $string; 
    return; 
} 

#This is called for any characters that don't have a registered handler. 
sub hdl_xml_default { return; } 
+1

Pourquoi pas 'XML :: Parser' travaille pour vous? – friedo

+2

J'aime vraiment XML :: Twig, pas moins parce qu'il me permet de «purger» comme je vais pour économiser l'empreinte de la mémoire. – Sobrique

+0

@friedo, j'ai édité ma question. Cela fonctionne, mais je préférerais prendre le tout en une fois dans un hachage. – Busch

Répondre

2

Avec les informations limitées dont vous avez offert, il est difficile d'écrire une solution complète, mais voici quelque chose qui utilise XML::Twig pour traiter les données XML que vous avez montré et afficher tous (un path les éléments qui n'ont pas un attribut kind égal à dir.

XML::LibXML est également un module de très haute qualité sur la base du C-code libxml2

use strict; 
use warnings; 

use XML::Twig; 

my $parser = XML::Twig->new(
    twig_handlers => { 
    path => \&path_handler, 
    } 
); 

$parser->parse(*DATA); 

sub path_handler { 
    my ($twig, $path) = @_; 
    return if $path->att('kind') eq 'dir'; 
    print $path->text, "\n"; 
} 


__DATA__ 
<?xml version="1.0" encoding="UTF-8"?> 
<log> 
    <logentry revision="3989"> 
     <author>cergyl</author> 
     <date>2013-07-19T05:31:01.212620Z</date> 
     <paths> 
      <path action="M" kind="dir">/team.admin/trunk/auth.conf</path> 
     </paths> 
     <path action="M" kind="file">/team.admin/trunk/file.cpp</path> 
     <msg>Whitespace change to verify repository synchronization</msg> 
    </logentry> 
</log> 

sortie

/team.admin/trunk/file.cpp 
0

Personnellement, j'aime XML :: DOM :: Parser de XML::DOM . Mais j'utilise XML :: Twig pour les imprimer.

my $xp = XML::DOM::Parser->new(); my $doc = $xp->parse("<xml></xml>"); $doc->dispose(); my $doc = $xp->parsefile("file.xml"); $doc->dispose(); // Pretty Print My poorly formatted xml doc my $xpp = XML::Twig->new(pretty_print => 'indented'); $xpp->parse("<xml></xml>"); $xpp->print();

Questions connexes