#!/usr/bin/perl <<DOC; Format d'entree : Un texte étiqueté et lemmatisé par TreeTagger Un texte étiqueté et lemmatisé par Cordial Format de Sortie : les mêmes textes au format XML + une version regroupant les deux sorties alignées DOC # Usage # Attention, merci de bien vouloir vérifier que le fichier Cordial est au format Unix $ChaineUsage="Usage : tag2xml.pl <FichierTreetagger> <FichierCordial>\n"; if (@ARGV!=2) { die $ChaineUsage; } # Initialisation des variables my $sortiegenerale = ""; my $sortietreetagger = ""; my $sortiecordial = ""; my $fic = ""; my $fic2 = ""; # Lancement des procédures &ouvre; &formatecordial; &entete; &traitement; &fin; &ecriture; &ferme; &nettoyage; exit; ############################################################################################## # Récupération des arguments et ouverture des tampons sub ouvre { $FichierTreetagger=$ARGV[0]; open(EntreeTreetagger,"<:encoding(iso-8859-1)",$FichierTreetagger); $FichierCordial=$ARGV[1]; open(EntreeCordial,"<:encoding(iso-8859-1)",$FichierCordial); $FichierSortieTree="TreeTagger.xml"; open(SortieTree,">:encoding(iso-8859-1)",$FichierSortieTree); $FichierSortieCordial="Cordial.xml"; open(SortieCordial,">:encoding(iso-8859-1)",$FichierSortieCordial); $FichierSortie="General.xml"; open(Sortie,">:encoding(iso-8859-1)",$FichierSortie); } ############################################################################################## # Formatage du fichier cordial # But : on élimine les lignes non taggées (typiquement, des \r, des guillemets, ou des points) # + on rectifie les erreurs de ponctuation : les ":", "..." et ";" deviennent des PCTFORTE sub formatecordial { my @dump = (); while (my $ligne = <EntreeCordial>) { if ($ligne =~ /([^\t]*)\t([^\t]*)\t(.*)/) { if ($ligne =~ /(.*[;:].*)(PCTFORTE)(.*)/) { $ligne =~ s/(.*[;:].*)(PCTFORTE)(.*)/$1PCTFAIBLE$3/; print "remplacement\n$ligne"; push(@dump, $ligne); } elsif ($ligne =~ /(.*\.\.\..*)(PCTFORTE)(.*)/) { print "remplacement\n"; $ligne =~ s/(.*\.\.\..*)(PCTFORTE)(.*)/$1PCTFAIBLE$3/; print "$ligne"; push(@dump, $ligne); } else { push(@dump, $ligne); } } elsif ($ligne =~ /^(\.)\s*$/) { $ligne = ". . PCTFORTE"; push(@dump, $ligne); } else { print "ligne éliminée : $ligne"; } } close(EntreeCordial); open(EntreeCordial,">:encoding(iso-8859-1)",$FichierCordial); my $i = $#dump; my $j = 0; while ($j < $i) { print EntreeCordial $dump[$j]; $j++; } chomp($dump[$j]); print EntreeCordial $dump[$j]; close(EntreeCordial); open(EntreeCordial,"<:encoding(iso-8859-1)",$FichierCordial); } ############################################################################################## # Entête des documents XML sub entete { $sortiegenerale .= "<?xml version=\"1.0\" encoding=\"iso-8859-1\" standalone=\"no\"?>\n"; $sortiegenerale .= "<?xml-stylesheet type=\"text/xsl\" href=\"feuille-generale.xsl\"?>\n"; $sortiegenerale .= "<PARCOURS methode=\"TreeTagger + Cordial\">\n"; $sortietreetagger .= "<?xml version=\"1.0\" encoding=\"iso-8859-1\" standalone=\"no\"?>\n"; $sortietreetagger .= "<?xml-stylesheet type=\"text/xsl\" href=\"feuille-tt.xsl\"?>\n"; $sortietreetagger .= "<PARCOURS methode=\"TreeTagger\">\n"; $sortiecordial .= "<?xml version=\"1.0\" encoding=\"iso-8859-1\" standalone=\"no\"?>\n"; $sortiecordial .= "<?xml-stylesheet type=\"text/xsl\" href=\"feuille-cordial.xsl\"?>\n"; $sortiecordial .= "<PARCOURS methode=\"Cordial\">\n"; } ############################################################################################## # Lancement de la transformation en XML # Première étape : on lit les trois premières lignes du fichier TT et Cordial # (contenant le nom de la rubrique, le nom du premier fichier + l'indication d'un premier bloc) sub traitement { my $rubrique = ""; while ($LigneT = <EntreeTreetagger>) { if ($LigneT =~ /<(.+?)>.*$/) { $rubrique = $1; $sortiegenerale .= "<RUBRIQUE rub=\"$rubrique\">\n"; $sortietreetagger .= "<RUBRIQUE rub=\"$rubrique\">\n" and last; } } while ($LigneC = <EntreeCordial>) { if ($LigneC =~ /LIGNEDERUBRIQUE.*$/) { $sortiecordial .= "<RUBRIQUE rub=\"$rubrique\">\n" and last; } } while ($LigneT = <EntreeTreetagger>) { if ($LigneT =~ /<(.+?.xml)>.*$/) { $fic = $1; } if ($LigneT =~ /<BLOC>.*$/) { $sortietreetagger .= "<ETIQUETAGE fichier=\"$fic\">\n"; $sortietreetagger .= "<PHRASE>\n"; $sortiegenerale .= "<ETIQUETAGE fichier=\"$fic\">\n<PHRASE>\n<VERSION prog=\"TreeTagger\">\n" and last; } } while ($LigneC = <EntreeCordial>) { if ($LigneC =~ /BLOCDEPHRASE.*$/) { $sortiecordial .= "<ETIQUETAGE fichier=\"$fic\">\n"; $sortiecordial .= "<PHRASE>\n" and last; } } # Puis, on commence par traiter le fichier TT &traitementTreeTagger; } ############################################################################################## # Procédure de traitement du fichier de TreeTagger # Principe : on effectue un traitement sur ce fichier jusqu'à tomber sur une indication # de début de bloc de phrases (début d'un titre ou d'un résumé) => on passe à Cordial à ce moment-là # Il y a donc un aller-retour perpetuel entre Cordial et TT, ce qui permet d'aligner les deux versions # dans le fichier XML final (General.XML) sub traitementTreeTagger { # En cas d'indication de début de fichier if ($LigneT =~ /<(.+?.xml)>.*$/) { $fic = $1; $fic2 = $fic; $sortietreetagger .= "<ETIQUETAGE fichier=\"$fic\">\n"; $sortietreetagger .= "<PHRASE>\n"; $sortiegenerale .= "<ETIQUETAGE fichier=\"$fic\">\n<PHRASE>\n<VERSION prog=\"TreeTagger\">\n"; } # Boucle pour lire le fichier TT while ($LigneT = <EntreeTreetagger>) { # En cas d'indication de début de bloc, on passe à Cordial if ($LigneT =~ /<BLOC>.*$/) { if ($repere ne "true") { $sortietreetagger .= "\n</PHRASE>\n"; $repere = "true"; &traitementCordial and last; } else { next; } } # En cas d'indication de début de fichier elsif ($LigneT =~ /<(.+?.xml)>.*$/) { $balise = "true"; $fic = $1; $fic2 = $fic; } if ($LigneT!~/\ô\¯\:\\ô\¯\:\\/) { if ($repere eq "true") { # En cas d'indication de début de fichier if ($balise eq "true") { $sortietreetagger .= "</ETIQUETAGE>\n<ETIQUETAGE fichier=\"$fic\">\n"; $sortietreetagger .= "<PHRASE>\n"; $sortiegenerale .= "</PHRASE>\n</ETIQUETAGE>\n<ETIQUETAGE fichier=\"$fic\">\n<PHRASE>\n<VERSION prog=\"TreeTagger\">\n"; $repere = "false"; $balise = "false"; } # En cas de retour à TT après une fin de bloc dans le fichier Cordial elsif ($LigneT ne "") { $sortietreetagger .= "<PHRASE>\n"; $sortiegenerale .= "</PHRASE>\n<PHRASE>\n<VERSION prog=\"TreeTagger\">\n"; $LigneT=~s/([^\t]*)\t([^\t]*)\t(.*)/<element><data type=\"type\">$2<\/data><data type=\"lemma\">$3<\/data> <data type=\"string\">$1<\/data><\/element>/; $sortietreetagger .= $LigneT; $sortiegenerale .= $LigneT; $repere = "false"; } } # Sinon, pour une ligne taggée classique elsif ($balise ne "true") { # Remplacement des guillemets par <![CDATA["]]> (évite erreur d'interprétation XML) $LigneT=~s/\"/<![CDATA[\"]]>/g; $LigneT=~s/([^\t]*)\t([^\t]*)\t(.*)/<element><data type=\"type\">$2<\/data><data type=\"lemma\">$3<\/data> <data type=\"string\">$1<\/data><\/element>/; $sortiegenerale .= $LigneT; $sortietreetagger .= $LigneT; } else { next; } } } &traitementCordial; } ############################################################################################## # Procédure de traitement du fichier de Cordial sub traitementCordial { # En cas d'indication de début de bloc if ($LigneC =~ /BLOCDEPHRASE.*$/) { $sortiegenerale .= "</VERSION>\n<VERSION prog=\"Cordial\">\n"; } # En cas d'indication de début de fichier elsif ($LigneC =~ /DEBUTDEFICHIER.*$/) { $sortiecordial .= "<ETIQUETAGE fichier=\"$fic2\">\n"; $sortiecordial .= "<PHRASE>\n"; $sortiegenerale .= "</VERSION>\n<VERSION prog=\"Cordial\">\n"; } while ($LigneC = <EntreeCordial>) { # En cas d'indication de début de bloc, on passe à TT if ($LigneC =~ /BLOCDEPHRASE.*$/) { if ($repere2 ne "true") { chomp($LigneC); $sortiegenerale .= "\n</VERSION>\n"; $sortiecordial .= "\n</PHRASE>\n"; $repere2 = "true"; &traitementTreeTagger and last; } else { next; } } # En cas d'indication de début de fichier elsif ($LigneC =~ /DEBUTDEFICHIER.*$/) { $balise2 = "true"; } if ($LigneC!~/\ô\¯\:\\ô\¯\:\\/) { if ($repere2 eq "true") { # En cas d'indication de début de fichier if ($balise2 eq "true") { $sortiecordial .= "</ETIQUETAGE>\n<ETIQUETAGE fichier=\"$fic2\">\n"; $sortiecordial .= "<PHRASE>\n"; $repere2 = "false"; $balise2 = "false"; } elsif ($LigneC ne "") { # En cas de retour à Cordial après une fin de bloc dans le fichier TT $sortiecordial .= "<PHRASE>\n"; chomp($LigneC); $LigneC=~s/([^\t]*)\t([^\t]*)\t(.*)/<element><data type=\"type\">$3<\/data><data type=\"lemma\">$2<\/data> <data type=\"string\">$1<\/data><\/element>\n/; $sortiecordial .= $LigneC; $sortiegenerale .= $LigneC; $repere2 = "false"; } } # Sinon, pour une ligne taggée classique elsif ($balise2 ne "true") { # Remplacement des guillemets par <![CDATA["]]> (évite erreur d'interprétation XML) chomp($LigneC); $LigneC=~s/\"/<![CDATA[\"]]>/g; $LigneC=~s/([^\t]*)\t([^\t]*)\t(.*)/<element><data type=\"type\">$3<\/data><data type=\"lemma\">$2<\/data> <data type=\"string\">$1<\/data><\/element>\n/; $sortiegenerale .= $LigneC; $sortiecordial .= $LigneC; } else { next; } } } } ############################################################################################## # Fin de fichier sub fin { $sortiegenerale .= "</VERSION>\n</PHRASE>\n</ETIQUETAGE>\n</RUBRIQUE>\n</PARCOURS>\n"; $sortietreetagger .= "</PHRASE>\n</ETIQUETAGE>\n</RUBRIQUE>\n</PARCOURS>\n"; $sortiecordial .= "</PHRASE>\n</ETIQUETAGE>\n</RUBRIQUE>\n</PARCOURS>\n"; } ############################################################################################## # Ecriture des sorties sub ecriture { $sortiegenerale =~ s/\n\n/\n/g; $sortietreetagger =~ s/\n\n/\n/g; $sortiecordial =~ s/\n\n/\n/g; print Sortie $sortiegenerale; print SortieTree $sortietreetagger; print SortieCordial $sortiecordial; } ############################################################################################## # Fermeture des tampons sub ferme { close(EntreeTreetagger); close(EntreeCordial); close(Sortie); close(SortieTree); close(SortieCordial); } ############################################################################################## # Supprime les balises taggées des fichiers Cordial et TT (version texte) # Permet de repartir sur une base de fichiers "propres" pour l'extraction de patrons (BaO3) sub nettoyage { # Dialogue utilisateur print "Voulez-vous supprimer le reperage des parties des fichiers in ? (o/n)\n"; my $rep = <STDIN>; if ($rep =~ /n|N/) { print "Tant pis !\n"; } elsif ($rep =~ /o|O/) { open(TREE, "<:encoding(iso-8859-1)", "$FichierTreetagger") or die; my $out = ""; while (<TREE>) { if ($_ !~ /<(.+?)>.*$/) { $out .= $_; } } close(TREE); open(TREE, ">:encoding(iso-8859-1)", "$FichierTreetagger"); $out =~ s/\n\n/\n/g; print TREE $out; close(TREE); open(CORD, "<:encoding(iso-8859-1)", "$FichierCordial") or die; my $out = ""; while (<CORD>) { if ($_ !~ /(LIGNEDERUBRIQUE|DEBUTDEFICHIER|BLOCDEPHRASE).+$/) { $out .= $_; } } close(CORD); open(CORD, ">:encoding(iso-8859-1)", "$FichierCordial"); $out =~ s/\n\n/\n/g; print CORD $out; close(CORD); } else { print "Je n'ai pas compris, donc je ne fais rien du tout !\n"; } }