Version HTML du script tag2xml.pl

Pour télécharger le script : cliquez ici

#!/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"; }
}