Archives par étiquette : Web sémantique

Sémantiser une base de données relationnelle (3ème épisode)

Ce billet est le troisième épisode d’une série de billets sur la sémantisation d’une base de données relationnelle des auteurs de langue bretonne issue du projet PRELIB.

Je posterai dorénavant la dernière version de la totalité des triplets RDF sur mon compte personnel sur le site de partage de code informatique GitHub Gist. Je commençai en effet à être un peu perdu avec mes petits bout de triplets dispersés d’un billet à l’autre. Pour l’instant, les triplets déclarés avec le vocabulaire BIO et le vocabulaire FRBRoo sont dans des fichiers prelib.ttl séparés, mais cela n’exclut pas par la suite l’utilisation combinée des deux vocabulaires.

Dans les fichiers prelib.ttl publiés sur GitHub Gist des codes de langue (language tags) ont été rajoutés sur tous les littéraux en se servant du formulaire de recherche de la page de l’ISO 639-6 sur geolang.org (champ de recherche Language Reference Name).

Saisie du décès de Théodore et de ses années collège avec BIO

Dans la version BIO de prelib.ttl, les triplets de la date et du lieu de décès de Théodore ont été rajoutés ainsi que ses études au collège des Jésuites de Keranna à Quimper entre 1825 et 1826.

BIO permet de déclarer des bio:Interval (les années d’études de Théodore au collège des Jésuites de Keranna correspondent à la ressource http://prelib.huma-num.fr/interval/1) bornées par des bio:Event (les ressources http://prelib.huma-num.fr/event/3 et http://prelib.huma-num.fr/event/4 correspondant à sont entrée en 1825 et à sa sortie en 1826 du collège). Les informations spatio-temporelles sont rattachées aux bio:Event.

Si une autre personne rentre au même moment au collège des jésuites de Keranna, faut-il créer une nouvelle ressource de type bio:Enrolment ou rattacher la personne au même événement ? Vous ne trouverez pas la réponse dans la documentation du vocabulaire BIO mais dans le schéma du vocabulaire1 où il est indiqué que la propriété bio:principal liant la personne à l’événement a une cardinalité de 1 pour les ressources de type bio:IndividualEvent (dont bio:Enrolment est une sous-classe). En d’autres termes, il ne peut y avoir qu’une seule personne liée par la propriété bio:principal à un événement de type bio:Enrolment. Il faut donc bien créer autant d’événements de type bio:Enrolment que de personnes qui seraient rentrées au collège des Jésuites de Quimperlé la même année que Théodore.

Le collège des Jésuites correspond à la ressource http://prelib.huma-num.fr/organization/1 de type foaf:Organization où le nom de l’établissement a été saisi avec dc:title et foaf:name. Mais cette saisie ne permet pas de tenir compte des éventuels changement de nom ni de statut de l’établissement ni de ses divers lieux d’enseignement. Comment modéliser par exemple l’histoire mouvementée des Écoles normales supérieures ? L’École normale supérieure de l’enseignement primaire de Fontenay-aux-Roses créée par Jules Ferry en 1880 et École normale supérieure de Fontenay-Saint-Cloud doivent-elle être représentées par la même ressource ou par des ressources différentes mais liées entre elles (de quelle manière) ?

Petite remarque en aparté : L’idée sous-jacente à la saisie des études est de savoir si des personnes ont fréquenté les mêmes lieux de sociabilité. Mais une proximité spatio-temporelle n’est pas suffisante pour attester d’une relation. Dans le cas d’études, des documents tels qu’une thèse ou des devoirs en groupe seraient des preuves plus tangibles d’une relation (de professeur à étudiant ou entre étudiants).

Les multiples implémentations de FRBR pour le web sémantique

Plus j’explore l’utilisation de FRBR pour la base de donnée, plus je m’aperçois qu’il en existe de multiples implémentations en RDFS ou dans les différentes versions de OWL2. Voici celles que j’ai trouvées jusqu’à présent :

Implémentations de FRBRER (entité-relation)

– La version de l’IFLA : http://iflastandards.info/ns/fr/frbr/frbrer/
– La version RDFS de Ian Davis (auteur également du vocabulaire BIO) : http://purl.org/vocab/frbr/core et http://purl.org/vocab/frbr/extended
– La version OWL 2 DL de Paolo Ciccarese et Silvio Peroni3 qui fait référence à la version de Ian Davis : http://purl.org/spar/frbr

Implémentations de FRBRoo (orienté objet, version dérivée de CIDOC-CRM)

– La version RDFS de la dernière version de FRBRoo (version 2.1 du modèle) édité par le groupe de travail du groupe de travail CRM-FRBR : voir en haut de la page http://www.cidoc-crm.org/frbr_drafts.html
– La version de l’IFLA : http://iflastandards.info/ns/fr/frbr/frbroo/
– La version OWL DL de l’Université d’Erlangen (version 1.0.2 du modèle) : http://erlangen-crm.org/efrbroo

Sur la page Vocabulaires du web sémantique sur le site de la BnF on trouve également un lien vers la page The FRBR Vocabularies de l’IFLA. Pas facile de s’y retrouver dans tout ça…

  1. Je mets en lien la version du schéma publié par Ian Davis sur GitHub pour faciliter sa lecture. []
  2. Pour tenter d’y voir clair dans les différentes versions de OWL, lire Difference between OWL Lite, DL, and Full. []
  3. Silvio Peroni a également développé le web service LODE permettant de créer une documentation web d’une ontologie OWL. []

Sémantiser une base de données relationnelle (2ème épisode)

Ce billet est le deuxième épisode d’une série de billets sur la sémantisation d’une base de données relationnelle des auteurs de langue bretonne issue du projet PRELIB.

Corrections et améliorations

Depuis le dernier billet, Patrick Le Boeuf de la BnF m’a apporté quelques précisions sur le modèle CIDOC-CRM et Gabriel Kepeklian d’Atos m’a aidé à connecter une copie locale de ma base de données à DataLift1. Je vous conseille à ce propos la lecture de How to import an SQL database? Si vous avez des difficultés pour utiliser DataLift ou si vous voulez signaler votre utilisation de l’outil, n’hésitez pas à le faire sur la liste de diffusion du projet DataLift. J’ai également réalisé en discutant avec mon collègue Fañch Postic qui connait très bien Théodore, que je n’avais pas très bien interprété l’écriture manuscrite de l’acte de naissance de ce dernier puisque le nom de famille de la mère de Théodore Hersart de la Villemarqué est Feydeau et non pas Kerjean, plus précisément Feydeau de Vaugien2.

Pour revenir aux exemples précédents de triplets en Turtle, j’ai un doute sur la validité des URI des classes et des propriétés du CIDOC CRM. J’avais supposé que l’URI de P96 by mother par exemple, était http://www.cidoc-crm.org/cidoc-crm/by_mother mais il s’avère que c’est plutôt http://www.cidoc-crm.org/cidoc-crm/P96_by_mother. Je modifie les triplets de l’accouchement http://prelib.huma-num.fr/event/1 en conséquence. J’en profite également pour corriger les URI préfixées. En effet, les URI prelib:event/1 ou prelib:person/1115 ne sont pas valides : Le / n’est pas reconnu après les préfixes. J’ai donc remplacé le préfixe prelib: par les préfixes event: et person:

@prefix person: <http://prelib.huma-num.fr/person/> .
@prefix event: <http://prelib.huma-num.fr/event/> .
@prefix cidoc: <http://www.cidoc-crm.org/cidoc-crm/> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix dc: <http://purl.org/dc/terms/> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .

event:1 a cidoc:E67_Birth ;
cidoc:P98_brought_into_life person:80 ;
cidoc:P96_by_mother person:1115 ;
cidoc:P97_from_father person:1114 ;
cidoc:P1_is_identified_by _:date1 .

_:date1 a cidoc:E50_Date ;
rdfs:label “1815-07-07″^^xsd:date .

J’ai rajouté un triplet concernant le père de Théodore, Pierre Hersart de la Villemarqué (person:1114) car j’avais mal interprété l’utilisation de P97 from father. Comme me l’a expliqué Patrick Le Boeuf, cette propriété sert à désigner le père biologique et peut être utilisée même si celui-ci n’a pas assisté à l’accouchement.

Saisie du lieu de naissance

Modélisation des informations sur une personne aec le modèle CIDOC CRM. Source : http://www.cidoc-crm.org/cidoc_graphical_representation_v_5_1/person_nationality.html.

Modélisation des informations sur une personne aec le modèle CIDOC CRM. Source : http://www.cidoc-crm.org/cidoc_graphical_representation_v_5_1/person_nationality.html.

Comment saisir le lieu de naissance, c’est à dire la ville de Quimperlé ? D’après le schéma publié sur le site du CIDOC CRM et reproduit ci-dessus, il faut créer une ressource E53 Place que l’on lie à l’accouchement par la propriété P7 took place at. On crée donc une nouvelle ressource http://prelib.huma-num.fr/place/1 et on déclare à cette URI les triplets suivants :

@prefix place: <http://prelib.huma-num.fr/place/> .
@prefix cidoc: <http://www.cidoc-crm.org/cidoc-crm/> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .

place:1 a cidoc:E53_Place ;
rdfs:label “Quimperlé″ .

Cependant, le CIDOC-CRM incite à saisir les dénominations dans des classes dédiées afin de relater leur évolution dans le temps (par exemple, Lutèce qui devient Paris). E48 Place Name, sous-classe de E44 Place Appellation, semble la mieux indiquée dans notre cas3. Je pourrai créer une nouvelle ressource http://prelib.huma-num.fr/appellation/1 de type E48 Place Name mais je ne sais pas si celle-ci sera utilisée pour un autre usage que l’appellation de http://prelib.huma-num.fr/place/1, je me contente donc pour l’instant d’une ressource anonyme (ou blank node en anglais).

@prefix place: <http://prelib.huma-num.fr/place/> .
 @prefix cidoc: <http://www.cidoc-crm.org/cidoc-crm/> .
 @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .

place:1 a cidoc:E53_Place ;
cidoc:E87_is_identified_by _place_name .

_place_name a cidoc:E48_Place_Name ;
rdfs:label “Quimperlé″ .

On peut maintenant compléter les triplets de l’accouchement avec une référence à Quimperlé :

@prefix person: <http://prelib.huma-num.fr/person/> .
@prefix event: <http://prelib.huma-num.fr/event/> .
@prefix place: <http://prelib.huma-num.fr/place/> .
@prefix cidoc: <http://www.cidoc-crm.org/cidoc-crm/> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix dc: <http://purl.org/dc/terms/> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .

event:1 a cidoc:E67_Birth ;
cidoc:P98_brought_into_life person:80 ;
cidoc:P96_by_mother person:1115 ;
cidoc:P97_from_father person:1114 ;
cidoc:P1_is_identified_by _:date1 ;
cidoc:P7_took_place_at place:1 .

_:date1 a cidoc:E50_Date ;
rdfs:label “1815-07-07″^^xsd:date .

Retour sur la date de l’accouchement

Je ne suis toujours pas convaincu de cette saisie de la date de l’accouchement. Or, on trouve l’information suivante dans le commentaire au début du fichier http://www.cidoc-crm.org/rdfs/cidoc_crm_v6.0-draft-2015January.rdfs :

8. CRM time extension 1.0 Encoded in RDFS
Since the Time Primitive of the CRM can not directly be implemented in RDF Triple Stores, we define in this extension of 4 properties replacing P81 and P82 adequately using xsd:dateTime.
Property P81 is dedicated for modeling the Time-Span’s maximum known temporal extent i.e. ongoing_throughout. Property P82 is for modeling the minimum outer bounds of events i.e. at_some_time_within. P81 has its time interval redefined by P81a and P81b. Similarly, we redefine P82 by P82a and P82b.

Visiblement, cette implémentation en RDFS par le FORTH-ICS4 a nécessité la création de quatre propriétés RDF P81a_end_of_the_begin, P81b_begin_of_the_end, P82a_begin_of_the_begin et P82b_end_of_the_end qui sont les seules propriétés permettant explicitement la saisie de dates au format ISO 6801 (elles ont toutes les quatre pour portée (range en anglais) http://www.w3.org/2001/XMLSchema#dateTime) .

A y regarder de prêt, il semblerait que toute information temporelle est de facto une durée dont il faut saisir la date de début et la date de fin. Cela vient du fait que les concepteurs du modèle considèrent que les données temporelles sont forcément floues (fuzzy en anglais)5 et qu’ils ont voulu introduire la possibilité d’utiliser l’algèbre des intervalles d’Allen pour déduire la chronologie d’événements6.

Cela dit, dire que Théodore est né le 7 juillet 1815 signifie qu’il est né entre le 7 juillet à 0 heure et le 7 juillet à minuit… Toute “date” est en soit une durée. Mais il faut tout de même avouer que cela complique un peu la saisie.

Expression des données avec le vocabulaire BIO

Comment les mêmes informations pourraient-elles être exprimées avec le vocabulaire BIO du développeur anglais Ian Davis suggéré par Gautier Poupeau ? A la fin de la documentation de BIO, Ian Davis a illustré le vocabulaire par des données biographiques sur le roi d’Angleterre Henry VIII exprimées en RDF dont voici un extrait :

@prefix bio: <http://purl.org/vocab/bio/0.1/> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .

_:henryviii
  a foaf:Person
  ; foaf:name "Henry VIII, King of England"
  ; bio:father _:henryvii
  ; bio:mother _:elizplantagenet
  ; bio:child _:child1, _:child2, _:child3, _:child4, _:child5, _:child6, _:child7, _:child8
  ; bio:birth _:birth
  ; bio:death _:death
  ; bio:event _:burial, _:accession, _:coronation, _:marriage1
            , _:marriage2, _:marriage3, _:marriage4, _:marriage5, _:marriage6
  .

_:henryvii
  a foaf:Person
  ; foaf:name "Henry VII Tudor, King of England"
  ; bio:child _:henryviii
  .

_:elizplantagenet
  a foaf:Person
  ; foaf:name "Elizabeth of York"
  ; bio:child _:henryviii
  .
  
_:birth
  a bio:Birth
  ; rdfs:label "The birth of Henry VIII to Henry VII and Elizabeth Plantagenet on 28 June 1491"
  ; bio:date "1491-06-28"
  ; bio:place <http://dbpedia.org/resource/Palace_of_Placentia>
  ; bio:parent _:henryvii, _:elizplantagenet
  ; bio:principal _:henryviii
  .

_:death
  a bio:Death
  ; rdfs:label "The death of Henry VIII on 28 January 1547"
  ; bio:date "1547-01-28"
  ; bio:place <http://dbpedia.org/resource/Palace_of_Whitehall>
  ; bio:principal _:henryviii
  .

Je me suis largement inspiré de cet exemple à la seule différence que j’ai évité l’utilisation de ressources anonymes.

Les triplets associés à Théodore pourraient devenir :

@prefix person: <http://prelib.huma-num.fr/person/> .
@prefix event: <http://prelib.huma-num.fr/event/> .
@prefix place: <http://prelib.huma-num.fr/place/> .
@prefix cidoc: <http://www.cidoc-crm.org/cidoc-crm/> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix dc: <http://purl.org/dc/terms/> .
@prefix bio: <http://purl.org/vocab/bio/0.1/> .

person:80 a cidoc:Person, foaf:Person ;
dc:title "Théodore-Claude-Henri Hersart de la Villemarqué (1815-1895)"@fr ;
foaf:name "Théodore-Claude-Henri Hersart de la Villemarqué"@fr ;
foaf:givenName "Théodore Claude Henri" ;
foaf:familyName "Hersart de la Villemarqué" ;
foaf:nickname "Barz Nizon", "Kervarker";
foaf:gender "male"@en, "homme"@fr ;
bio:birth  event:1 .

Et les triplets de l’accouchement deviennent :

@prefix person: <http://prelib.huma-num.fr/person/> .
@prefix event: <http://prelib.huma-num.fr/event/> .
@prefix place: <http://prelib.huma-num.fr/place/> .
@prefix cidoc: <http://www.cidoc-crm.org/cidoc-crm/> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix dc: <http://purl.org/dc/terms/> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix dbpedia: <http://dbpedia.org/resource/> .

event:1 a bio:Birth ;
rdfs:label "Naissance de Théodore-Claude-Henri Hersart de la Villemarqué le 7 juillet 1815 à Quimperlé"@fr ;
bio:date "1815-07-07"^^xsd:date ;
bio:place dbpedia:Quimperl%C3%A9 ; # Voir http://www.dbpedia.org/resource/Quimperl%C3%A9
bio:parent person:1115 , person:1114 ;
bio:principal person:1 .

On perd la distinction du père et de la mère du CIDOC CRM mais les informations sur la date et le lieu sont plus faciles à saisir. Notamment pour le lieu, il est possible de ne saisir non pas une valeur littérale mais l’URI d’une ressource qui permette de désambiguïser l’information et de récupérer des informations saisies par ailleurs7. Après, je ne dis pas que cela n’est pas possible avec le CIDOC CRM, je n’ai peut-être pas encore compris comment procéder. Toujours est-il que la propriété bio:place n’a pas de portée (range) et n’impose donc pas de valeur particulière à l’objet d’un triplet dans lequel la propriété est utilisée.

Pour signifier Quimperlé, j’ai suivit l’exemple de la biographie d’Henry VIII et j’ai utilisé DBpedia en anglais, mais j’aurais tout aussi bien pu utiliser DBpedia en français, voire un référentiel géographique (gazetteer en anglais) tel que Getty Thesaurus of Geographic Names et faire la déclaration suivante :

@prefix person: <http://prelib.huma-num.fr/person/> .
@prefix event: <http://prelib.huma-num.fr/event/> .
@prefix place: <http://prelib.huma-num.fr/place/> .
@prefix cidoc: <http://www.cidoc-crm.org/cidoc-crm/> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix dc: <http://purl.org/dc/terms/> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix tgn: <http://vocab.getty.edu/tgn/> .

event:1 a bio:Birth ;
rdfs:label "Naissance de Théodore-Claude-Henri Hersart de la Villemarqué le 7 juillet 1815 à Quimperlé"@fr ;
bio:date "1815-07-07"^^xsd:date ;
bio:place tgn:7009459 ; # Voir http://vocab.getty.edu/tgn/7009459
bio:parent person:1115 , person:1114 ;
bio:principal person:1 .

Bon, ce n’est pas tout de faire des tests de vocabulaires, mais il faudrait faire quelques premières requêtes en SPARQL pour les évaluer. Pour cela rien de tel qu’un triple store tel que Sesame RDF que vous pouvez installer en suivant les instructions de Thomas Francart. La suite au prochain épisode…

  1. Par copie locale, j’entends une copie de ma base de données installée sur mon ordinateur avec la plateforme de développement web EasyPHP. []
  2. Source : Ces Quimperlois(es) qui ont fait l’histoire (Jacques Gouriou, Alain Pennec, Fañch Postic), Amis de l’abbaye Sainte-Croix de Quimperlé / Société d’Histoire de Kemperle, décembre 2007. []
  3. Notez que la notion de sous-classe est indiquée dans le graphique ci-dessus par des doubles flèches. []
  4. Le FORTH Institute of Computer Science est un institut d’informatique grec où travaille Martin Doerr, un des co-rédacteurs du manuel de référence du CIDOC CRM []
  5. Voir à ce sujet la discussion Start/End vs Period of Existence sur le site officiel du CIDOC CRM. []
  6. Voir le chapitre 6 “Example” de Deducing Event Chronology in a Cultural Heritage Documentation System où l’on trouve un exemple de déduction de la date de construction d’une église à partir de la date à laquelle ont été approuvés les plans et la date d’un mariage célébré dans cette église. []
  7. L’intérêt de passer par des ressources externes sera plus évidente quand on fera des requêtes en SPARQL. []

Sémantiser une base de données relationnelle (1er épisode)

Dans un billet précédent, j’avais commencé à envisager l’évolution de la base de données relationnelle des auteurs de langue bretonne du projet PRELIB afin de mieux gérer la saisie des données temporelles. Mais au delà de ce problème, ce pose la question du stockage dans une base de donnée relationnelle et le passage au web sémantique.

Je m’intéresse depuis 2012 au web sémantique mais j’avais du mal à passer à la pratique faute d’avoir trouvé un outil de publication en RDF bien documenté et des vocabulaires ou des ontologies permettant d’exprimer nos données biographiques en RDF.

Concernant les outils, j’avais découvert en 2013 le logiciel Open source Callimachus en lisant le livre Linked Data co-écrit par David Wood (livre dont je vous recommande la lecture que je trouve plus digeste que celle du livre en français Le web sémantique), mais la documentation de Callimachus n’était pas assez aboutie à l’époque et je n’ai pas su comment l’utiliser pour mes besoins. J’avais aussi repéré CubicWeb un outil en Python sur lequel repose data.bnf.fr. Mais son installation s’est avérée trop compliquée sous Windows et je n’ai pas pu le tester. Sans compter là encore sur une documentation peu aboutie.

D’un autre côté, la plateforme DataLift, que j’ai rapidement testée la semaine dernière, permettrait dans un premier temps de transformer les données relationnelles en RDF. Je conserverai le stockage des données dans la base de données relationnelle mySQL, mais elles seraient “libérées” de la base sous la forme d’un export en RDF (et interrogeables à travers un SPARQL Endpoint ou REST + RESTdesc ? A voir).

Pour découvrir DataLift, je vous conseille de visionner la vidéo de démonstration de Gabriel Kepeklian où il se sert de DataLift pour sémantiser en quelques clics un fichier CSV des emplacements des kiosques à journaux mis à disposition sur ParisData. C’est plutôt convaincant.

Du côté des vocabulaires, j’avais identifié FRBR pour la saisie des œuvres littéraires mais j’avais du mal à en trouver une pour exprimer les données biographiques jusqu’à ce que j’entende parler fin 2014 de CIDOC1 CRM2 grâce au projet Biblissima.

Une lecture récente de documents sur le CIDOC CRM m’a également permit de comprendre que FRBRoo (FRBR object oriented) était une extension du modèle du CIDOC et que je devais plutôt m’intéresser à FRBRoo qu’à FRBR pour exprimer en RDF les données de ma base concernant la production littéraire.

L’objectif, au printemps 2015 est donc d’essayer de voir comment exprimer les données avec le CIDOC CRM et FRBRoo puis de convertir les données de la base de données relationnelles avec DataLift afin de comparer les requêtes SPARQL avec des requêtes SQL, de faire des essais d’analyse de réseau à partir de ces données RDF et de vérifier si le web sémantique permet réellement d’inférer de nouvelles connaissances (peut-être l’aspect le plus intéressant du web sémantique) en mettant en pratique l’article Bringing reasoning to the Web de Ruben Verborgh.

Vous pouvez télécharger le PDF du Schéma conceptuel de la base de données PRELIB au 23 octobre 2014. Ce n’est certainement pas un modèle à suivre pour la conception d’une base de données relationnelle mais il me servira de référence pour RDFiser la base de données par étapes successives.

Pour commencer, où peut-on trouver des informations sur le CIDOC CRM ?

Le site officiel du CIDOC CRM (version du 17 avril 2015) est la source de référence mais est un peu fouillis. L’information est dispersée dans de multiples sous-rubriques où l’on a un peu de mal à se retrouver. Mais j’ai découvert un peu par hasard qu’une nouvelle version du site est en chantier à cette adresse http://139.91.183.82:8888/drupal/ où l’excellent CIDOC-CRM Tutorial et la version HTML du manuel de référence de la version 6.0 du CRM (sortie en février 2015) sont mieux mis en avant.

SI vous êtes intéressés par la version PDF du manuel de référence (200 pages) de la version 6.0, il est disponible depuis la page Official Release of the CIDOC CRM où vous trouverez également un lien vers l’expression en RDF Schema du modèle (à consulter aussi sur LOV, Linked Open Vocabulary3).

Le manuel faisant 200 pages, vous aurez une meilleure introduction au CRM en lisant le document d’introduction (les anglophones appellent ce type de document des “primer”) ou si vous avez du temps devant vous, en visionnant les vidéos du CIDOC-CRM Tutorial.

Pour vous y retrouver dans les multiples entités et propriétés du modèle, vous pouvez aussi consulter des représentations graphiques de la version 5.0.4 du modèle : La version complète et la version réduite.

Toutes ces ressources sont en anglais. Le seul document de référence en français sur le CIDOC CRM est la traduction de la norme ISO 21127 (la normalisation ISO du CIDOC CRM) dont la lecture vous coutera 198 francs suisses sur le site de l’ISO ou 157 euros sur la boutique en ligne de l’Afnor.

Il faut noter au passage que le CIDOC CRM est un modèle et qu’il n’impose pas de langage pour exprimer les données. Je pourrai donc tout aussi bien adapter ma base de données relationnelle pour qu’elle repose sur le modèle, rien ne m’oblige à utiliser le RDF sinon mon intérêt pour ce format et le web sémantique. Il est néanmoins dommage que l’on ne trouve pas d’exemples de données exprimées en RDF sur le site officiel du CIDOC CRM alors que le Dublin Core Metadata Initiative l’a fait pour le Dublin Core dans deux guides utilisateurs publiés sur son wiki4.

Table "Personne" de la base de données relationnelle PRELIB

Table “Personne” de la base de données relationnelle PRELIB

Essayons d’appliquer le modèle CIDOC CRM à la base de données en commençant par la table “Personne” qui stocke des informations sur des individus. L’entité qui correspond le mieux à cette table est E21 Person. Dans le futur site du projet, chaque individu va devenir une ressource RDF de type E21 Person accessible à partir d’une URI construite à partir de la clé primaire de la table “Personne”. Par exemple, les informations sur Théodore Hersart de la Villemarqué, qui a pour clé primaire id_personne = 80 dans la table “Personne” pourra être accessible à l’URI http://prelib.huma-num.fr/person/80. Notez que vous pourrez récupérer depuis cette URI, soit du contenu en HTML sur Théodore si vous la consultez avec votre navigateur web, soit du RDF si vous vous connectez avec une application telle ARQ pour faire des requêtes SPARQL5.

Une première lecture de la référence à E21 Person dans le manuel de référence peut donner l’impression que l’entité n’a qu’une seule propriété P152 has parent. Ne peut-on que donner des informations sur les parents d’un individu avec CIDOC-CRM ?

Que neni.

En effet, en consultant la représentation graphique des entités et des modules disponibles pour signifier l’existence d’un objet ou d’une personne (reproduite ci-dessous), on se rend compte qu’il existe une propriété P98 brought into life qui permet de lier la personne à une ressource de type E67 Birth. Notez au passage que le sens de la flèche entre E67 Birth et E21 Person indique que P98 brought into life est une propriété de E67 Birth et non pas de E21 Person.

Source : http://www.cidoc-crm.org/cidoc_graphical_representation_v_5_1/existence.html

Source :http://www.cidoc-crm.org/cidoc_graphical_representation_v_5_1/existence.html

Le diagramme indique aussi les cardinalités. Ces couples (0,n) ou (1,n) ou (0,1) qui indiquent le nombre d’entités minimales et maximales impliquées dans la relation. Notamment le (0,n) indiqué du côté de E67 Birth pour la propriété  P98 brought into life indique qu’un accouchement (il s’agit plus d’un accouchement que d’une naissance si je ne m’abuse) peut donner naissance à zéro (!?) ou plusieurs enfants (dans le cas de jumeaux, triplés, etc.). Le (1,1) du côté de E21 Person précise comme on pourrait s’y attendre qu’une personne ne peut naitre qu’une seule fois lors du même accouchement et qu’un individu est forcément né une fois (donc Dieu ne peut être une E21 Person si on considère qu’il a toujours existé). On voit que E67 Birth nous permet aussi de déclarer le père et la mère des enfants et il y a fort à parier que l’on puisse aussi déclarer le lieu de la naissance.

A creuser : Les cardinalités fonctionnent-elles pour toutes les instances de l’entité ou pour une seule ? Autrement dit, dès qu’un individu est impliqué dans un accouchement comme nouveau-né, est ce que cela suffit pour qu’il ne puisse pas être impliqué dans un autre accouchement ?

Au passage, rien ne nous empêche d’enfreindre les règles de cardinalité. Il nous faudra nous même mettre en place des mécanismes pour vérifier si les règles sont respectées.

Concernant les parents, le manuel indique pour E67 Birth que dans ce modèle, le père biologique n’est pas vu comme un participant nécessaire de l’événement. Ce qui conforte l’idée que l’entité E67 Birth permet de décrire un accouchement (un événement impliquant la mère et les nouveaux-nés, ayant lieu à une date, une durée et à un endroit donnés) et non pas des liens de parentés. Puisque comme chacun sait, les pères n’assistent pas systématiquement à la naissance de leurs enfants.

In this model, the biological father is not seen as a necessary participant in the E67 Birth event.

Le manuel précise également que P96 by mother et P97 from father concernent uniquement les parents biologiques. Le modèle n’écarte pas pour autant les parents non-biologiques puisqu’ils peuvent être déclarés avec la fameuse propriété P152 has parent évoquée précédemment :

This property associates an instance of E21 Person with another instance of E21 Person who plays the role of the first instance’s parent, regardless of whether the relationship is biological parenthood, assumed or pretended biological parenthood or an equivalent legal status of rights and obligations obtained by a social or legal act.

Extrait de l'acte de naissance de Théodore Hersart de la Villemarqué

Extrait de l’acte de naissance de Théodore Hersart de la Villemarqué. Source : Archives départementales du Finistère (http://mnesys-portail.archives-finistere.fr).

D’après l’acte de naissance de Théodore Hersart de la Villemarqué6, l’auteur du Barzaz-Breiz est né le 7 juillet 1815 à Quimperlé et il est le fils de Pierre Michel François Marie Toussaint Hersart de la Villemarqué et de Marie Ursule Claude Henriette Kerjean Feydeau.

Pour exprimer cette information en RDF, il nous faut une URI (si possible une URL permanente ou PURL) où un processeur SPARQL comme ARQ pourra trouver une version RDF Shema ou OWL du CIDOC CRM7. En tapant “CIDOC” sur LOV (Linked Open Vocabularies), on trouve que l’espace de nom du CIDOC est http://www.cidoc-crm.org/cidoc-crm/.

L’URI http://prelib.huma-num.fr/person/80 pourrait donc renvoyer le RDF suivant (exprimé ici avec Turtle) :

@prefix prelib: <http://prelib.huma-num.fr/> .
@prefix cidoc: <http://www.cidoc-crm.org/cidoc-crm/> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix dc: <http://purl.org/dc/terms/> .

prelib:person/80 a cidoc:Person, foaf:Person ;
dc:title "Théodore-Claude-Henri Hersart de la Villemarqué (1815-1895)"@fr ;
foaf:name "Théodore-Claude-Henri Hersart de la Villemarqué"@fr ;
foaf:givenName "Théodore Claude Henri" ;
foaf:familyName "Hersart de la Villemarqué" ;
foaf:nickname "Barz Nizon", "Kervarker";
foaf:gender "male"@en, "homme"@fr.

Le CIDOC CRM permet de nommer les ressources mais je vais me contenter pour l’instant d’exprimer le nom et les pseudonymes de Théodore avec le Dublin Core et FOAF (Friend of a Friend) comme le fait la BnF sur data.bnf.fr.

Les informations concernant la naissance de Théodore devront être exprimées depuis une autre URI par une autre ressource de type E67 Birth. En effet, je ne peux exprimer à l’adresse http://prelib.huma-num.fr/person/80 que des triplets qui ont pour sujet8 la ressource elle-même (Enfin, je suppose que c’est comme cela qu’il faut procéder).

Je pourrai mettre à disposition la ressource à l’URI http://prelib.huma-num.fr/birth/1 (où le chiffre 1 indique le numéro de la ressource de type E67 Birth) mais pour éviter d’utiliser des chemins dédiés à chaque classe du CIDOC CRM, je vais utiliser le nom de la classe générique E5 Event dans le chemin de l’URI.

Supposons donc qu’à l’URI http://prelib.huma-num.fr/event/1 on va pouvoir récupérer le RDF suivant (en supposant que l’URI correspondant à Marie Kerjean Feydeau, la mère de Théodore soit http://prelib.huma-num.fr/person/1115) :

@prefix prelib: <http://prelib.huma-num.fr/> .
@prefix cidoc: <http://www.cidoc-crm.org/cidoc-crm/> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix dc: <http://purl.org/dc/terms/> .

prelib:event/1 a cidoc:Event ;
prelib:event/1 a cidoc:Birth ;
cidoc:brought_into_life prelib:person/80 ;
cidoc:by_mother prelib:person/1115.

Comme rien ne prouve que le père de Théodore n’ai assisté à l’accouchement, on ne le rajoute pas à l’événement avec la propriété P97 from father. Par contre, comment signaler la date et le lieu de l’heureux événement ? C’est là que ça se complique.

En parcourant les représentations graphiques sur le site officiel du modèle, j’ai trouvé la modélisation des informations sur la nationalité d’une personne où l’on constate que l’on peut déclarer qu’un accouchement E67 Birth s’est produit durant une E4 Period et à une E53 Place.

Modélisation des informations sur une personne avec le modèle CIDOC CRM. Source : http://www.cidoc-crm.org/cidoc_graphical_representation_v_5_1/person_nationality.html.

Modélisation des informations sur une personne avec le modèle CIDOC CRM. Source : http://www.cidoc-crm.org/cidoc_graphical_representation_v_5_1/person_nationality.html.

Cependant, P10 falls within sert à lier entre elles des E4_Period et servirait plutôt à déclarer que la naissance de Théodore a eu lieu durant la Restauration. Comme E67 Birth est une sous-classe de E2 Temporal Entity (une sous-sous-sous-classe) il doit bien y avoir moyen de déclarer la date du 7 juillet 1815 avec une propriété quelconque de Temporal Entity ou de ses sous-classes ?

En cherchant sur le web, j’ai trouvé la présentation du modèle CIDOC CRM par Patrick Le Boeuf le 9 décembre 2010 (reproduite ci-dessus) où l’on constate à la diapositive n°37 que la valeur littérale de la date de l’accouchement pourrait être saisie grâce à une ressource de type E50 Date elle même reliée à notre accouchement par P4 has time-span.

Pour l’instant, j’utilise une ressource anonyme ou blank node en anglais pour exprimer la ressource de type E50 Date et je saisi la valeur littérale avec une propriété rdfs:label et en lui donnant un type xsd:date conforme au format ISO 8601.

@prefix prelib: <http://prelib.huma-num.fr/> .
@prefix cidoc: <http://www.cidoc-crm.org/cidoc-crm/> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix dc: <http://purl.org/dc/terms/> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .

prelib:event/1 a cidoc:Event ;
prelib:event/1 a cidoc:Birth ;
cidoc:brought_into_life prelib:person/80 ;
cidoc:by_mother prelib:person/1115.
cidoc:is_identified_by _:date1

_:date1 a cidoc:Date ;
rdfs:label "1815-07-07"^^xsd:date

Pourquoi utiliser rdfs:label ? Et bien parce que c’est le seul moyen que j’ai trouvé l’instant pour saisir cette fameuse valeur. Si vous exprimez ces données avec RDF/XML, vous pouvez toujours mettre la valeur à l’intérieur d’une balise, comme dans l’exemple de la saisie de la période entre -500 à 500 tiré du wiki du projet Claros.

<crm:E52_Time-Span>
<crm:P82_at_some_time_within>
<claros:Period>
<claros:period_begin rdf:datatype="&xsd;gYear">-550</claros:period_begin>
<claros:period_end   rdf:datatype="&xsd;gYear">-500</claros:period_end>
</claros:Period>
</crm:P82_at_some_time_within>
</crm:E52_Time-Span>

Sauf qu’avec Turtle ou Notation3 (N3), la valeur (l’objet du triplet RDF) passe forcément par l’utilisation d’un prédicat. C’est pourquoi GND Ontology l’ontologie de la Deutsche Nationalbibliothek met à disposition la propriété (en non pas la classe) Date of birth qui permet la déclaration suivante :

@prefix prelib: <http://prelib.huma-num.fr/> .
@prefix cidoc: <http://www.cidoc-crm.org/cidoc-crm/> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix dc: <http://purl.org/dc/terms/> .
@prefix gnd: <http://d-nb.info/standards/elementset/gnd#> .

prelib:person/80 a cidoc:Person, foaf:Person , gnd:DifferentiatedPerson ;
dc:title "Théodore-Claude-Henri Hersart de la Villemarqué (1815-1895)"@fr ;
foaf:name "Théodore-Claude-Henri Hersart de la Villemarqué"@fr ;
gnd:dateOfBirth "1815/07/07"^^xsd:date .

Bon, ce billet est assez long comme ça. La suite au prochain épisode…

  1. Comité International pour la DOCumentation du Conseil international des musées []
  2. Conceptual Reference Model []
  3. Linked Open Vocabularies est un projet hébergé par l’Open Knowledge Fundation qui propose le référencement d’ontologies pour le web des données. []
  4. Wiki qui n’est certes pas mis en avant. []
  5. Pour en savoir plus, vous pouvez consulter la page Wikipedia sur la négociation de contenu : http://fr.wikipedia.org/wiki/N%C3%A9gociation_de_contenu. []
  6. L’acte de naissance de Théodore Hersart de la Villemarqué peut-être consulté en ligne dans la version numérisée des actes de naissances de Quimperlé entre 1814 et 1822 sur le portail des Archives départementales du Finistère. []
  7. Si vous n’êtes pas familiers avec ce vocabulaire, lisez le RDF 1.1 Primer du W3C. C’est une bonne introduction au web sémantique []
  8. Pour le concept de triplets RDF composés d’un sujet, d’un prédicat et d’un objet, lire le RDF 1.1 Primer. []

La saisie et les requêtes de dates pour la prosopographie (1ère partie)

Avertissement : Cet article est en cours de rédaction mais il est publié pour permettre une discussion sur ce sujet.

Depuis 2012, date de mon arrivée à l’UMS, je travaille avec deux enseignantes-chercheuses de Celtique, Mannaig Thomas et Nelly Blanchard à une base de données prosopographique des auteurs de langue bretonne. Cette base de données a été créée dans le cadre du projet PRELIB dont une des ambitions est de comprendre les raisons qui ont poussé des personnes à écrire et à publier en breton. En effet, écrire en breton, langue de tradition orale, ne va pas de soi et résulte d’un choix qui peut être influencé par la fréquentation de personnes rencontrées dans des lieux de sociabilité tels que des cercles littéraires, des associations ou des mouvements politiques.

La base contient des informations du type : François Jaffrennou est né le 15 mars 1879 à Carnoët, il a étudié au Collège Notre-Dame-de-Bon-Secours à Guingamp vers 1891 puis a débuté des études de droit à Rennes en 1899. Il a contribué aux revues An Oaled, War Sao, Buez Breiz. Il a été secrétaire de la section Langue et Littérature Bretonne de l’Union Régionaliste Bretonne à partir du 14 aout 1898. Il est l’auteur de Oberou yaouankiz, Ganedigez eun emzao, Le dictionnaire français-breton de poche.

Dans cette base de données relationnelle, conçue avec mySQL, la plupart des dates (par ex. une date de naissance) ne sont pas saisies dans un seul champ sous la forme d’une date complète (un jour, un mois, une année) mais dans trois champs séparant la saisie du jour, du mois et de l’année. Du point de vue du stockage, les dates ne sont pas stockées au format SQL DATE mais dans trois champs SQL de type INTEGER (un chiffre entier).

Les bases de données relationnelles ne permettent pas la saisie d’intervalles de temps. Elles ne permettent la saisie de données temporelles que sous la forme de dates (avec obligatoirement un jour, un mois, une année). Or les données historiques sont souvent imprécises et il n’est pas rare que l’on ne connaisse pas la date complète d’un événement (une date de naissance, la date à laquelle un individu a été élu président d’une association, etc.). La séparation de la saisie a donc été envisagée sous la forme de trois champs séparés pour le jour, le mois et l’année en attendant de trouver une solution plus orthodoxe.

Dans les bases de données SQL, les données de type date sont stockées au format aaaa-mm-jj (je parle bien ici du stockage dans la base et non pas de la saisie, le stockage dans ce format n’empêchant pas la saisie dans un formulaire web de dates au format français jj/mm/aaaa). La date du 3 juillet 1896 sera donc stockée sous la forme 1896-07-03.

On pourrait alors envisager de stocker une date incomplète en remplaçant le jour ou le mois par des zéros. Par exemple, si l’on sait que la personne est née en 1896 sans aucune précision sur le mois ou le jour de naissance, on pourrait stocker la date 1896-00-00 dans la base. Et si l’on sait au moins qu’elle est née en juillet 1896 de stocker la date 1896-07-00.

Mais cette solution amène d’autres problèmes : Premièrement, Django, le framework qui sert à élaborer les formulaires de saisie de notre base ne permet pas la saisie de dates non “valides” et l’adaptation de Django pour ajouter cette fonctionnalité ne semble pas chose aisée (Tout du moins si l’on en juge par la question How to deal with “partial” dates (2010-00-00) from MySQL in Django? posée sur le site de questions-réponses Stack Overflow en juin 2010).

Deuxièmement, il faudrait aussi adapter Django pour l’affichage des dates incomplètes. Car une personne souhaitant consulter la base comprendra peut-être qu’une personne est née en juillet 1896 mais comprendra moins l’affichage de 1896-07-00 ou 00/07/1896.

D’autre part les requêtes dans la base ne donnent pas des résultats attendus. En partant de la table prelib_participe_collectif qui stocke les participations d’individus à des collectifs, j’ai saisi des dates d’entrées dont certaines sont incomplètes (la saisie a été faite directement dans la base avec phpMyAdmin, sans passer par Django) : 0000-05-03 (le 3 mai d’une année indéterminée ?), 1898-08-14, 1959-00-00 (l’année 1959 ?), 1959-05-00 (le mois de mai 1959 ?), 1959-06-08, 2015-08-09.

Or la requête qui devrait permettre de récupérer les dates d’entrées dans des collectifs postérieures au 16 mai 1959 ne renvoie que 1959-06-08 et 2015-08-09 :

SELECT `date_entree`
FROM `prelib_participe_collectif`
WHERE `date_entree` > ‘1959-05-16’
ORDER BY `id_participe_collectif`

Alors que la requête qui devrait permettre de récupérer les dates d’entrées dans les collectifs antérieures au 16 mai 1959 renvoie les dates 0000-05-03, 1898-08-14, 1959-00-00, 1959-05-00 :

SELECT `id_participe_collectif`, `date_entree`
FROM `prelib_participe_collectif`
WHERE `date_entree` < ‘1959-05-16’
ORDER BY `id_participe_collectif`

Cela vient du fait que 1959-00-00 reste une date et n’est pas considérée par mySQL comme l’année 1959 soit une durée entre le 1er janvier 1959 à 0h et le 31 décembre 1959 à minuit. mySQL doit probablement comparer les années (1959 = 1959) puis les mois (00 < 05) puis les jours (00 < 16) de ces deux “dates” et en déduire que 1959-00-00 < 1959-05-16.

Ce qui amène à la constatation suivante : Les “dates” incomplètes sont en fait des durées (l’année 1959, le mois de mai 1959, d’avril à juin 1959). Il faudrait donc plutôt stocker une date de début et une date de fin quand on ne connait pas la date exacte d’un événement.

A ce propos, les développeurs de l’outil de création de bibliothèques numériques CollectiveAccess sont même allés plus loin puisqu’ils stockent toutes les métadonnées temporelles décrivant un document sous forme de durées. Ainsi la date du 7 juin 2007 est stockée sous la forme des deux dates (à la seconde près) du 7 juin 2007 à 00:00:00 et du 7 juin 2007 à 24:59:59. L’avantage de cette solution est que les deux dates sont stockées dans le format SQL TIMESTAMP prévu à cet effet. On bénéficie alors de tous les avantages des requêtes sur les dates en SQL.

Ce changement de paradigme du stockage d’une date vers le stockage d’une durée change aussi les requêtes. On ne fait plus de requête pour trouver les dates d’entrées dans un collectif antérieures au 16 mai 1959 pour reprendre l’exemple précédent, mais pour trouver des intervalles de temps terminés avant l’intervalle de temps du 16 mai 1959 à 00:00:00 au 16 mai à 24:59:59 ou des intervalles de temps dans lequel le 16 mai 1959 est compris.

Que donneraient donc les requêtes SQL sur des dates uniquement stockées sous forme d’intervalles temporels ? Ne seront-elles pas trop complexes ?

Autre piste : Le stockage en RDF offre-t-il des avantages pour le stockage des dates et à quoi ressemblerai des requêtes sur des durées avec SPARQL ?