Boîte à Outil 3

Objectif: extraction de patrons morphosyntaxiques via un script perl, des feuilles de sytle XSLT et XQuery.

1/Script perl: L'extraction de patrons morphosyntaxiques à partir d'un fichier talismane (produit dans la BàO2) peut se faire grâce à un programme perl et un fichier texte contenant les patrons morphosyntaxiques à extraire. Ce fichier ressemble tout simplement à ça:


Voilà le programme perl que l'on a utilisé (programme principal), écrit en cours par M.Daube et M.Fleury :
Exported from Notepad++

#!/usr/bin/perl #Commande pour éxecuter le script: perl nom_programme.pl nom_fichier_talismane.txt termino.txt #perl extraction_pos.pl 3208-2018-talismane.txt termino.txt use utf8; use POSIX qw(strftime); binmode STDOUT,":utf8"; #permet d'afficher en utf-8 dans le terminal use Time::HiRes qw(gettimeofday tv_interval); my $timepg = [gettimeofday]; my $filetalismane=$ARGV[0]; my $filetermino=$ARGV[1]; my $datestring = strftime "%a %b %e %H:%M:%S %Y", localtime; print "DEBUT : $datestring \n"; open my $fileT,"<:encoding(UTF-8)",$filetalismane; open my $fileTer,"<:encoding(UTF-8)",$filetermino; my @TERMINO=<$fileTer>, close $fileTer; my %dicotmp=(); my %dicoPatron=(); my $nbTerme=0; my $nbMotInPhrase=0; while (my $ligne=<$fileT>) { #On passe si la ligne par un 1 suivit d'une tabulation et de ££ car c'est une ligne indiquant les débuts et fin des titres et descriptions #On passe aussi les lignes commençant par ## car ce sont des lignes indiquant les titres et descriptions #avec le chemin jusqu'au fil RSS nous renseignant sur la date et la catégorie next if (($ligne=~/^1\t££/) or ($ligne=~/^\#\#/) or ($ligne=~/^$/)); #On compte le nombre de mots de chaque phrase, c'est-à-dire tout mot précédé d'un chiffre #sauf le signe § if ($ligne!~/^\d+\t§/) { $ligne=~/^\d+\t(.+)$/; my $reste=$1; $nbMotInPhrase++; my $cle=$nbMotInPhrase; my @listereste=split(/\t/,$reste); $dicotmp{$cle}=\@listereste; } else { #------------------------ # extraction termino.... my $phrase=" "; my $longueur = scalar (keys %dicotmp); for (my $i=1;$i<=$longueur;$i++) { my $LISTE=$dicotmp{$i}; my @listedeferencee = @$LISTE; my $mot=$listedeferencee[0]; my $pos=$listedeferencee[2]; $phrase=$phrase.$mot."/".$pos." "; } foreach my $patron (@TERMINO) { my $patron2=$patron; chomp($patron2); $patron2=~s/([^ ]+)/\[\^ \]\+\/\\b$1/g; #(?=regexp) permet la recherche globale en contraignant le moteur d'expressions régulières à se comporter #de manière contrainte via une "assertion de regard en avant" au moment de la recherche. while ($phrase=~/(?=\s($patron2))/g) { my $terme=$1; $terme=~s/\/[^ ]+//g; $dicoPatron{$patron}->{$terme}++; $nbTerme++; } } %dicotmp=(); $nbMotInPhrase=0; } } close($fileT); open my $fileResu,">:encoding(UTF-8)","resultat_extraction.txt"; print $fileResu "$nbTerme éléments trouvés\n"; foreach my $patron (keys %dicoPatron) { print $fileResu "\nType de pattern: ".$patron." \n\n"; foreach my $terme (sort {$dicoPatron{$patron}->{$b} <=> $dicoPatron{$patron}->{$a} } keys %{$dicoPatron{$patron}}) { print $fileResu $dicoPatron{$patron}->{$terme}."\t".$terme."\n"; } } print $fileResu "\nScript execution time: " . tv_interval($timepg) . " seconds."; close($fileResu); $datestring = strftime "%a %b %e %H:%M:%S %Y", localtime; print "FIN : $datestring \n";
Télécharger le script

Il nous a aussi été fourni un programme alternatif pour réaliser la même tâche d'extraction de patrons morphosyntaxiques:

Exported from Notepad++
#!/usr/bin/perl <<DOC; Format d\'entree : un texte étiqueté et lemmatisé par Talismane + un fichier de patrons syntaxiques avec un patron par ligne (ex: DET NC ADJ) Format de sortie : un fichier avec pour chaque patron sa liste de termes triés par fréquence DOC use utf8; use Time::HiRes qw(gettimeofday tv_interval); my $timepg = [gettimeofday]; my $listePatron; open my $fileTer,"<:encoding(UTF-8)",$ARGV[1]; while (my $patron=<$fileTer>) { chomp($patron); push(@{$listePatron},[split(/ +/,$patron)]) } close($fileTer); my %dicoPatron=(); my $nbTerme=0; my @WORDS; my @POS; open my $fileT,"<:encoding(UTF-8)",$ARGV[0]; while (my $ligne=<$fileT>) { if (($ligne!~/^1\t££/) and ($ligne!~/^\#\#/) and ($ligne!~/^$/)){ my @TMPLIGNE=split(/\t/,$ligne); push(@WORDS,$TMPLIGNE[1]); push(@POS,$TMPLIGNE[3]); } } close($fileT); my $lg=0; while (my $pos=$POS[$lg]) { foreach my $patron (@{$listePatron}) { if ($pos eq $patron->[0] ) { my $indice=1; my $longueur=1; my $stop=1; while (($indice <= scalar @$patron) and ($stop == 1)) { if ($POS[$indice+$lg] eq $patron->[$indice]) { $longueur++; $indice++; } else { $stop=0; } } if ($longueur == scalar @$patron) { $dicoPatron{join(" ",@{$patron})}->{join(" ",@WORDS[$indice+$lg-scalar @$patron..$indice+$lg-1])}++; $nbTerme++; } } } $lg++; } open my $fileResu,">:encoding(UTF-8)","perlIsTheBigOneBis.txt"; print $fileResu "$nbTerme éléments trouvés\n"; foreach my $patron (keys %dicoPatron) { print $fileResu "\nType de pattern: ".$patron." \n\n"; foreach my $terme (sort {$dicoPatron{$patron}->{$b} <=> $dicoPatron{$patron}->{$a} } keys %{$dicoPatron{$patron}}) { print $fileResu $dicoPatron{$patron}->{$terme}."\t".$terme."\n"; } } print $fileResu "\nScript execution time: " . tv_interval($timepg) . " seconds."; close($fileResu); exit;
Télécharger le script

Voici un aperçu de l'extraction des patrons ci-dessus obtenu grâce à notre programme (programme principal) pour la rubrique À la une (3208) de 2018:

Voici le résultat obtenu pour l'extraction des patrons morphosyntaxiques mentionnés plus haut via notre programme perl pour la rubrique Sports (3242): Télécharger le résultat de l'extraction
Et voici le résultat pour la rubrique Sciences (3244): Télécharger le résultat de l'extraction

2/Feuille de style XSLT: On peut également extraire des patrons morphosyntaxiques grâce à des feuilles de style XSLT. Bien entendu, l'extraction via des feuilles de style XSLT ne peut se faire qu'à partir des sorties TreeTagger transformer au format XML dans la BàO2.
Le principe du XSLT est simple: on utilise des expressions XPath afin d'extraire le contenu des balises de notre fichier XML. Il faut donc connaître la stucture de notre document XML. Chaque balise <element> contient trois balise <data>. Dans la première se trouve la catégorie morphosyntaxique, dans la deuxième le lemme et dans la troisième se trouve le mot en tant que tel. Si les patrons qu'on souhaite extraire sont NOM-ADJ, on cible pour chaque balise <element> la balise <data> numéro une contenant la catégorie morphosyntaxique "NOM" et la balise <element> suivante dont la première balise <data> contient "ADJ". Si tel est le cas, on extrait le contenu de la troisième balise <data> qui contient le mot en tant que tel. Et on fait la même chose dans l'autre sens, si la première balise <data> contient "ADJ" et que la balise <data> de la balise <element> précédente contient "NOM" alors on extrait le contenu de la troisième balise <data>. Le principe est ensuite le même si on veut chercher d'autre patrons morphosyntaxiques.



Feuille de style XSLT pour l'extraction des patrons NOM-ADJ: Exported from Notepad++
<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text" encoding="utf-8"/> <xsl:template match="/"> <xsl:apply-templates select="//element"/> </xsl:template> <xsl:template match="element"> <xsl:choose> <xsl:when test="(./data[contains(text(),'NOM')]) and (following-sibling::element[1][./data[contains(text(),'ADJ')]])"> <xsl:value-of select="./data[3]"/><xsl:text> </xsl:text> </xsl:when> <xsl:when test="(./data[contains(text(),'ADJ')]) and (preceding-sibling::element[1][./data[contains(text(),'NOM')]])"> <xsl:value-of select="./data[3]"/><xsl:text> </xsl:text> </xsl:when> </xsl:choose> </xsl:template> </xsl:stylesheet>
Télécharger la feuille de style XSLT

Feuille de style XSLT pour l'extraction des patrons NOM-PRP-NOM:

Exported from Notepad++
<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output method="text" encoding="utf-8"/> <xsl:template match="/"> <xsl:apply-templates select=".//article"/> </xsl:template> <xsl:template match="article"> <xsl:for-each select="element"> <xsl:if test="(./data[1][contains(text(),'NOM')])"> <xsl:variable name="p1" select="./data[3]/text()"/> <xsl:if test="following-sibling::element[1][./data[1][contains(text(),'PRP')]]"> <xsl:variable name="p2" select="following-sibling::element[1]/data[3]/text()"/> <xsl:if test="following-sibling::element[2][./data[1][contains(text(),'NOM')]]"> <xsl:variable name="p3" select="following-sibling::element[2]/data[3]/text()"/> <xsl:value-of select="$p1"/><xsl:text> </xsl:text><xsl:value-of select="$p2"/><xsl:text> </xsl:text> <xsl:value-of select="$p3"/><xsl:text> </xsl:text> </xsl:if> </xsl:if> </xsl:if> </xsl:for-each> </xsl:template> </xsl:stylesheet>

Télécharger la feuille de style XSLT


Voici le résultat obtenu pour l'extraction des patrons morphosyntaxiques NOM-ADJ et NOM-PRP-NOM pour la rubrique Technologies (651865) (les rubriques Sports et Sciences étant mal formées): Télécharger le résultat de l'extraction(NOM-ADJ), Télécharger le résultat de l'extraction(NOM-PRP-NOM)
Et voici le résultat pour la rubrique Voyages (3546): Télécharger le résultat de l'extraction(NOM-ADJ), Télécharger le résultat de l'extraction(NOM-PRP-NOM)


On aimerait aussi utiliser des feuilles des styles afin d'extraire des patrons morphosyntaxiques à partir des sorties Talismane produites dans la BàO2 
et ça tombe bien puisqu'on a sous la main un programme permettant de transformer la sortie Talismane au format XML: talismane2xml-v2 (télécharger).
Le principe d'extraction des patrons morphosyntaxiques est le même que précedemment, seule la structure du balisage change vu que c'est Talismane.

Le résultat ressemble à ça:

Télécharger le fichier Talismane complet au format XML pour la rubrique Sports (3242): cliquez ici

Télécharger le fichier Talismane complet au format XML pour la rubrique Sciences (3244): cliquez ici


Feuille de style XSLT pour extraire les patrons NC-P-NC du fichier Talismane complet au format XML:

Exported from Notepad++
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output method="text" encoding="utf-8"/> <xsl:template match="/"> <xsl:apply-templates select="//p"/> </xsl:template> <xsl:template match="p"> <xsl:for-each select="item"> <xsl:if test="(./a[4][text()='NC'])"> <xsl:comment>Patrons morphosyntaxique à extraire: NC-P-NC</xsl:comment> <xsl:variable name="p1" select="./a[2]/text()"/> <xsl:if test="following-sibling::item[1][./a[4][text()='P']]"> <xsl:variable name="p2" select="following-sibling::item[1]/a[2]/text()"/> <xsl:if test="following-sibling::item[2][./a[4][text()='NC']]"> <xsl:variable name="p3" select="following-sibling::item[2]/a[2]/text()"/> <xsl:text>&#xA;</xsl:text> <xsl:value-of select="$p1"/> <xsl:text> </xsl:text> <xsl:value-of select="$p2"/> <xsl:text> </xsl:text> <xsl:value-of select="$p3"/> <xsl:text> </xsl:text> </xsl:if> </xsl:if> </xsl:if> </xsl:for-each> </xsl:template> </xsl:stylesheet>

Télécharger la feuille de style XSLT



Feuille de style XSLT pour extraire les patrons DET-ADV-ADJ-NC du fichier Talismane complet au format XML:

Exported from Notepad++
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output method="text" encoding="UTF-8"/> <xsl:template match="/"> <xsl:apply-templates select="//p"/> </xsl:template> <xsl:template match="p"> <xsl:for-each select="item"> <xsl:comment>Patrons morphosyntaxique à extraire: DET-ADV-ADJ-NC</xsl:comment> <xsl:if test="(./a[4][text()='DET'])"> <xsl:variable name="p1" select="./a[2]/text()"/> <xsl:if test="following-sibling::item[1][./a[4][text()='ADV']]"> <xsl:variable name="p2" select="following-sibling::item[1]/a[2]/text()"/> <xsl:if test="following-sibling::item[2][./a[4][text()='ADJ']]"> <xsl:variable name="p3" select="following-sibling::item[2]/a[2]/text()"/> <xsl:if test="following-sibling::item[3][./a[4][text()='NC']]"> <xsl:variable name="p4" select="following-sibling::item[3]/a[2]/text()"/> <xsl:text>&#xA;</xsl:text> <xsl:value-of select="$p1"/> <xsl:text> </xsl:text> <xsl:value-of select="$p2"/> <xsl:text> </xsl:text> <xsl:value-of select="$p3"/> <xsl:text> </xsl:text> <xsl:value-of select="$p4"/> <xsl:text> </xsl:text> </xsl:if> </xsl:if> </xsl:if> </xsl:if> </xsl:for-each> </xsl:template> </xsl:stylesheet>

Télécharger la feuille de style XSLT



Feuille de style XSLT pour extraire les patrons DET-NC-P-NPP-PONCT du fichier Talismane complet au format XML:

Exported from Notepad++
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output method="text" encoding="UTF-8"/> <xsl:template match="/"> <xsl:apply-templates select="//p"/> </xsl:template> <xsl:template match="p"> <xsl:for-each select="item"> <xsl:comment>Patrons morphosyntaxique à extraire: DET-NC-P-NPP-PONCT</xsl:comment> <xsl:if test="(./a[4][text()='P'])"> <xsl:variable name="p1" select="./a[2]/text()"/> <xsl:if test="following-sibling::item[1][./a[4][text()='DET']]"> <xsl:variable name="p2" select="following-sibling::item[1]/a[2]/text()"/> <xsl:if test="following-sibling::item[2][./a[4][text()='NC']]"> <xsl:variable name="p3" select="following-sibling::item[2]/a[2]/text()"/> <xsl:if test="following-sibling::item[3][./a[4][text()='P']]"> <xsl:variable name="p4" select="following-sibling::item[3]/a[2]/text()"/> <xsl:if test="following-sibling::item[4][./a[4][text()='NPP']]"> <xsl:variable name="p5" select="following-sibling::item[4]/a[2]/text()"/> <xsl:if test="following-sibling::item[5][./a[4][text()='PONCT']]"> <xsl:variable name="p6" select="following-sibling::item[5]/a[2]/text()"/> <xsl:text>&#xA;</xsl:text> <xsl:value-of select="$p1"/> <xsl:text> </xsl:text> <xsl:value-of select="$p2"/> <xsl:text> </xsl:text> <xsl:value-of select="$p3"/> <xsl:text> </xsl:text> <xsl:value-of select="$p4"/> <xsl:text> </xsl:text> <xsl:value-of select="$p5"/> <xsl:text> </xsl:text> <xsl:value-of select="$p6"/> <xsl:text> </xsl:text> </xsl:if> </xsl:if> </xsl:if> </xsl:if> </xsl:if> </xsl:if> </xsl:for-each> </xsl:template> </xsl:stylesheet>

Télécharger la feuille de style XSLT


Voici le résultat de l'extraction pour les patrons NC-P-NC du fichier Talismane complet au format XML pour la rubrique Sports (3242): Télécharger le résultat de l'extraction Patrons DET-ADV-ADJ-NC: Télécharger le résultat de l'extraction Patrons DET-NC-P-NPP-PONCT: Télécharger le résultat de l'extraction


Et voici le résultat de l'extraction pour les patrons NC-P-NC du fichier Talismane complet au format XML pour la rubrique Sciences (3244):				
Télécharger le résultat de l'extraction
				
Patrons DET-ADV-ADJ-NC: Télécharger le résultat de l'extraction
				
Patrons DET-NC-P-NPP-PONCT: Télécharger le résultat de l'extraction


3/XQuery: la troisième méthode d'extraction de patrons morphosyntaxiques est l'utilsation de requêtes XQuery.

XQuery est un langage permettant de traiter un document XML. Comme XSLT, il produit un document en sortie. Les instructions XQuery se placent au milieu d'une sorte de modèle XML contenant ce qu'on veut. L e traitement consiste à remplacer les instructions par ce qu'elles calculent.
Les différences avec XSLT sont dans la syntaxe, XQuery n'est pas du XML. D'autre part la norme XPath utilisée est la version 2.0 qui offren des possibilités supplémentaires.
XQuery permet d'exprimer des requêtes beaucoup plus complexes que XPath version 1.0. Il permet de faire des sortes de jointures. De fait, XQuery est aux bases de données XML ce que SQL est aux SGBD relationnels. XQuery utilise le principe de la requête FLWOR:
_for pour sélectionner une séquence de noeuds, chaque élément étant stocké dans la variable $var
_let pour lier une séquence à une variable (sans itération)
_where pour filtrer les noeuds (prédicats reliés par and/or)
_order by pour trier les noeuds (ascending, descending)
_return pour retourner un résutat par noeud (seule clause obligatoire)

On peut donc utiliser les requêtes XQuery afin d'extraire des patrons morphosyntaxiques à partir des sorties TreeTagger et Talismane préalablement transformer au format XML.


TREETAGGER: requête XQuery sur la rubrique Technologies (651865) afin d'extraire les patrons morphosyntaxiques NOM-ADJ
Télécharger la requête XQuery
Télécharger le résultat
Pareil pour la rubrique Voyages (3546)
Télécharger le résultat
Requête XQuery sur la rubrique Technologies (651865) afin d'extraire les patrons morphosyntaxiques NOM-PREP-NOM
Télécharger la requête XQuery
Télécharger le résultat
Pareil pour la rubrique Voyages (3546)
Télécharger le résultat

TALISMANE: requête XQuery sur la rubrique Sports (3242) afin d'extraire les patrons morphosyntaxiques NOM-PREP-NOM
Télécharger la requête XQuery
Télécharger le résultat
Pareil pour la rubrique Sciences (3244)
Télécharger le résultat
Requête XQuery sur la rubrique Sports (3242) permettant d'extraire simultanément les patrons "NOM-PREP-NOM", "VERBE-DET-NOM", " NOM-ADJ" et "ADJ-NOM"
Télécharger la requête XQuery
Télécharger le résultat
Pareil pour la rubrique Sciences (3244)
Télécharger le résultat