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[data[\@type=\"type\"][contains(text(),\"$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.="[ancestor::element/following-sibling::element[1]/data[\@type=\"type\"][contains(text(),\"$tokens[$i]\")]";
  60.         $i++;
  61.     }
  62.     my $j=$i-1;
  63.     my $search_path_suffix="]";
  64.    
  65.     # 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,
  66.     # soit $i fois $search_path_suffix
  67.     $search_path_suffix=$search_path_suffix x $i;
  68.    
  69.     # le chemin XPath final
  70.     $search_path.="[ancestor::element/following-sibling::element[1]/data[\@type=\"type\"][contains(text(),\"".$tokens[$#tokens]."\")]]"
  71.                                 .$search_path_suffix;
  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 avec le chemin XPath construit précédement
  95.     # avec la fonction construit_XPath
  96.     foreach my $noeud ( $xp->findnodes($search_path)) {
  97.         # extraction impression de la forme correspondant au premier élément du motif
  98.         print MATCHFILE $noeud->getChildNode(3)->string_value," ";
  99.        
  100.         # Copie de la variable de la boucle $noeud dans une la variable de travail $noeud_suivant
  101.         # cette variable va subir les modification nécessaires pour le calcul, on ne peut évidement pas modifier la variable de boucle
  102.         my $noeud_suivant=$noeud;
  103.        
  104.         # Initialisation du compteur pour la boucle d'éxtraction des formes correspondants aux éléments suivants du motif
  105.         my $following=0;
  106.        
  107.         # Boucle d'éxtraction des formes correspondants aux éléments suivants du motif
  108.         # On descend graduellement au dernier noeud element
  109.         while ( $following < $#tokens) {
  110.             $following++;
  111.            
  112.             # construction du chemin XPath cible pour atteindre le noeud suivant
  113.             my $following_elmt="./following-sibling::element[".$following."]";
  114.            
  115.             # la méthode "find" retourne un objet dont on peut extraire une liste de noeuds au moyen de la méthode get_nodelist,
  116.             # bien que cette liste, vu notre chemin, ne contient qu'un seul noeud (voir element[1])
  117.             my @noeuds_suivants=$xp->find("./following-sibling::element[1]",$noeud_suivant)->get_nodelist();
  118.            
  119.             # récupération du noeud recherché
  120.             $noeud_suivant=shift(@noeuds_suivants);
  121.            
  122.             # impression de la forme correspondant à l'élément suivant du motif au moyen de la méthode string_value
  123.             print MATCHFILE $noeud_suivant->getChildNode(3)->string_value," ";
  124.         }
  125.         print MATCHFILE "\n";
  126.     }
  127.     # Fermeture du fichiers de motifs
  128.     close(MATCHFILE);
  129. }
  130.