Table des matières

Encodage de textes en XML – TEI

Licence Creative Commons Le cours "Informatique pour les historiens" de Francesco Beretta, avec tous les documents, fichiers et scripts associés, est mis à disposition selon les termes de la licence Creative Commons Attribution - Pas d’Utilisation Commerciale - Partage dans les Mêmes Conditions 4.0 International.

Retour vers l'accueil

Exercice pour la prochaine séance

Exercice pour la séance du 3 novembre – à remettre au plus le vendredi 31 octobre

Logiciles à installer

Installer le navigateur Firefox

Activation de l'éditeur jEdit

Pour les instructions de mise en fonction de jEdit, voir ici

Principes du XML: la grammaire de l'encodage

Pour encoder nos textes et les annoter sémantiquement nous allons utiliser le format XML: Extensible Markup Language (“langage de balisage extensible”).
Pour en savoir plus sur ce format, voir ces tutoriels d'introduction à XML et en particulier l'introduction à XML par Victor Stinner, qui explique les concepts essentiels.

Dans le format XML, le texte est enveloppé par des balises qui en disent le sens:

<seg ana="ObPe36">
<name ref="ObPe6"/>Weil, aujourd'hui <name ref="ObPe22" type="place">Weil der Stadt, Wurtemberg</name>, 
<date when="1571-12-27">le vingt-septième jour du mois de décembre 1571</date>
</seg>

Une balises est un nom enveloppé par deux chevrons '<' '>'. Les balises sont ouvertes, puis fermées. La valeur du nom de chaque balise ('seg', 'name', 'date' dans l'exeple ci-dessus) ne fait pas partie de la grammaire XML mais des sémantique qu'on peut construire à partir de cette grammaire. Nous y reviendrons ci-dessous.

<name>Johannes Kepler</name>

La balise de fermeture possède un signe '/' après le premier chevron '<'. Les balises doivent former une arboréscence sans intersections: lorsqu'une balise qui en contient quelques autres est fermée, toutes les balises qu'elle contient doivent également avoir été fermées préalablement. C'est le cas des balises 'name' et 'date' de l'exemple ci-dessus, qui doivent être fermées avant la fermetur de la balise 'seg' qui les contient.
C'est donc FAUX d'écrire:

<seg>L'astronome <name>Johannes Kepler</seg></name>

C'est correct d'écrire:

<seg>L'astronome <name>Johannes Kepler</name></seg>

De plus le document doit posséder une et une seule balise racine qui contient toutes les autres balises.

A ces conditions le document est dit 'bien formé' (well formed) et peut être enregistré (vous pourrez l'enregistrer sous format texte même s'il n'es pas bien formé, mais la base de données personnelle refusera de l'enregistrer dan le champs texte_tei: postgreSQL vérifie que le document est 'bien formé' avant de l'enregistrer).

Les balises peuvent contenir des attributs (dans l'exemple il s'agit des attributs @ana, @ref et @type) qui ajoutent des précisions concernant la signification des balises et de leur contenu. Les attributs peuvent également contenir des valeurs même si les balises sont vides (cf., dans l'exemple, la première balise 'name'). Une balise vide est directement fermée par une barre oblique.

<name ref="ObPe6"/>

La TEI (Text encoding initiative): la sémantique de l'encodage

Le format XML comme tel ne fournit qu'une grammaire concernant le fonctionnement des balises et des attributs mais il ne définit pas les noms des balises ou des attributs, ni leur sens. La notion d'extensibilité propre au XML (eXtensible Markup Language) permet précisément de décider soi-même le nom qu'on donne aux balises et aux attributs. Chacun pourrait donc créer son propre système de balises. Toutefois, il serait difficile d'échanger les textes entre utilisateurs car on ne connaîtrait pas le sens des balises utilisée par les autres, ou alors il faudrait l'expliciter chaque fois. Différents standards ont donc été mis en place afin de faciliter l'échange et la compréhension du sens des encodages des textes, dont la Text encoding initiative (TEI) qui est largement utilisée pour l'édition numérique de textes, notamment en histoire. Cf. par ex. les formations proposées par l'Ecole des chartes à Paris ou le Centre d’Études Supérieures de la Renaissance (CESR) à Tours.

Dans le codage de nos textes (notes de lecture ou dépouillement d'archives, transcriptions de textes, etc.) nous utiliserons la sémantique de la Text encoding initiative, tout en choisissant une partie limitée de ses possibilités afin qu'elle soit adaptée à notre propos. La sémantique de la TEI est définite dans les Guidelines (la version en 'français' contient quelques traductions des définitions des balises).

Les Guidelines

Les Guidelines sont organisées par chapitres qui traitent différentes parties de l'encodage. Les Guidelines contiennent également une définition du sens et de l'utilisation de chaque balise, par exemple de la balise 'seg'. Si on remplace le nom de la balise dans l'URL par celui d'une autre balise, on peut facilement retrouver la définition de chaque balise (ou alors utiliser l'index des balises). On peut également accéder à une liste des exemples d'utilisation des balises tirés des Guidelines, par ex. l'élément 'seg'. Et, si souhaité, remplacer le nom de l'élément après le tiret avec le nom de l'élément pour lequel on cherche des exemples.

La structure d'un document

Dans la sémantique de la TEI, l'élément racine s'appelle 'TEI'. Il se trouve après les éventuels prologues (déclaration de version xml, déclaration de traitements, etc.) et il est fermé à la fin du document. De plus, il comporte un attribut (@xmlns) qui indique l'identifiant de l'espace de noms de la TEI (c'est-à-dire les noms des balises prévues et leur sens, cf. les explications fournies précédemment): xmlns=“http://www.tei-c.org/ns/1.0. Cette indication est indispensable non seulement pour identifier la sémantique de référence, mais encore pour le traitement informatisé des textes.


Un document TEI comprend en règle générale deux parties principales, enveloppées respectivement par l'élément teiHeader et par l'élément text. L'élément 'teiHeader' contient les métadonnées qui décrivent le texte: son titre, son auteur, sa source, le traitement dont il a été objet, etc. On trouvera des explications concernant les éléments du 'teiHeader' dans le document 'modele_commente.xml' se trouvant dans le dossier 'documents_exemple' du dossier téléchargé.


L'élément 'text' contient le texte lui-même et il est le principal objet de l'encodage. On convient de distinguer entre un codage structurel du texte, qui nous permet de restituer ou construire sa stucture (les parties, les paragraphes, les tableaux, etc.) et un codage sémantique, qui nous permet d'identifier des objets dans le texte (on parle d'entités nommées, c'est-à-dire de chaînes de caractères qui se référent à un objet) et de mettre en évidence les relations qui subsistent entre ces objets.

Un exemple de document

<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet href="transformation/visualisation_navigateur.xsl" type="text/xsl"?>
<TEI xmlns="http://www.tei-c.org/ns/1.0" xml:id="ObPe26">
	<teiHeader>
		<fileDesc>
			<titleStmt>
				<title>Nicolas Claude Fabri de Peiresc</title>
				<author/>
			</titleStmt>
			<publicationStmt>
				<p>Document à usage personnel</p>
			</publicationStmt>
			<sourceDesc>
				<bibl>Cet <ref target="http://www.larousse.fr/encyclopedie/litterature/Peiresc/175946">article</ref> est extrait de l'ouvrage Larousse « Dictionnaire mondial des littératures »</bibl>
			</sourceDesc>
		</fileDesc>
		<revisionDesc>
			<change type="synchronisation_base" when="2014-10-19">
				Mise-à-jour effectuée
			</change>
			<change type="production_texte" when="2014-10-02"/>
			<change type="structure" when="2014-10-03"/>
			<change type="semantique" when="2014-10-19">J'ai encodé toutes les entités nommées qui figurent dans ce texte</change>
		</revisionDesc>
	</teiHeader>
	<text>
		<body>
			<div type="structure">
				<p>Érudit et collectionneur français (<seg ana="ObPe36"><name ref="ObPe9"/>
						<name ref="ObPe39">Belgentier, Provence</name>, <date when="1580">1580</date>
					</seg> – Aix-en-Provence 1637). </p>
				<p>Ce conseiller au parlement d'Aix voyagea à travers l'Europe et se lia avec les grands collectionneurs et bibliothécaires de son temps.</p>
				<p>Secrétaire du garde des sceaux Guillaume du Vair en 1616, il devient un membre assidu de l'Académie des frères Dupuy (où il rencontre <name ref="ObPe8">Gassendi</name>, Guez de Balzac, Ducange).</p>
				<p>Témoin typique de la curiosité du xviie siècle, il réunit et observe les choses et les faits curieux dont on peut mesurer l'ampleur dans la correspondance qu'il a laissée. </p>
			</div>
		</body>
	</text>
</TEI>

Codage structurel

Comme le montrent les documents qui se trouvent dans le dossier 'documents_exemple', à l'intérieur de l'élément 'text' le texte principal est contenu par l'élément body. Un élément 'front' et un élément 'back' pourraient contenir un titre du livre ou la table des noms mais nous ne les utilisons pas pour une première approche.

A l'intérieur de l'élément 'body', le document est structuré en divisions et subdivisions grâce à l'élément div. Plusieurs éléments 'div' peuvent être imbriqués pour donner des niveaux de division successifs (par ex. chapitres et sous-chapitres d'un livre). Il n'est toutefois pas prévu, dans cette approche basique, d'imbriquer plus que trois niveaux. On aura donc au maximum la structure d'arboréscence:

body > div > div > div > p

Pour un texte avec un structure plus complexe, il est préférable de produire plusieurs documents en découpant le texte en plusieurs morceaux.

L'attribut @type des éléments 'div' prévoit quatre valeurs: 'structure' (utilisation des 'div' pour renseigner la structure du document); 'transcription' (l'élément 'div' contient un texte transcrit à partir d'une source, imprimée ou manuscrite); 'notes' (l'élément 'div' contient ses propres notes); 'redaction' (l'élément 'div' contient un texte rédigé par ses propres soins). De cette manière, on saura d'emblée quelle est la nature du texte que contient la division.

Si souhaité, on peut ajouter également un élément head qui contient le titre de la division. Il sera réutilisé dans l'export vers une page HTML de navigateur ou vers LibreOffice en tant que titre de la subdivision du texte.

A l'intérieur des éléments 'div' on utilise des éléments p pour structurer les paragraphes. Si les portions de texte ne correspondent pas vraiment à des paragraphes, il est préférable d'utiliser l'élément ab, plus générique. Ou alors on peut encoder des éléments table avec leur parties (colonnes et lignes, respectivement éléments 'row' et 'cell'), des figures, etc.

Codage sémantique

Pour le codage sémantique (qui nous permettra d'indexer les acteurs, les lieux, etc. dont parle le texte, ou d'indiquer quel est le sens de parties du texte), nous retendrons trois types d'éléments:


Pour des exemples, voir les textes qui se trouvent dans le dossier 'documents_exemple'.


Création d'un nouveau document

Une fois acquises les notions de base expliquées jusqu'ici, il s'agit maintenant de créer un nouveau document XML, selon la sémantique TEI, et d'encoder ses propres notes, transcriptions de documents, etc.

Pour ce faire, on peut procéder de deux manières:

  1. créer un nouveau document vide dans jEdit, avec le menu 'Fichier > Nouveau'
    • copier en entier le texte XML qui se trouve sur cette même page du wiki, ci-dessus, sous le titre 'Un exemple de document'
    • le coller dans le nouveau document
    • créer (ou avoir créé) dans la base de données un objet de type 'objet digital' qui sert de témoin à cet objet
    • utiliser la clé de l'objet créé dans la base de données (par ex. ObPe77) comme nom du nouveau document xml sous cette forme ObPe77.xml
    • enregistrer dans JEdit le noueau document ObPe77.xml dans le dossier 'mes_documents' du projet 'documents_tei'
    • remplacer le texte de l'exemple par son propre texte (partie 'text') et mettre à jour les dates des meta-données (partie 'teiHeader')
  2. ouvrir un document du dossier 'documents_exemple
    • dans le menu 'Fichier' choisir 'enregistrer une copie sous'
    • créer un objet dans la base de données : ObPe77
    • appeler la copie du document ObPe77.xml
    • l'enregistrer dans le dossier 'mes_documents' (donc: changer de dossier!)
    • remplacer le texte de l'exemple par son propre texte (partie 'text') et mettre à jour les dates des meta-données (partie 'teiHeader')

Visualisation des documents encodés

Le balisage ou encodage des documents en XML – TEI permet ensuite de les visualiser sous différentes formes et de les fouiller pour de retrouver facilement les passages des textes qui nous intéressent, ou d'en extraire des connaissances.

Visualisation des documents encodés

Mais avant tout, il s'agit de visualiser le document encodé de manière plus lisible. Un affichage de travail est disponible en ouvrant le document dans un navigateur web (testé avec Firefox et Internet Explorer): il suffit d'ouvrir le fichier depuis le navigateur, comme on ouvrirait n'importe quel document avec un traitement de texte, et un affichage 'ad hoc' apparaît.

Cet affichage est modulable à son gré en modifiant les feuilles de style XSLT et CSS qui se trouvent dans le dossier 'transformation' – ceci est toutefois facultatif et demande un savoir faire supplémentaire. La feuille de style de base permet de lire le texte et prendre connaissance du balisage sémantique effectué.

Importation dans LibreOffice

On peut aussi transformer le document XML-TEI en un document traitement de texte grâce aux filtres dont dispose LibreOffice. Pour ce faire, il faut télécharger le fichier des filtres (version actuelle 29 octobre 2014), le dézipper de manière à disposer d'un fichier se terminant par le suffixe .jar et l'installer dans LibreOffice. Pour ce faire, il faut:

Maintenant vous pouvez ouvrir vos fichiers XML-TEI dans LibreOffice:

Avec cette méthode on peut profiter du codage sémantique pour indexer le texte et en extraire des connaissances, puis transformer facilement le format XML pour l'importer dans un document de traitement de texte et l'utiliser pour des citations, etc., en faisant disparaître les balises XML.

ATTENTION: le filtre que vous venez d'installer est réduit aux fonctionnalités minimales; toutefois, il est paramétrable et adaptable en fonction de ce qu'on veut sortir: styles, italiques, index des noms, etc. Simplement il faut une certaine connaissance du XSLT pour ce faire. Si l'une ou l'autre de vous pense utiliser cette approche, je pourrai facilement adapter le filtre à ses besoins.

Interrogation des documents encodés

Extraction de typologies et de connaissances.

Importation dans la base de données PostgreSQL

Pour pouvoir fouiller les textes, il est nécessaire de les importer (par copier-coller) dans la base de données PostgreSQL. Nous prendrons l'exemple de la base de données de l'exercice: bd_td_exercice – par analogie on appliquera le même procédé à ses propres textes et à la base de données personnelle.

La procédure est très simple:

Le nouveau texte est ainsi enregistré dans la base de données.

Requêtes SQL /XPath

Une fois les textes XML-TEI enregistrés dans la base (dans le champs 'texte-tei' des objets correspondants aux textes, un objet par texte) on peut intérroger la base de données et extraire des informations des textes.

Pour ce faire, on utilise la langage SQL en le combinant avec le langage XPATH que PostgreSQL implémente également si le champs sur lequel porte la requête est de type 'XML'.

Pour apprendre la syntaxe des requêtes SQL, voir la manuel PostreSQL, chapitres 2 et 7. Nous y reviendrons. Pour apprendre celle du XPATH, un excellent tutoriel rédigé par Wieslaw Zielonka est disponible sur internet

Pour exécuter les requêtes ci-dessous:

Pour exporter le résultat:

Visualisation de toutes les portions de texte qui contiennent un attribut @ana

Cette requête a été stockée dans une vue. Une vue est un table virtuelle construite à partir d'une requête. On peut donc intérroger la vue comme s'il s'agissait d'une table.

Requête de base:

SELECT *
FROM vues_analyse.v_xml_balises_avec_ana

Compter les types de balises munies de l'attribut @ana:

SELECT COUNT(*),
       nom_balise
FROM vues_analyse.v_xml_balises_avec_ana
GROUP BY nom_balise

Compter les types de balises par acteur et type de texte:

SELECT   ???

Extraction de toutes les naissances

Un exemple de requête qui extrait des textes exemple toutes les connaissances concernant des naissances:

WITH TA1 AS
(
  SELECT ROW_NUMBER() OVER (ORDER BY 1)::INTEGER AS id,
         UNNEST(xpath ('//name/@ref | //date/@when',UNNEST(xpath ('//tei:seg[@ana="ObPe36"]',t1.texte_tei,ARRAY [ARRAY['tei','http://www.tei-c.org/ns/1.0']])),'{}'))::text AS cle,
         t1.pk_objet
  FROM objets.objet t1
),
TA2 AS
(
  SELECT TA1.cle,
         t2.nom,
         t2.type_objet,
         TA1.pk_objet,
         tA1.id
  FROM ta1
    LEFT JOIN vues_affichage.v_proprietes_standard_objet t2 ON t2.cle_objet = TA1.cle
  ORDER BY TA1.id,
           TA1.cle
)
SELECT t3.cle AS date_naissance,
       t1.cle,
       t1.nom,
       t2.cle cle_lieu,
       t2.nom nom_lieu,
       t4.longitude,
       t4.latitude
FROM TA2 AS t1
  LEFT JOIN TA2 AS t2
         ON t2.id = t1.id
        AND (t2.type_objet = 'Lieu'
         OR t2.type_objet = 'Immeuble')
  LEFT JOIN TA2 AS t3
         ON t3.id = t1.id
        AND t3.cle NOT LIKE 'ObPe%'
  LEFT JOIN objets.objet t4 ON 'ObPe' ||t4.pk_objet = t2.cle
WHERE t1.type_objet = 'Acteur'
ORDER BY date_naissance,
         nom

Exercice

Compléter les données des quatre personnages et ajouter les coordonnées géographiques, puis afficher sur une carte