Outils pour utilisateurs

Outils du site


td_histoire_numerique:descriptif_exercice_4

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

  • Indexer un ou plusieurs textes concernant votre sujet (vos notes, une transcription de sources, un article de dictionnaire, etc.) en XML - TEI, avec les clés des objets (= les identifiants préfixés par ObPe: ObPe1, ObPe2, etc.) et par thématique, selon le procédé indiqué ci-dessous et tout en s'inspirant des fichiers qui se trouvent dans dossier 'documents_exemple' du dossier téléchargé..
  • Stocker le ou les textes XML – TEI indexés dans votre base de données personnelle, dans le champs texte_tei d'un ou plusieurs objets de type 'Objet digital'
  • M'envoyer le ou les textes XML – TEI ainsi qu'une sauvegarde du schéma 'objets' de votre base personnelle

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:

  • les éléments qui identifient des entités nommées: name si la chaîne de caractères que contient la balise 'name' correspond à un nom; rs (referring string) si la chaîne de caractères se trouvant dans la balise 'rs' correspond à une référence, allusion, pronom qui se réfère à une entité nommée (un acteur, un lieu, etc.). L'attribut @ref contiendra la clé de l'objet tel qu'il est défini dans la base de données, en créant ainsi une correspondance entre celle-ci et les textes, et en permettant d'index aisément ces derniers.
  • avec l'élément seg on identifie une portion de texte dans laquelle on reconnaît un sens spécifique, qui correspond à une assertion ou à une unité de connaissance atomisée. L'attribut @ana permet de typer avec un objet abstrait la proposition que contient l'élément 'seg', en lien avec la définition qu'on donnera de l'objet abstrait dans la base de données.
    • ATTENTION: l'élément 'seg' doit se trouver toujours en dessous d'un élément 'p' ou 'ab', comme 'enfant' des précédents, c'est-à-dire enveloppé par eux. En d'autres termes, un élément 'seg' ne peut pas englober plusieurs 'p' ou plusieurs 'ab'.
  • si on a besoin de classer les paragraphes ou les divisions du texte avec une typologie sémantique, l'attribut @ana peut-être également utilisé au niveau des éléments 'p' ou 'div' pour indiquer le sens des textes qui se trouvent dans ces balises et les classer grâce à des objets abstraits définis dans la base de données (par ex. récit, analyse, etc.). La valeur de l'attibut @ana, qui peut être multiple (plusieurs valeurs séparées par un espace) sera la clé d'un objet abstrait défini dans la base de données, toujours munie de son préfixe (par ex. ObPe555)


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:

  • Dans LibreOffice, ouvrir un nouveau document texte vide
  • Dans le menu Outils, sélectionner 'Paramétrage du filtre XML'
  • Clicker sur le bouton “Ouvrir comme package…”
  • Chercher le fichier .jar que vous venez de télécharger et décompresser/dézipper et ouvrez-le (sous Windows 7 il faut l'ouvrir deux fois, c'est-à-dire déscende de deux niveaux)
  • Une fois ouvert, vous aurez le message: Installation du filtre “TEI_TD_Lyon3” terminée et vous verrez le filtre “TEI_TD_Lyon3” dans la liste des filtres
  • Fermez la boîte de dialogue “Paramétrage du filtre XML”

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

  • Ouvrir la boîte de dialogue “Ouvrir un fichier” (raccourci: Ctrl-O)
  • Cocher “EN LECTURE SEULE” ! Il est en effet INTERDIT d'enregitrer le fichier une fois ouvert dans LibreOffice directement en format XML – ce faisant, vour perdrez tous vos codages TEI
  • Sélectionnez le type de fichier à ouvrir: “TEI_TD_Lyon3” (menu à côté de 'Nom de fichier'), dans la liste vers la fin des types de Texte ODF
  • Choisissez un des documents encodés et ouvrez-le
  • Il sera en lecture seule: vous pouvez maintenant l'enregistrer dans un autre format (.odt, .doc, .docx, etc.) ou récupérer le texte par copier–coller et le mettre, par ex., dans votre mémoire de master

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:

  • créer dans la base de données un objet de type 'objet digital' qui correspond au texte encodé, qui le représente dans la base de données → cf. l'exemple ObPe77 mentionné ci-dessus
    • dans la base de données de l'exercice, il s'agit par ex. des objets ObPe24, ObPe40, etc.
  • ouvrir le document à importer sous jEdit, par ex. le document ObPe24.xml qui, comme son nom l'indique, correspond à l'objet ObPe24 de la base de données – dans l'exemple ci-dessous le document texte XML-TEI qui contient ses propres notes a été appelé ObPe77.xml
  • sélectionner le texte en entier et le copier
  • ouvrir la fiche de l'objet ObPe24 (ou l'objet ObPe77 pour son propre texte) dans la base de données, sélectionner tout le contenu du champs 'texte-tei', l'effacer
  • avec un click droit coller le texte issu de jEdit – puis enregistrer (avec le bouton ou en clicquant hors des champs)

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:

  • ouvrir la base de données 'bd_td_exercice' avec pgAdminIII, sélectionner le dossier rouge 'schémas' dans l'arboréscence, puis ouvrir la boît de dialoque 'SQL': bouton loupe.
  • copier la requête dans l'Editeur SQL
  • exécuter la requête avec le bouton vert en forme de flèche
  • le résultat s'affichera dans le panneau de sortie en bas

Pour exporter le résultat:

  • sous CSV = dans le menu 'Fichier' sélectionner 'Exporter…', choisir un nom de fichier et un emplacement (attention à mettre le suffixe .csv après le nom)
  • pour visualiser directement le résultat avec un navigateur, sélectionner dans le menu 'Fichier' la commande 'Rapport rapide', choisir de nouveau un fichier de sortie (tout en bas), ne rien toucher aux autres paramètres et appuyer sur OK
  • le résultat apparaîtra immédiatement dans votre navigateur web

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

td_histoire_numerique/descriptif_exercice_4.txt · Dernière modification: 2014/12/02 10:20 par Francesco Beretta