Signalement dans Calames du corpus sous licence nationale « Archives du Parlement britannique » : Pas à pas vers l’EAD (2/2)

Du point de vue des processus de traitement de métadonnées de l’Abes, le cas des Archives du Parlement britannique constitue un cas inédit. La bonne manière de l’aborder n’allait pas de soi : pourrait-on réutiliser les méthodes et outils habituels ? Devrait-on imaginer une autre manière de faire ? Paradoxalement, comment traiter ce cas d’espèce tout en tirant des enseignements génériques pour dompter d’autres « ovnis documentaires » ?

Quelle méthode ? Passer par RDF ou rester en XML ?

L’Abes a une longue expérience d’intégration des métadonnées fournies par des éditeurs ou diffuseurs, en MARC ou en XML. Pour traiter les métadonnées obtenues dans le cadre des programmes d’acquisition ISTEX, CollEx-Persée et du Plan de soutien à l’édition scientifique française, l’Abes a conçu et développé un workflow, dont la pièce maîtresse est une base RDF. Habituellement, les métadonnées sont récupérées en XML, converties en RDF, chargées dans une base RDF, enrichies puis redistribuées vers le Sudoc, Bacon ou scienceplus.abes.fr.

Dans le cas de l’achat de ces archives numérisées, il a été décidé de ne pas suivre la voie RDF, mais plutôt d’emprunter un nouveau chemin, où les manipulations sont entièrement en XML, pour les raisons suivantes :

  • le traitement n’a qu’une sortie : il s’agit d’un format XML, en l’occurrence EAD. Le RDF serait un modèle/format pivot adéquat s’il fallait générer différentes sorties.
  • le format EAD de sortie possède une structure foncièrement hiérarchique, qui se prête mieux à une représentation en XML qu’en RDF (dont la vocation est d’exprimer des graphes).
  • le format EAD peut contenir du « contenu mixte », ie un élément XML ayant pour enfants à la fois un autre élément XML et directement du texte : <a>blabla <b>hum</b> blabla</a>. Essayer de modéliser du contenu mixte en RDF serait peu, voire absolument pas, efficient. Notons cependant que, dans ce projet,  l’EAD produit ne contient finalement pas de contenu mixte.

XML à tous les étages

Il a donc été décidé de travailler dans un environnement purement XML : des données XML, un système de gestion de base de données nativement XML (BaseX), un langage de requête XML (XQuery). Ces requêtes XQuery ne sont pas seulement des requêtes qui extraient de l’information. Elles servent surtout à modifier les données, à supprimer (DELETE) et créer (INSERT) des éléments ou attributs XML. On parle de XQuery Update.

Comme indiqué plus haut, parmi nos sources de données, trois ne sont pas en XML. Pour importer les deux fichiers Excel dans BaseX, il a fallu passer une commande qui utilise son module CSV. Mais, on s’en doute, BaseX ne propose pas de module MARC. Dans ce cas, il a fallu passer par une étape préalable qui convertisse le MARC en MARCXML avant de l’importer de manière standard.

A ce stade, on se retrouve avec quatre bases XML différentes dans BaseX. L’essentiel du processus consiste à fusionner ces bases avant de générer le résultat de cette fusion en EAD. L’ensemble du processus prend la forme d’une suite d’environ trente opérations successives, chaque opération étant l’exécution d’une requête XQuery.

En toute rigueur, il s’agit moins de fusionner ces quatre sources que d’injecter des éléments extraits des trois autres sources dans la source principale, à savoir les notices MARCXML. Après cette injection, on ne s’intéresse plus qu’à nos notices MARCXML enrichies d’éléments étrangers . C’est aussi le moment de raffiner les données MARCXML elles-mêmes pour préparer la suite des opérations. Il peut s’agir par exemple de :

  • normaliser un identifiant :
declare namespace marc="http://www.loc.gov/MARC21/slim";

for $record in db:open('marcxml_full')//marc:record

let $id := $record/marc:controlfield[@tag='001']/replace(replace(text(),'hcpp',"),'-',")

return insert node <abes_id<{$id}>/abes_id>into$record
  • nettoyer une date :
    declare namespace marc="http://www.loc.gov/MARC21/slim";
    
    for $z490 in //marc:datafield[@tag="490"]
    
    let $date := replace(replace($z490/marc:subfield[@code="a"]/text(), '\[', ''), '\] ;', '')
    
    return insert node <abes_date<{$date}>/abes_date>into $z490

    Là encore, sans aucun scrupule, on « décore » le MARCXML d’éléments intrus, comme ce <abes_id> ou ce <abes_date>.

    D’une série de notices MARCXML trafiquées à un arbre EAD valide

    L’étape suivante consiste à générer un composant EAD <c> pour chaque notice MARCXML. On n’obtient pas encore un fichier EAD hiérarchique (des <c> dans des <c> dans des <c>.), mais une série d’environ 76 000 <c>, à plat. Il s’agit alors de regrouper les <c> selon l’architecture hiérarchique qui a été définie.

    Pour le plaisir des yeux, voici une requête XQuery qui regroupe tous les documents de la série « Bills and Acts » sous un chapeau commun (qu’on appelle provisoirement <level>) :

    for $c in (/marc/marc:record[record/Paper_Series='Bills and Acts']/c)
    
    let $dateraw := $c/did/unitdate/@normal
    
    order by $dateraw
    
    return
    
    insert node $c into /level[@type="root"]/level[@type="Archives du circuit legislatif"]/level[@type="Bills and Acts"]/vrac
    

    On obtient toujours une série de <c> à plat, triés par date. Il s’agit alors de les regrouper par période :

    for $level in //level
    
    for $c in ($level/vrac/c)
    
    let $dateraw := $c/did/unitdate/@normal
    
    let $date := substring($dateraw, 1, 4)
    
    return
    
    if ( number($date) >= 1801 and number($date)<= 1819 )
    
    then  ( insert node $c into $level/c[did/unittitle = "1801-1819"] )
    
    else if ( number($date) >= 1820 and number($date) <= 1839 )
    
    then  ( insert node $c into $level/c[did/unittitle = "1820-1839"] )
    
    else if ( number($date) >= 1840 and number($date) <= 1859 )
    
    then  ( insert node $c into $level/c[did/unittitle = "1840-1859"] )
    
    else if ( number($date) >= 1860 and number($date) <=1879 )
    
    then  ( insert node $c into $level/c[did/unittitle = "1860-1879"] )
    
    else if ( number($date) >= 1880 and number($date) <= 1900 )
    
    then  ( insert node $c into $level/c[did/unittitle = "1880-1900"] )
    
    else insert node attribute error {'yes'} into $c
    
    

    … puis de les regrouper par session :

    for $period in /level/level/level[@type="Bills and Acts"]/c
    
    let $sessions := distinct-values($period/c/did/unitdate/@normal)
    
    for $session in $sessions
    
    let $c := $period/c[did/unitdate/@normal=$session]
    
    return
    
    insert node
    
    <c level="recordgrp"><did><unitid>{concat('Session ',$session)}</unitid></did>{$c}</c>
    
    into $period
    

     

    Les bons outils font les bons ouvriers

    On pourra s’étonner du fait que ce processus nécessite une succession de dizaines d’opérations manuelles, et non l’exécution d’un programme qui enchaînerait lui-même des opérations. Qu’est-ce qui justifie cet artisanat ? L’explication tient au fait qu’il s’agit d’un chantier unique, ad hoc. Du « sur mesure ». Il n’y a donc guère de sens à automatiser une tâche qui ne sera exécutée entièrement qu’une fois. De plus, le fait de découper le chantier en petites tâches successives procure l’agilité nécessaire. Devant un chantier inédit, rempli d’inconnues, les tâtonnements sont inévitables.

    Par ailleurs, ce découpage facilitera le transfert de compétences : si l’ensemble du processus ne sera jamais rejoué pour un autre corpus, les requêtes individuelles utilisées resserviront sans aucun doute. L’équipe Calames pourra puiser dans cette bibliothèque de requêtes pour de prochains chantiers, et l’enrichir.

    Ce grand chantier a également permis d’approfondir la maîtrise du logiciel BaseX, qui promet de rendre de grands services à l’équipe Calames – ainsi qu’à d’autres, à l’Abes et sans doute ailleurs. Il n’est pas exagéré de dire qu’il s’agit d’un logiciel exceptionnel, par sa robustesse, sa très grande usabilité, son respect des standards et la richesse de ses commandes propriétaires qui étendent ces standards pour faciliter la vie de l’utilisateur et réaliser des opérations lourdes sur des données volumineuses. Sa documentation est par ailleurs excellente et sa communauté vivante et réactive. Avec un tel outil, installé sur son poste ou sur un serveur, l’expert données bénéficie d’une très grande autonomie, dans un cadre rassurant (par exemple, il est facile de faire une sauvegarde de la base puis de la restaurer), ce qui l’encourage à engager des chantiers ambitieux.

    Il faut reconnaître que le traitement de ce type de corpus atypiques mobilise beaucoup de jours/hommes, autant voire plus que certains corpus plus classiques et moins spécialisés, comme la plupart des corpus acquis dans le cadre du GIS CollEx-Persée. Ce constat est assez caractéristique de certains achats de niche qui font la spécificité du GIS. Mais, outre l’intérêt scientifique de tels corpus et l’importance qu’ils revêtent pour certaines communautés de chercheurs, les méthodes et outils employés à cette occasion sont des acquis qui aideront les équipes de l’Abes à améliorer les données et enrichir les services du réseau Calames.

    Yann Nicolas, responsable du Labo de l’Abes

Cette publication a un commentaire

Laisser un commentaire

Aller au contenu principal