BAO3 - Script d'extraction de motifs avec XPath
  1. #/usr/bin/perl
  2. <<DOC;
  3. Nom : Rachid Belmouhoub
  4. Avril 2012
  5.  usage : perl bao3_rb_new.pl fichier_tag fichier_motif
  6. DOC
  7.  
  8. use strict;
  9. use utf8;
  10. use XML::XPath;
  11.  
  12. # Définition globale des encodage d'entrée et sortie du script à utf8
  13. binmode STDIN,  ':encoding(utf8)';
  14. binmode STDOUT, ':encoding(utf8)';
  15.  
  16. # On vérifie le nombre d'arguments de l'appel au script ($0 : le nom du script)
  17. if($#ARGV!=1){print "usage : perl $0 fichier_tag fichier_motif";exit;}
  18.  
  19. # Enregistrement des arguments de la ligne de commande dans les variables idoines
  20. my $tag_file= shift @ARGV;
  21. my $patterns_file = shift @ARGV;
  22.  
  23. # Ouverture du fichiers de motifs
  24. open(PATTERNSFILE, $patterns_file) or die "can't open $patterns_file: $!\n";
  25.  
  26. # lecture du fichier contenant les motifs, un motif par ligne (par exemple : NOM ADJ)
  27. while (my $ligne = <PATTERNSFILE>) {
  28.     # Appel à  la procédure d'extraction des motifs
  29.     &extract_pattern($ligne);
  30. }
  31.  
  32. # Fermeture du fichiers de motifs
  33. close(PATTERNSFILE);
  34.  
  35. # routine de construction des chemins XPath
  36. sub construit_XPath{
  37.     # On récupère la ligne du motif recherché
  38.     my $local_ligne=shift @_;
  39.    
  40.     # initialisation du chemin XPath
  41.     my $search_path="";
  42.    
  43.     # on supprime avec la fonction chomp un éventuel retour à la ligne
  44.     chomp($local_ligne);
  45.    
  46.     # on élimine un éveltuel retour chariot hérité de windows
  47.     $local_ligne=~ s/\r$//;
  48.    
  49.     # Construction au moyen de la fonction split d'un tableau dont chaque élément a pour valeur un élément du motif recherché
  50.     my @tokens=split(/ /,$local_ligne);
  51.    
  52.     # On commence ici la construction du chemin XPath
  53.     # Ce chemin correspond au premier noeud "element" de l'arbre XML qui répond au motif cherché
  54.     my $search_path="//element[contains(data[\@type=\"type\"],\"$tokens[0]\")]";
  55.    
  56.     # Initialisation du compteur pour la boucle de construction du chemin XPath
  57.     my $i=1;
  58.     while ($i < $#tokens) {
  59.         $search_path.="[following-sibling::element[1][contains(data[\@type=\"type\"],\"$tokens[$i]\")]";
  60.         $i++;
  61.     }
  62.     my $search_path_suffix="]";
  63.    
  64.     # on utilise l'opérateur x qui permet de répéter la chaine de caractère à sa gauche autant de fois que l'entier à sa droite,
  65.     # soit $i fois $search_path_suffix
  66.     $search_path_suffix=$search_path_suffix x $i;
  67.    
  68.     # le chemin XPath final
  69.     $search_path.="[following-sibling::element[1][contains(data[\@type=\"type\"],\"".$tokens[$#tokens]."\")]"
  70.                                 .$search_path_suffix;
  71.         # print  "$search_path\n";
  72.  
  73.     # on renvoie à la procédure appelante le chein XPath et le tableau des éléments du motif
  74.     return ($search_path,@tokens);
  75. }
  76.  
  77. # routine d'extraction du motif
  78. sub extract_pattern{
  79.     # On récupère la ligne du motif recherché
  80.     my $ext_pat_ligne= shift @_;
  81.  
  82.     # Appel de la fonction construit_XPath pour le motif lu à la ligne courrante du fichier de motif
  83.     my ($search_path,@tokens) = &construit_XPath($ext_pat_ligne);
  84.    
  85.     # définition du nom du fichier de résultats pour le motif en utilisant la fonction join
  86.     my $match_file = "res_extract-".join('_', @tokens).".txt";
  87.  
  88.     # Ouverture du fichiers de résultats encodé en UTF-8
  89.     open(MATCHFILE,">:encoding(UTF-8)", "$match_file") or die "can't open $match_file: $!\n";
  90.    
  91.     # création de l'objet XML::XPath pour explorer le fichier de sortie tree-tagger XML
  92.     my $xp = XML::XPath->new( filename => $tag_file ) or die "big trouble";
  93.    
  94.     # Parcours des noeuds du ficher XML correspondant au motif, au moyen de la méthode findnodes
  95.     # qui prend pour argument le chemin XPath construit précédement
  96.     # avec la fonction "construit_XPath"
  97.     foreach my $noeud ( $xp->findnodes($search_path)) {
  98.         # Initialisation du chemin XPath relatif du noeud "data" contenant
  99.         # la forme correspondant au premier élément du motif
  100.         # Ce chemin est relatif au premier noeud "element" du bloc retourné
  101.         # et pointe sur le troisième noeud "data" fils du noeud "element"
  102.         # en l'identifiant par la valeur "string" de son attribut "type"
  103.         my $form_xpath="";
  104.         $form_xpath="./data[\@type=\"string\"]";
  105.        
  106.         # Initialisation du compteur pour la boucle d'éxtraction des formes correspondants
  107.         # aux éléments suivants du motif
  108.         my $following=0;
  109.  
  110.         # Recherche du noeud data contenant la forme correspondant au premier élément du motif     
  111.         # au moyen de la fonction "find" qui prend pour arguments:
  112.         #           1. le chemin XPath relatif du noeud "data"
  113.         #           2. le noeud en cours de traitement dans cette boucle foreach
  114.         # la fonction "find" retourne par défaut une liste de noeuds, dans notre cas cette liste
  115.         # ne contient qu'un seul élément que nous récupérons avec la fonction "get_node"
  116.         # enfin nous en imprimons le contenu textuel au moyen de la méthode string_value
  117.         print MATCHFILE $xp->find($form_xpath,$noeud)->get_node(1)->string_value," ";
  118.        
  119.         # Boucle d'éxtraction des formes correspondants aux éléments suivants du motif
  120.         # On descend dans chaque noeud element du bloc
  121.         while ( $following < $#tokens) {
  122.             # Incrémentation du compteur $following de cette boucle d'éxtraction des formes
  123.             $following++;
  124.            
  125.             # Construction du chemin XPath relatif du noeud "data" contenant
  126.             # la forme correspondant à l'élément suivant du motif
  127.             # Notez bien l'utilisation du compteur $folowing tant dans la condition de la boucle ci-dessus
  128.             # que dans la construction du chemin relatif XPath
  129.             my $following_elmt="following-sibling::element[".$following."]";           
  130.             $form_xpath=$following_elmt."/data[\@type=\"string\"]";
  131.  
  132.             #   Impression du contenu textuel du noeud data contenant la forme correspondant à l'élément suivant du motif
  133.             print MATCHFILE $xp->find($form_xpath,$noeud)->get_node(1)->string_value," ";
  134.        
  135.             # Incrémentation du compteur $following de cette boucle d'éxtraction des formes
  136.             # $following++;
  137.         }
  138.         print MATCHFILE "\n";
  139.     }
  140.     # Fermeture du fichiers de motifs
  141.     close(MATCHFILE);
  142. }
  143.