Forum Programmation.perl Ajouter une condition if

Posté par . Licence CC by-sa
Tags : aucun
-4
7
déc.
2015

salut a tous j'ai un code qui me menace ici et je comprend pas ce qui ce passe le code traite des fichiers xml et ecrit
les resultats dans un fichier csv auf fait j'aimerai ajouter une condition if dans le cas ou il travaille le reste de fichiers xml, trouve une variable attr_value dont la variable $attr_name correspondante n'existe pas qu'il ecrive 'missing'.
je ne sais pas si quelqu'un ici pourrai m'aider. je vous remerci d'avance.

#!/usr/local/bin/perl -w                         
use strict; 
use warnings; 
use XML::Twig;
use Text::CSV;
use POSIX qw(strftime);  
use autodie;   
use File::Basename;

my $file1 = shift @ARGV;       

my @files = glob( '../InputData/*.xml');     

@files = grep { $_ ne $file1 } @files if defined $file1;  

 $file1 = basename '..\InputData\DEFAULT\default_sysvalue.xml';


my $date_1 = strftime "%Y%m%d %H:%M:%S", localtime; 


my $FileResult = '../CSV/DATA.csv';
open( my $Fhhtml, '>', $FileResult );  


print $Fhhtml $date_1, "\n"; 

#a ce niveau le code traite le premier fichier et ecrit juste les noms des variables  $attr_name #dans le fichier de sortie

my $twig1= XML::Twig->new(    
        twig_handlers => {    

                'Par' => sub {  

                        my $attr_name = $_->{'att'}->{'name'};

                        print $Fhhtml $attr_name . ", ";    
                },
        },
);

print $Fhhtml( (split('_', $file1,2))[0] . ', ' );  

$twig1->parsefile($file1 = '..\InputData\DEFAULT\default_sysvalue.xml');   


#a ce niveau le code traite le reste des fichiers et ecrit juste les valeurs des variables  #$attr_value sous la colonne correspondante a $attr_name dans le cas ou la valeur ($attr_value) #n'existe pas il ecrit a ce niveau 'fault'. Maintenant j'aimerai en plus que dans le cas la #variable $attr_value existe et que la variable $attr_name n'existe pas qu'il ecrive 'missing'

for my $file (@files) { 

    my $twig1 = XML::Twig->new(

        twig_handlers => {

            'Par' => sub {

                my $attr_value = $_->{'att'}->{'value'} // 'fault';  

                print $Fhhtml $attr_value . ", ";
            },
        },
    );

    my $result = (split( '_', "\n$file", 2 ) )[0] . ', ';
    $result =~ s/..\/InputData\///g;
    print $Fhhtml($result);


    $twig1->parsefile($file);                  
}

close $Fhhtml;
  • # lien entre value et name ?

    Posté par (page perso) . Évalué à 2.

    Il y a un lien entre attr_value et attr_name du premier fichier et des suivants ? Ou les attr_name sont aussi définis pour les suivants, et c'est ceux-là dont tu veux l'existence ? Si c'est le cas, tu veux peut-être juste un

    unless (defined $_->{att}{name}) {
        $attr_value = "missing"
    }

    dans ta deuxième boucle après la ligne my $attr_value = ..., remplaçant $attr_value par « missing » s'il n'y a pas de name, en supposant que c'est dans ce fichier là, que tu veux qu'il existe.

    • [^] # Re: lien entre value et name ?

      Posté par . Évalué à -6.

      Salut anaseto et merci bien de ta proposition et je m'excuse je pense que je t'ai induit en erreur il faut pas m'en vouloir auf je vais essayer d'etre un plus plus clair avec des semblants de fichiers:

      le code traite le fichier de depart (src_sys.xml) et me renvoit les noms 'name'(attr_name) sur la pemiere ligne de mon fichier de sortie tout en splitant le nom du fichier de depart.(ceci dans le premier Twig)

      ensuite il va et traite les fichiers restant dans le second Twig. Pour ce fait il cherche les valeurs 'value' (attr_value) correspondant a chaque 'name':

      -Dans le cas ou il n'existe pas dans le fichier entrain d'etre traite il ecrit en desous du 'name' correspondant 'fault'.

      -Dans le cas ou un fichier-xml qui est entrain d'etre traite possede plus de 'name' que le fichier de depart (src_sys.xml) ignorer le 'name' et continue.

      -Dans le cas ou un fichier-xml qui est entrain d'etre traite possede moin de 'name' que le fichier de depart (src_sys.xml) ecrire en desous du 'name' correspondant 'missing'

      jusqu'ici mon code travaille un peu et mais j'ai du souci sur 2 points:

      -par moment quand 'value' n'existe pas au lieu d'ecire 'fault' comme mensionne dans le code il ecrit '0'

      -Et maintenant au niveau de 'missing' cela m'echappe aussi.

      je ne sais pas si quelqu'un ici pourrai me venir en aide. Merci bien d'avance.

      _________________src_sys______________
      <?xml version="1.0" encoding="UTF-8"?>
      <Profile origin="get" version="2.0" date="2013-07-021:49:13Z">
        <Par name="cost" value="0">
         <Target class="inter" inst="en0"/>
        </Par>
        <Par name="mic" value="0">
         <Target class="inter" inst="en1"/>
        </Par>
        <Par name="mor" value="0">
         <Target class="inter" inst="en2"/>
        </Par>
        <Par name="cost" value="0">
         <Target class="inter" inst="lo0"/>
        </Par>
        <Par name="actived" value="0">
         <Target class="inter" inst="en0"/>
        </Par>
        <Par name="edgd" value="0">
         <Target class="inter" inst="en1"/>
        </Par>
        <Par name="activ" value="0">
         <Target class="inter" inst="en2"/>
        </Par>
      </Profile>
      
      _________________ABO________________
      <?xml version="1.0" encoding="UTF-8"?>
      <Profile origin="get" version="2.0" date="2013-07-021:49:13Z">
        <Par name="cost" value="0">
         <Target class="inter" inst="en0"/>
        </Par>
        <Par name="mic">
         <Target class="inter" inst="en1"/>
        </Par>
        <Par name="mor" value="ce">
         <Target class="inter" inst="en2"/>
        </Par>
        <Par name="cost" value="A0">
         <Target class="inter" inst="lo0"/>
        </Par>
        <Par name="actived" value="10">
         <Target class="inter" inst="en0"/>
        </Par>
        <Par name="edgd" value="out">
         <Target class="inter" inst="en1"/>
        </Par>
        <Par name="activ">
         <Target class="inter" inst="en2"/>
        </Par>
      </Profile>
      
      __________________ABI_________________
      <?xml version="1.0" encoding="UTF-8"?>
      <Profile origin="get" version="2.0" date="2013-07-021:49:13Z">
        <Par name="cost" value="1">
         <Target class="inter" inst="en0"/>
        </Par>
        <Par name="mic" value="A">
         <Target class="inter" inst="en1"/>
        </Par>
        <Par name="mor" value="B">
         <Target class="inter" inst="en2"/>
        </Par>
        <Par name="cost" value="C">
         <Target class="inter" inst="lo0"/>
        </Par>
        <Par name="actived">
         <Target class="inter" inst="en0"/>
        </Par>
        <Par name="mac" value="E">
         <Target class="inter" inst="en1"/>
        </Par>
        <Par name="edgd" value="F">
         <Target class="inter" inst="en1"/>
        </Par>
        <Par name="activ" value="G">
         <Target class="inter" inst="en2"/>
        </Par>
      </Profile>
      
      _________________ABA_________________
      <?xml version="1.0" encoding="UTF-8"?>
      <Profile origin="get" version="2.0" date="2013-07-021:49:13Z">
        <Par name="cost" value="40">
         <Target class="inter" inst="en0"/>
        </Par>
        <Par name="mic" value="ae">
         <Target class="inter" inst="en1"/>
        </Par>
        <Par name="mor" value="0">
         <Target class="inter" inst="en2"/>
        </Par>
        <Par name="cost">
         <Target class="inter" inst="lo0"/>
        </Par>
        <Par name="actived" value="da">
         <Target class="inter" inst="en0"/>
        </Par>
        <Par name="activ" value="ka">
         <Target class="inter" inst="en2"/>
        </Par>
      </Profile>
      _____________________output__________________________
      src cost  mic    mor   cost   actived   edgd     activ
      ABO  0    fault  ce     A0      10      out      fault
      ABI  1    A      B      C      fault    F        G
      ABA  40   ae     0      fault   da      missing  ka
      • [^] # Re: lien entre value et name ?

        Posté par (page perso) . Évalué à 2.

        -Dans le cas ou un fichier-xml qui est entrain d'etre traite possede plus de 'name' que le fichier de depart (src_sys.xml) ignorer le 'name' et continue.

        Au moment de parser ton premier fichier, tu pourrais créer une table de hachage %names qui garde en mémoire quels noms sont apparus avec un $names{$attr_name} = 1, puis après dans ton deuxième handler tester avec un if ($names{$attr_name}) où tu récupères $attr_name pareil.

        -Dans le cas ou un fichier-xml qui est entrain d'etre traite possede moin de 'name' que le fichier de depart (src_sys.xml) ecrire en desous du 'name' correspondant 'missing'

        La c'est similaire : il faudrait que tu fasses une passe préliminaire sur chaque fichier qui répertorie les noms qui apparaissent en utilisant une table de hachage comme avant.

        Voilà, j'espère que ça t'aidera.

        • [^] # Re: lien entre value et name ?

          Posté par . Évalué à -7.

          Voici un morceau de mon code mais je ne comprend pas pourquoi a la derniere ligne il me revoi toujours l'erreur suivante la ligne 37 est la derniere de ce morceau de code.

          C:\Users\Desktop\probe>perl parser.pl default_sysvalue.xml *.xml
          Couldn't open ..\InputData\DEFAULT\default_sysvalue.xml:
          No such file or directory at parser.pl line 37.
           at parser.pl line 37.
          
          C:\Users\Desktop\probe>
          #!/usr/local/bin/perl
              use Modern::Perl;
              use autodie;
              use XML::Twig;
              use Data::Dumper;
              use File::Basename;
          
              # parametrage externe
              my $arg_file = shift @ARGV;
              my $sys_file = '..\InputData\DEFAULT\src_sys.xml';
              my @files = glob('..\InputData\*.xml');
              @files = grep { $_ ne $arg_file } @files if defined $arg_file;
              my $result_file = '..\CSV\DATA.csv';
          
              # On recupere le liste des noms d'attributs
              my @sys_names;
              my $sys_twig = XML::Twig->new( twig_handlers => { 'Parameter' => sub { push @sys_names, $_->{'att'}->{'name'}; }});
              $sys_twig->parsefile($sys_file); # a ce niveau est le probleme
          • [^] # Re: lien entre value et name ?

            Posté par (page perso) . Évalué à 2.

            $sys_twig->parsefile($sys_file); # a ce niveau est le probleme

            Non, le problème n'est pas là : il te dit qu'il ne trouve pas default_sysvalue.xml, alors que dans cette ligne tu ouvres src_sys.xhml (du moins, sur ton bout de code). D'ailleurs, la ligne 37 ne se situe pas là, je pense.

            De plus, au lieu d'utiliser un tableau @sys_names, tu devrais utiliser une table de hachage %sys_names (ou alors la créer après à partir du tableau), car c'est plus adapté pour tester l'existence d'une clé.

            • [^] # Re: lien entre value et name ?

              Posté par . Évalué à -6.

              salut si tu regarde plus haut j'ai deja deklare la variable

              my $sys_file = '..\InputData\DEFAULT\default_sysvalue.xml'

              c'est exactement ce que je ne comprend pas alors que j'ai deja bien declare la direcion ou

                      default_sysvalue.xml'
              

              se trouve

          • [^] # Re: lien entre value et name ?

            Posté par . Évalué à 2.

            peut-etre parce qu'il n'arrive deja pas à ouvrir ..\InputData\DEFAULT\default_sysvalue.xml

            C:\Users\Desktop\probe>perl parser.pl default_sysvalue.xml .xml
            **Couldn't open ..\InputData\DEFAULT\default_sysvalue.xml:
            *
            No such file or directory at parser.pl line 37.
            at parser.pl line 37.

            qui au vu de l'emplacement ou est executé le parser, devrait se trouver dans c:\Users\Desktop\InputData\DEFAULT\

            mais en meme temps, tu as passé le nom default_sysvalue.xml en ligne de commande, tel quel :

            perl parser.pl default_sysvalue.xml *.xml

            pourquoi faudrait-il aller le chercher dans ..\InputData\DEFAULT ?

            • [^] # Re: lien entre value et name ?

              Posté par . Évalué à -6.

              Neox peut etre tu as raison je vais essaye de voire cela sans relative pfade si ca fonctionne

              • [^] # Re: lien entre value et name ?

                Posté par . Évalué à 2.

                ben c'est facile, on l'a vu sur les precedents posts.

                3 possibilités :

                1. soit tu definis l'emplacement et les fichiers en dur dans le programme, pratique pour debugger, mais pas tres portable quand un autre utilisateur va vouloir utiliser ton script dans un autre dossier, avec un autre rangement
                2. soit tu ne definis aucun chemin et tu prends *.xml dans le dossier en cours
                3. soit tu recuperes le chemin en parametre de la ligne de commande pour aller prendre les xmls qui sont dans le dossier passé en parametre, cela pourra etre un chemin absolu c:\users\henri\desktop\data… ou un chemin relatif . ou ..\chemin\dossier\data\

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.