OpenRefine au service de BACON : quelle évaluation pour les fichiers KBART ? [4] – Dispositif CERCLES dans le cadre de BACON

[Lire le billet qui introduit cette série « OpenRefine au service de BACON : quelle évaluation pour les fichiers KBART ? »]

Développer des outils et les mettre à la disposition du réseau afin de répondre à vos besoins est l’une des principales missions de l’Abes. Dans le cadre du projet Bacon, l’idée de mettre entre vos mains une partie du travail mené est née avec le projet. Celui-ci étant suffisamment mûr, le temps est venu d’ouvrir ce que nous avons choisi d’appeler les CERCLES-BACON.

Le premier d’entre eux portera sur l’éditeur BREPOLS. Avant d’exposer les modalités de dépôt des candidatures, revenons sur les principes qui prévalent à un tel dispositif.

Le dispositif CERCLES-BACON

CERCLES permet la mutualisation des compétences du réseau au service de la qualité du catalogue. Organisé sous la forme de chantiers qualités, l’objectif est de s’attaquer à des corpus dont les notices ne sont pas toujours de qualité satisfaisante.
Avec BACON la thématique reste la même, améliorer la qualité des métadonnées, circonscrite de fait aux ressources électroniques. Avec quelques nuances :

  • les métadonnées KBART sont des métadonnées de signalement et de gestion des accès. Elles sont moins riches et moins complexes que les métadonnées descriptives contenues dans les notices du SUDOC ;
  • la participation du fournisseur des métadonnées KBART est une condition sine qua non. En aucun cas les métadonnées ne sont corrigées par l’évaluateur, qui intervient seulement afin de produire un rapport d’erreurs. Ce rapport est ensuite transmis au fournisseur, qui a à sa charge la correction du fichier. De cette façon, la qualité des données est améliorée à la source et profite à l’ensemble de la chaîne.

CERCLES-BACON est initié pour plusieurs raisons.
Avant tout il s’agit de s’appuyer sur l’expertise d’un catalogueur qui, de par son expérience, sera en mesure de mener à bien l’évaluation des fichiers KBART dans les moindres détails. La simplicité du contenu des fichiers cache parfois des problématiques plus complexes, telles que les métarevues.
Par ailleurs, l’évaluateur qui aura fait le choix de travailler avec nous aura accès aux ressources, ce qui lui permettra de dénouer certains cas. Car, contrairement à l’Abes, son établissement en aura fait l’acquisition. A cet égard, la relation de confiance établie auprès de l’éditeur permettra de favoriser la prise en compte des demandes de corrections.
Enfin, l’occasion est ainsi donnée de former des membres du réseau à l’utilisation d’outils qui, s’ils ne le sont déjà, deviendront certainement nécessaires dans la trousse à outils du bibliothécaire : OpenRefine, webservices, etc…

L’évaluateur : activités et compétences

Pour l’évaluateur, plusieurs tâches seront à accomplir. Contacter l’éditeur, lui expliquer le principe du partenariat ainsi que la recommandation, récupérer les fichiers et les évaluer, lui en communiquer le résultat et procéder aux chargements. Autant de compétences techniques et relationnelles, que la formation et le suivi proposés par l’Abes permettront de mettre en œuvre au cours du premier trimestre 2017.

Les conditions d’accès au dispositif sont les suivantes :

  • l’établissement dont vous dépendez doit avoir souscrit à des ressources auprès de l’éditeur BREPOLS ;
  • vous devez disposer d’un accès au registre ISSN ;
  • vous devez avoir la possibilité, avec ou sans l’intervention de votre DSI, d’installer OpenRefine sur votre poste de travail.

Les compétences de l’évaluateur devront être les suivantes :

  • familiarité avec la documentation électronique ;
  • notions en UNIMARC ;
  • notions en catalogage (WinIBW) ;
  • niveau intermédiaire en informatique ;
  • bon relationnel ;
  • anglais technique : lu.

La connaissance de la recommandation KBART n’est pas un prérequis obligatoire. Pour autant, elle devra être acquise au lancement du CERCLES.

La charge de travail est estimée à 1/2 ETP durant les deux premières semaines, formation comprise, puis à 1 journée par mois. Le partenariat établi entre l’établissement et l’Abes fera l’objet d’un acte d’engagement.

Si vous êtes intéressé(e) par ce projet et que vous souhaitez rejoindre le premier des CERCLES-BACON, n’hésitez plus ! Il est dès à présent possible de nous contacter en postant une demande sur le guichet Bacon.

CLY

OpenRefine au service de BACON : quelle évaluation pour les fichiers KBART ? [3] – Cas pratique

[Lire le billet qui introduit cette série « OpenRefine au service de BACON : quelle évaluation pour les fichiers KBART ? »]

Dans le cadre de l’accompagnement des éditeurs scientifiques francophones à la mise en œuvre de la recommandation KBART, les fichiers sont évalués par l’Abes à l’aide d’OpenRefine.

Les tests menés sont de différents types : syntaxiques et sémantiques. Les premiers vérifient la conformité du format des métadonnées au regard des règles édictées par la recommandation. Les seconds comparent les informations contenues dans le fichier à celles du SUDOC.

Un script GREL a été réalisé, pour l’évaluation des périodiques d’une part, des livres électroniques d’autre part.

La dernière version du script utilisé pour l’évaluation des périodiques est la suivante :

[ { "op": "core/text-transform", "description": "Script syntaxique : pour chaque ligne, test l'ensemble des champs. Si une ligne ne contient que des champs vides, alors la mention « ligne vide » apparaît dans le champ publication_title de la ligne concernée", "engineConfig": { "mode": "row-based", "facets": [] }, "columnName": "publication_title", "expression": "grel:if(cells.publication_title.value.length()==0,(if(cells.print_identifier.value.length()==0,(if(cells .online_identifier.value.length()==0,(if(cells.date_first_issue_online.value.length()==0,(if(cells.num_first_vol_online.value.length()==0,(if(cells.num_first_issue_online.value.length()==0,(if(cells.date_last_issue_online.value.length()==0,(if(cells.num_last_vol_online.value.length()==0,(if(cells.num_last_issue_online.value.length()==0,(if(cells.title_url.value.length()==0,(if(cells .first_author.value.length()==0,(if(cells.title_id.value.length()==0,(if(cells.embargo_info.value.length()==0,(if(cells.coverage_depth.value.length()==0,(if(cells.notes.value.length()==0,(if(cells.publisher_name.value.length()==0,(if(cells.publication_type.value.length()==0,(if(cells.date_monograph_published_print.value.length()==0,(if(cells.date_monograph_published_online.value.length()==0,(if(cells.monograph_volume.value.length()==0,(if(cells.monograph_edition.value.length()==0,(if(cells.first_editor.value.length()==0,(if(cells.parent_publication_title_id.value.length()==0,(if(cells.preceding_publication_title_id.value.length()==0,(if(cells.access_type.value.length()==0,'ligne vide',value)),value)),value)),value)),value)),value)),value)),value)),value)),value)),value)),value)),value)),value)),value)),value)),value)),value)),value)),value)),value)),value)),value)),value)),value)", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Suppression des espaces en début et en fin de cellule", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "publication_title", "expression": "value.trim()", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Suppression des espaces en début et en fin de cellule", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "print_identifier", "expression": "value.trim()", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Suppression des espaces en début et en fin de cellule", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "online_identifier", "expression": "value.trim()", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Suppression des espaces en début et en fin de cellule", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "date_first_issue_online", "expression": "value.trim()", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Suppression des espaces en début et en fin de cellule", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "num_first_vol_online", "expression": "value.trim()", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Suppression des espaces en début et en fin de cellule", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "num_first_issue_online", "expression": "value.trim()", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Suppression des espaces en début et en fin de cellule", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "date_last_issue_online", "expression": "value.trim()", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Suppression des espaces en début et en fin de cellule", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "num_last_vol_online", "expression": "value.trim()", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Suppression des espaces en début et en fin de cellule", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "num_last_issue_online", "expression": "value.trim()", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Suppression des espaces en début et en fin de cellule", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "title_url", "expression": "value.trim()", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Suppression des espaces en début et en fin de cellule", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "title_id", "expression": "value.trim()", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Suppression des espaces en début et en fin de cellule", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "embargo_info", "expression": "value.trim()", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Suppression des espaces en début et en fin de cellule", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "coverage_depth", "expression": "value.trim()", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Suppression des espaces en début et en fin de cellule", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "publisher_name", "expression": "value.trim()", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Suppression des espaces en début et en fin de cellule", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "publication_type", "expression": "value.trim()", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Suppression des espaces en début et en fin de cellule", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "preceding_publication_title_id", "expression": "value.trim()", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Suppression des espaces en début et en fin de cellule", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "access_type", "expression": "value.trim()", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Si plusieurs caractères d’espaces consécutifs, fusion en un seul", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "publication_title", "expression": "value.replace(/\\s+/,' ')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Si plusieurs caractères d’espaces consécutifs, fusion en un seul", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "print_identifier", "expression": "value.replace(/\\s+/,' ')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Si plusieurs caractères d’espaces consécutifs, fusion en un seul", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "online_identifier", "expression": "value.replace(/\\s+/,' ')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Si plusieurs caractères d’espaces consécutifs, fusion en un seul", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "date_first_issue_online", "expression": "value.replace(/\\s+/,' ')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Si plusieurs caractères d’espaces consécutifs, fusion en un seul", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "num_first_vol_online", "expression": "value.replace(/\\s+/,' ')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Si plusieurs caractères d’espaces consécutifs, fusion en un seul", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "num_first_issue_online", "expression": "value.replace(/\\s+/,' ')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Si plusieurs caractères d’espaces consécutifs, fusion en un seul", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "date_last_issue_online", "expression": "value.replace(/\\s+/,' ')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Si plusieurs caractères d’espaces consécutifs, fusion en un seul", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "num_last_vol_online", "expression": "value.replace(/\\s+/,' ')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Si plusieurs caractères d’espaces consécutifs, fusion en un seul", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "num_last_issue_online", "expression": "value.replace(/\\s+/,' ')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Si plusieurs caractères d’espaces consécutifs, fusion en un seul", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "title_url", "expression": "value.replace(/\\s+/,' ')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Si plusieurs caractères d’espaces consécutifs, fusion en un seul", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "title_id", "expression": "value.replace(/\\s+/,' ')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Si plusieurs caractères d’espaces consécutifs, fusion en un seul", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "embargo_info", "expression": "value.replace(/\\s+/,' ')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Si plusieurs caractères d’espaces consécutifs, fusion en un seul", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "coverage_depth", "expression": "value.replace(/\\s+/,' ')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Si plusieurs caractères d’espaces consécutifs, fusion en un seul", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "notes", "expression": "value.replace(/\\s+/,' ')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Si plusieurs caractères d’espaces consécutifs, fusion en un seul", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "publisher_name", "expression": "value.replace(/\\s+/,' ')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Si plusieurs caractères d’espaces consécutifs, fusion en un seul", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "publication_type", "expression": "value.replace(/\\s+/,' ')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Si plusieurs caractères d’espaces consécutifs, fusion en un seul", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "preceding_publication_title_id", "expression": "value.replace(/\\s+/,' ')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Si plusieurs caractères d’espaces consécutifs, fusion en un seul", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "access-type", "expression": "value.replace(/\\s+/,' ')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : suppression du caractère de retour à la ligne et du caractère d'espace insécable", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "publication_title", "expression": "grel:value.replace(/\\u000a/,'').replace(/\\u00A0/,'')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : suppression du caractère de retour à la ligne et du caractère d'espace insécable", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "print_identifier", "expression": "grel:value.replace(/\\u000a/,'').replace(/\\u00A0/,'')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : suppression du caractère de retour à la ligne et du caractère d'espace insécable", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "online_identifier", "expression": "grel:value.replace(/\\u000a/,'').replace(/\\u00A0/,'')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : suppression du caractère de retour à la ligne et du caractère d'espace insécable", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "date_first_issue_online", "expression": "grel:value.replace(/\\u000a/,'').replace(/\\u00A0/,'')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : suppression du caractère de retour à la ligne et du caractère d'espace insécable", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "num_first_vol_online", "expression": "grel:value.replace(/\\u000a/,'').replace(/\\u00A0/,'')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : suppression du caractère de retour à la ligne et du caractère d'espace insécable", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "num_first_issue_online", "expression": "grel:value.replace(/\\u000a/,'').replace(/\\u00A0/,'')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : suppression du caractère de retour à la ligne et du caractère d'espace insécable", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "date_last_issue_online", "expression": "grel:value.replace(/\\u000a/,'').replace(/\\u00A0/,'')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : suppression du caractère de retour à la ligne et du caractère d'espace insécable", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "num_last_vol_online", "expression": "grel:value.replace(/\\u000a/,'').replace(/\\u00A0/,'')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : suppression du caractère de retour à la ligne et du caractère d'espace insécable", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "num_last_issue_online", "expression": "grel:value.replace(/\\u000a/,'').replace(/\\u00A0/,'')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : suppression du caractère de retour à la ligne et du caractère d'espace insécable", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "title_url", "expression": "grel:value.replace(/\\u000a/,'').replace(/\\u00A0/,'')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : suppression du caractère de retour à la ligne et du caractère d'espace insécable", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "title_id", "expression": "grel:value.replace(/\\u000a/,'').replace(/\\u00A0/,'')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : suppression du caractère de retour à la ligne et du caractère d'espace insécable", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "embargo_info", "expression": "grel:value.replace(/\\u000a/,'').replace(/\\u00A0/,'')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : suppression du caractère de retour à la ligne et du caractère d'espace insécable", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "coverage_depth", "expression": "grel:value.replace(/\\u000a/,'').replace(/\\u00A0/,'')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "SScript syntaxique : suppression du caractère de retour à la ligne et du caractère d'espace insécable", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "notes", "expression": "grel:value.replace(/\\u000a/,'').replace(/\\u00A0/,'')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : suppression du caractère de retour à la ligne et du caractère d'espace insécable", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "publisher_name", "expression": "grel:value.replace(/\\u000a/,'').replace(/\\u00A0/,'')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : suppression du caractère de retour à la ligne et du caractère d'espace insécable", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "publication_type", "expression": "grel:value.replace(/\\u000a/,'').replace(/\\u00A0/,'')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : suppression du caractère de retour à la ligne et du caractère d'espace insécable", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "preceding_publication_title_id", "expression": "grel:value.replace(/\\u000a/,'').replace(/\\u00A0/,'')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : suppression du caractère de retour à la ligne et du caractère d'espace insécable", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "access_type", "expression": "grel:value.replace(/\\u000a/,'').replace(/\\u00A0/,'')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : remplace le x minuscule par un X majuscule pour les p-ISSN", "engineConfig": { "mode": "row-based", "facets": [] }, "columnName": "print_identifier", "expression": "grel:value.replace(\"x\",\"X\")", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : remplace le x minuscule par un X majuscule pour les e-ISSN", "engineConfig": { "mode": "row-based", "facets": [] }, "columnName": "online_identifier", "expression": "grel:value.replace(\"x\",\"X\")", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/column-addition", "description": "Script syntaxique : doublons sur le publication_title", "engineConfig": { "mode": "row-based", "facets": [] }, "newColumnName": "publication_title_doublon", "columnInsertIndex": 25, "baseColumnName": "publication_title", "expression": "grel:forNonBlank(value,v,facetCount(v,'value','publication_title'),'')", "onError": "set-to-blank" }, { "op": "core/text-transform", "description": "Script syntaxique : vérifie qu'aucun champ du publication_title n'est vide", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "publication_title", "expression": "grel:if(isBlank(value)==true,'titre manquant',value)", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/column-addition", "description": "Script syntaxique : doublons sur le print_identifier", "engineConfig": { "mode": "row-based", "facets": [] }, "newColumnName": "print_identifier_doublon", "columnInsertIndex": 26, "baseColumnName": "print_identifier", "expression": "grel:forNonBlank(value,v,facetCount(v,'value','print_identifier'),'')", "onError": "set-to-blank" }, { "op": "core/column-addition", "description": "Script syntaxique : doublons sur le online_identifier", "engineConfig": { "mode": "row-based", "facets": [] }, "newColumnName": "online_identifier_doublon", "columnInsertIndex": 27, "baseColumnName": "online_identifier", "expression": "grel:forNonBlank(value,v,facetCount(v,'value','online_identifier'),'')", "onError": "set-to-blank" }, { "op": "core/text-transform", "description": "Script syntaxique : ne conserve que les quatre premiers caractères contenus dans le date_first_issue_online, à condition qu'ils respectent le format YYYY. Sinon, renvoie un message d'erreur", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "date_first_issue_online", "expression": "grel:if(value.match(/.*(\\d{4}).*/)[0]==null,value+' : format incorrect',value.match(/.*(\\d{4}).*/)[0])", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : ne conserve que les quatre premiers caractères contenus dans le date_last_issue_online, à condition qu'ils respectent le format YYYY. Sinon, informe d'une erreur de format", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "date_last_issue_online", "expression": "grel:if(isNonBlank(value),if(value.match(/.*(\\d{4}).*/)[0]==null,value+' : format incorrect',value.match(/.*(\\d{4}).*/)[0]),value)", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/column-addition", "description": "Script syntaxique : le contenu du num_first_vol_online, lorsqu'il n'est pas numérique, suit-il une cohérence ?", "engineConfig": { "mode": "row-based", "facets": [] }, "newColumnName": "num_first_vol_non_numérique", "columnInsertIndex": 28, "baseColumnName": "num_first_vol_online", "expression": "grel:if(isNotNull(value.match(/[0-9]*/)),'','cohérent ? '+value)", "onError": "set-to-blank" }, { "op": "core/column-addition", "description": "Script syntaxique : le contenu du num_first_issue_online, lorsqu'il n'est pas numérique, suit-il une cohérence ?", "engineConfig": { "mode": "row-based", "facets": [] }, "newColumnName": "num_first_issue_non_numérique", "columnInsertIndex": 29, "baseColumnName": "num_first_issue_online", "expression": "grel:if(isNotNull(value.match(/[0-9]*/)),'','cohérent ? '+value)", "onError": "set-to-blank" }, { "op": "core/column-addition", "description": "Script syntaxique : le contenu du num_last_vol_online, lorsqu'il n'est pas numérique, suit-il une cohérence ?", "engineConfig": { "mode": "row-based", "facets": [] }, "newColumnName": "num_last_vol_non_numérique", "columnInsertIndex": 30, "baseColumnName": "num_last_vol_online", "expression": "grel:if(isNotNull(value.match(/[0-9]*/)),'','cohérent ? '+value)", "onError": "set-to-blank" }, { "op": "core/column-addition", "description": "Script syntaxique : le contenu du num_last_issue_online, lorsqu'il n'est pas numérique, suit-il une cohérence ?", "engineConfig": { "mode": "row-based", "facets": [] }, "newColumnName": "num_last_issue_non_numérique", "columnInsertIndex": 31, "baseColumnName": "num_last_issue_online", "expression": "grel:if(isNotNull(value.match(/[0-9]*/)),'','cohérent ? '+value)", "onError": "set-to-blank" }, { "op": "core/text-transform", "description": "Script syntaxique : URL manquante", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "title_url", "expression": "grel:if(isBlank(value)==true,'URL obligatoire',value)", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/column-addition", "description": "Script syntaxique : la partie fixe du title_url mise de côté, la partie évolutive restante correspond-elle au title_id ? Test I ATTENTION : A ACTUALISER AVANT D'UTILISER LE SCRIPT : remplacer [X] par la partie fixe de l'URL", "engineConfig": { "mode": "record-based", "facets": [] }, "newColumnName": "title_url_bis", "columnInsertIndex": 32, "baseColumnName": "title_url", "expression": "grel:value.replace('[X]','')", "onError": "set-to-blank" }, { "op": "core/column-addition", "description": "Script syntaxique : la partie fixe du title_url mise de côté, la partie évolutive restante correspond-elle au title_id ? Test II", "engineConfig": { "mode": "row-based", "facets": [] }, "newColumnName": "title_url_vs_title_id", "columnInsertIndex": 33, "baseColumnName": "title_url_bis", "expression": "grel:if(value==cells['title_id'].value,'','erreur ? '+value)", "onError": "set-to-blank" }, { "op": "core/text-transform", "description": "Script syntaxique : champ obligatoirement vide", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "first_author", "expression": "grel:if(isBlank(value)!=true,value+' : doit être vide','')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : champ obligatoirement vide", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "date_monograph_published_print", "expression": "grel:if(isBlank(value)!=true,value+' : doit être vide','')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : champ obligatoirement vide", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "date_monograph_published_online", "expression": "grel:if(isBlank(value)!=true,value+' : doit être vide','')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : champ obligatoirement vide", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "monograph_volume", "expression": "grel:if(isBlank(value)!=true,value+' : doit être vide','')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : champ obligatoirement vide", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "monograph_edition", "expression": "grel:if(isBlank(value)!=true,value+' : doit être vide','')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : champ obligatoirement vide", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "first_editor", "expression": "grel:if(isBlank(value)!=true,value+' : doit être vide','')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : champ obligatoirement vide", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "parent_publication_title_id", "expression": "grel:if(isBlank(value)!=true,value+' : doit être vide','')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : peut être vide ou contient strictement : P ou R + 1 à 9999 + Y ou M ou D", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "embargo_info", "expression": "grel:if(isBlank(value),value,if(isNotNull(value.match(/[PR]\\d{1,4}[YMD]/)),'',value+': format incorrect'))", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : contient obligatoirement « fulltext », « selected articles » ou abstract", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "coverage_depth", "expression": "grel:if(isNotNull(value.match(/fulltext|selected articles|abstracts/)),'',value+' : format incorrect')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : ne peut pas être vide", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "publisher_name", "expression": "grel:if(isBlank(value)!=false,'doit être renseigné',value)", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : contient obligatoirement « serial »", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "publication_type", "expression": "grel:if(isNotNull(value.match(/serial/)),value,value+' : format incorrect')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : contient obligatoirement P ou F", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "access_type", "expression": "grel:if(isNotNull(value.match(/[PF]/)),value,value+' : format incorrect')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/column-addition", "description": "Script sémantique : création d'une nouvelle colonne, qui récupère la valeur du date_first_issue_online et lui donne le format Number", "engineConfig": { "facets": [], "mode": "row-based" }, "newColumnName": "year_first_issue", "columnInsertIndex": 34, "baseColumnName": "date_first_issue_online", "expression": "grel:value.split(\"-\")[0].toNumber()", "onError": "set-to-blank" }, { "op": "core/column-addition", "description": "Script sémantique : création d'une nouvelle colonne, qui récupère la valeur du date_last_issue_online et lui donne le format Number", "engineConfig": { "facets": [], "mode": "row-based" }, "newColumnName": "last_year_issue", "columnInsertIndex": 35, "baseColumnName": "date_last_issue_online", "expression": "grel:value.split(\"-\")[0].toNumber()", "onError": "set-to-blank" }, { "op": "core/column-addition-by-fetching-urls", "description": "Script sémantique : indique quel webservice (issnbacon) interroger pour la récupération des informations de référence dans le SUDOC", "engineConfig": { "facets": [], "mode": "row-based" }, "newColumnName": "sudoc_print_identifier", "columnInsertIndex": 36, "baseColumnName": "print_identifier", "urlExpression": "grel:'https://bacon.abes.fr/issnbacon/'+value+'.json'", "onError": "set-to-blank", "delay": 10 }, { "op": "core/column-addition", "description": "Script sémantique : indiquer, le cas échéant, l'écart entre le type de média donné par le SUDOC et le type d'identifiant (en l'occurrence papier)", "engineConfig": { "facets": [], "mode": "row-based" }, "newColumnName": "erreur_print_media", "columnInsertIndex": 37, "baseColumnName": "sudoc_print_identifier", "expression": "grel:if(value!=null+isNonBlank(cells[\"print_identifier\"].value),(if(value.parseJson()[\"sudoc\"][\"ppn\"][\"media\"]!=\"a\",cells[\"print_identifier\"].value+\" n'est pas un imprime\",forEach(value.parseJson().sudoc,v,[v.ppn.media,v.ppn.content].join(':')).join(' '))),'')", "onError": "set-to-blank" }, { "op": "core/column-addition", "description": "Script sémantique : récupérer les informations associées au webservice issnbacon pour la date de début de couverture", "engineConfig": { "facets": [], "mode": "row-based" }, "newColumnName": "sudoc_startdate", "columnInsertIndex": 38, "baseColumnName": "sudoc_print_identifier", "expression": "grel:value.parseJson()[\"sudoc\"][\"ppn\"][\"startdate\"]", "onError": "set-to-blank" }, { "op": "core/column-addition", "description": "Script sémantique : renvoie le ppn de la notice si la date SUDOC est plus récente que la date de début de couverture, indice d'une métarevue non déployée", "engineConfig": { "facets": [], "mode": "row-based" }, "newColumnName": "erreur_print_date", "columnInsertIndex": 39, "baseColumnName": "year_first_issue", "expression": "grel:if(value<cells[\"sudoc_startdate\"].value, cells[\"sudoc_print_identifier\"].value.parseJson()[\"sudoc\"][\"ppn\"][\"content\"],\"\")", "onError": "set-to-blank" }, { "op": "core/column-addition", "description": "Script sémantique : si la colonne erreur_print_date contient un élément, rappel des dates : date SUDOC > date_first_issue_online", "engineConfig": { "facets": [], "mode": "row-based" }, "newColumnName": "date_sudoc>date_first", "columnInsertIndex": 40, "baseColumnName": "erreur_print_date", "expression": "grel:if(isBlank(value),'',cells[\"sudoc_print_identifier\"].value.parseJson()[\"sudoc\"][\"ppn\"][\"startdate\"]+' > '+cells[\"date_first_issue_online\"].value)", "onError": "set-to-blank" }, { "op": "core/column-addition-by-fetching-urls", "description": "Script sémantique : indique quel webservice (issnbacon) interroger pour la récupération des informations de référence dans le SUDOC, pour le online_identifier", "engineConfig": { "facets": [], "mode": "row-based" }, "newColumnName": "sudoc_online_identifier", "columnInsertIndex": 41, "baseColumnName": "online_identifier", "urlExpression": "grel:'https://bacon.abes.fr/issnbacon/'+value+'.json'", "onError": "set-to-blank", "delay": 10 }, { "op": "core/column-addition", "description": "Script sémantique : indiquer, le cas échéant, l'écart entre le type de média donné par le SUDOC et le type d'identifiant (en l'occurrence électronique)", "engineConfig": { "facets": [], "mode": "row-based" }, "newColumnName": "erreur_online_media", "columnInsertIndex": 42, "baseColumnName": "sudoc_online_identifier", "expression": "grel:if(value!=null+isNonBlank(cells[\"online_identifier\"].value),(if(value.parseJson()[\"sudoc\"][\"ppn\"][\"media\"]!=\"l\",cells[\"online_identifier\"].value+\" n'est pas un imprime\",forEach(value.parseJson().sudoc,v,[v.ppn.media,v.ppn.content].join(':')).join(' '))),'')", "onError": "set-to-blank" }, { "op": "core/column-removal", "description": "Script sémantique : supprime la colonne year_first_issue", "columnName": "year_first_issue" }, { "op": "core/column-removal", "description": "Script sémantique : supprime la colonne last_year_issue", "columnName": "last_year_issue" }, { "op": "core/column-removal", "description": "Script sémantique : supprime la colonne sudoc_startdate", "columnName": "sudoc_startdate" }, { "op": "core/text-transform", "description": "Script syntaxique : p-ISSN non conforme", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "print_identifier", "expression": "grel:forNonBlank(value,v,if(v.match(/^\\d{4}-\\d{3}(\\d|X)$/)!=null,value,value+\" n'est pas un ISSN conforme\"),'')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : e-ISSN non conforme", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "online_identifier", "expression": "grel:forNonBlank(value,v,if(v.match(/^\\d{4}-\\d{3}(\\d|X)$/)!=null,value,value+\" n'est pas un ISSN conforme\"),'')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : vérifie qu'un titre dispose au moins d'un ISSN", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "print_identifier", "expression": "grel:if(isBlank(value),(if(isBlank(cells[\"online_identifier\"].value),'aucun ISSN',value)),value)", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : aucun p-ISSN mais un e-ISSN : s'agit-il d'une revue numérique native ?", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "print_identifier", "expression": "grel:if(isBlank(value)==true,'revue numerique native ?',value)", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : tous les eISSN doivent être renseignés, y compris si la revue a été numérisée (demande à faire auprès du CIEPS)", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "online_identifier", "expression": "grel:if(isBlank(value)==true,'ISSN obligatoire',value)", "onError": "keep-original", "repeat": false, "repeatCount": 10 } ]

Celle pour l’évaluation des livres électroniques :

[ { "op": "core/text-transform", "description": "Script syntaxique : pour chaque ligne, test l'ensemble des champs. Si une ligne ne contient que des champs vides, alors la mention « ligne vide » apparaît dans le champ publication_title de la ligne concernée", "engineConfig": { "mode": "row-based", "facets": [] }, "columnName": "publication_title", "expression": "grel:if(cells.publication_title.value.length()==0,(if(cells.print_identifier.value.length()==0,(if(cells .online_identifier.value.length()==0,(if(cells.date_first_issue_online.value.length()==0,(if(cells.num_first_vol_online.value.length()==0,(if(cells.num_first_issue_online.value.length()==0,(if(cells.date_last_issue_online.value.length()==0,(if(cells.num_last_vol_online.value.length()==0,(if(cells.num_last_issue_online.value.length()==0,(if(cells.title_url.value.length()==0,(if(cells .first_author.value.length()==0,(if(cells.title_id.value.length()==0,(if(cells.embargo_info.value.length()==0,(if(cells.coverage_depth.value.length()==0,(if(cells.notes.value.length()==0,(if(cells.publisher_name.value.length()==0,(if(cells.publication_type.value.length()==0,(if(cells.date_monograph_published_print.value.length()==0,(if(cells.date_monograph_published_online.value.length()==0,(if(cells.monograph_volume.value.length()==0,(if(cells.monograph_edition.value.length()==0,(if(cells.first_editor.value.length()==0,(if(cells.parent_publication_title_id.value.length()==0,(if(cells.preceding_publication_title_id.value.length()==0,(if(cells.access_type.value.length()==0,'ligne vide',value)),value)),value)),value)),value)),value)),value)),value)),value)),value)),value)),value)),value)),value)),value)),value)),value)),value)),value)),value)),value)),value)),value)),value)),value)", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Suppression des espaces en début et en fin de cellule", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "publication_title", "expression": "value.trim()", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Suppression des espaces en début et en fin de cellule", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "print_identifier", "expression": "value.trim()", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Suppression des espaces en début et en fin de cellule", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "online_identifier", "expression": "value.trim()", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Suppression des espaces en début et en fin de cellule", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "title_url", "expression": "value.trim()", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Suppression des espaces en début et en fin de cellule", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "first_author", "expression": "value.trim()", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Suppression des espaces en début et en fin de cellule", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "title_id", "expression": "value.trim()", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Suppression des espaces en début et en fin de cellule", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "coverage_depth", "expression": "value.trim()", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Suppression des espaces en début et en fin de cellule", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "publisher_name", "expression": "value.trim()", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Suppression des espaces en début et en fin de cellule", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "publication_type", "expression": "value.trim()", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Suppression des espaces en début et en fin de cellule", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "date_monograph_published_print", "expression": "value.trim()", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Suppression des espaces en début et en fin de cellule", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "date_monograph_published_online", "expression": "value.trim()", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Suppression des espaces en début et en fin de cellule", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "monograph_volume", "expression": "value.trim()", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Suppression des espaces en début et en fin de cellule", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "monograph_edition", "expression": "value.trim()", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Suppression des espaces en début et en fin de cellule", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "first_editor", "expression": "value.trim()", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Suppression des espaces en début et en fin de cellule", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "parent_publication_title_id", "expression": "value.trim()", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Suppression des espaces en début et en fin de cellule", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "access_type", "expression": "value.trim()", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Si plusieurs caractères d’espaces consécutifs, fusion en un seul", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "publication_title", "expression": "value.replace(/\\s+/,' ')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Si plusieurs caractères d’espaces consécutifs, fusion en un seul", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "print_identifier", "expression": "value.replace(/\\s+/,' ')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Si plusieurs caractères d’espaces consécutifs, fusion en un seul", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "online_identifier", "expression": "value.replace(/\\s+/,' ')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Si plusieurs caractères d’espaces consécutifs, fusion en un seul", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "title_url", "expression": "value.replace(/\\s+/,' ')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Si plusieurs caractères d’espaces consécutifs, fusion en un seul", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "first_author", "expression": "value.replace(/\\s+/,' ')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Si plusieurs caractères d’espaces consécutifs, fusion en un seul", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "title_id", "expression": "value.replace(/\\s+/,' ')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Si plusieurs caractères d’espaces consécutifs, fusion en un seul", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "coverage_depth", "expression": "value.replace(/\\s+/,' ')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Si plusieurs caractères d’espaces consécutifs, fusion en un seul", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "publisher_name", "expression": "value.replace(/\\s+/,' ')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Si plusieurs caractères d’espaces consécutifs, fusion en un seul", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "publication_type", "expression": "value.replace(/\\s+/,' ')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Si plusieurs caractères d’espaces consécutifs, fusion en un seul", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "date_monograph_published_print", "expression": "value.replace(/\\s+/,' ')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Si plusieurs caractères d’espaces consécutifs, fusion en un seul", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "date_monograph_published_online", "expression": "value.replace(/\\s+/,' ')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Si plusieurs caractères d’espaces consécutifs, fusion en un seul", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "monograph_volume", "expression": "value.replace(/\\s+/,' ')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Si plusieurs caractères d’espaces consécutifs, fusion en un seul", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "monograph_edition", "expression": "value.replace(/\\s+/,' ')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Si plusieurs caractères d’espaces consécutifs, fusion en un seul", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "first_editor", "expression": "value.replace(/\\s+/,' ')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Si plusieurs caractères d’espaces consécutifs, fusion en un seul", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "parent_publication_title_id", "expression": "value.replace(/\\s+/,' ')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : Si plusieurs caractères d’espaces consécutifs, fusion en un seul", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "access_type", "expression": "value.replace(/\\s+/,' ')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : suppression du caractère de retour à la ligne", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "publication_title", "expression": "grel:value.replace(/\\u000a/,'').replace(/\\u00A0/,'')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : suppression du caractère de retour à la ligne", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "print_identifier", "expression": "grel:value.replace(/\\u000a/,'').replace(/\\u00A0/,'')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : suppression du caractère de retour à la ligne", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "online_identifier", "expression": "grel:value.replace(/\\u000a/,'').replace(/\\u00A0/,'')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : suppression du caractère de retour à la ligne", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "title_url", "expression": "grel:value.replace(/\\u000a/,'').replace(/\\u00A0/,'')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : suppression du caractère de retour à la ligne", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "first_author", "expression": "grel:value.replace(/\\u000a/,'').replace(/\\u00A0/,'')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : suppression du caractère de retour à la ligne", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "title_id", "expression": "grel:value.replace(/\\u000a/,'').replace(/\\u00A0/,'')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : suppression du caractère de retour à la ligne", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "coverage_depth", "expression": "grel:value.replace(/\\u000a/,'').replace(/\\u00A0/,'')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : suppression du caractère de retour à la ligne", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "publisher_name", "expression": "grel:value.replace(/\\u000a/,'').replace(/\\u00A0/,'')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : suppression du caractère de retour à la ligne", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "publication_type", "expression": "grel:value.replace(/\\u000a/,'').replace(/\\u00A0/,'')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : suppression du caractère de retour à la ligne", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "date_monograph_published_print", "expression": "grel:value.replace(/\\u000a/,'').replace(/\\u00A0/,'')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : suppression du caractère de retour à la ligne", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "date_monograph_published_online", "expression": "grel:value.replace(/\\u000a/,'').replace(/\\u00A0/,'')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : suppression du caractère de retour à la ligne", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "monograph_volume", "expression": "grel:value.replace(/\\u000a/,'').replace(/\\u00A0/,'')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : suppression du caractère de retour à la ligne", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "monograph_edition", "expression": "grel:value.replace(/\\u000a/,'').replace(/\\u00A0/,'')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : suppression du caractère de retour à la ligne", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "first_editor", "expression": "grel:value.replace(/\\u000a/,'').replace(/\\u00A0/,'')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : suppression du caractère de retour à la ligne", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "parent_publication_title_id", "expression": "grel:value.replace(/\\u000a/,'').replace(/\\u00A0/,'')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "SScript syntaxique : suppression du caractère de retour à la ligne", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "access_type", "expression": "grel:value.replace(/\\u000a/,'').replace(/\\u00A0/,'')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : suppression du caractère d'espace insécable", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "publication_title", "expression": "grel:value.replace(/\\u000a/,'').replace(/\\u00A0/,'')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : suppression du caractère d'espace insécable", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "print_identifier", "expression": "grel:value.replace(/\\u000a/,'').replace(/\\u00A0/,'')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : suppression du caractère d'espace insécable", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "online_identifier", "expression": "grel:value.replace(/\\u000a/,'').replace(/\\u00A0/,'')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : suppression du caractère d'espace insécable", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "title_url", "expression": "grel:value.replace(/\\u000a/,'').replace(/\\u00A0/,'')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : suppression du caractère d'espace insécable", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "first_author", "expression": "grel:value.replace(/\\u000a/,'').replace(/\\u00A0/,'')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : suppression du caractère d'espace insécable", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "title_id", "expression": "grel:value.replace(/\\u000a/,'').replace(/\\u00A0/,'')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : suppression du caractère d'espace insécable", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "coverage_depth", "expression": "grel:value.replace(/\\u000a/,'').replace(/\\u00A0/,'')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : suppression du caractère d'espace insécable", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "publisher_name", "expression": "grel:value.replace(/\\u000a/,'').replace(/\\u00A0/,'')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : suppression du caractère d'espace insécable", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "publication_type", "expression": "grel:value.replace(/\\u000a/,'').replace(/\\u00A0/,'')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : suppression du caractère d'espace insécable", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "date_monograph_published_print", "expression": "grel:value.replace(/\\u000a/,'').replace(/\\u00A0/,'')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : suppression du caractère d'espace insécable", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "date_monograph_published_online", "expression": "grel:value.replace(/\\u000a/,'').replace(/\\u00A0/,'')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : suppression du caractère d'espace insécable", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "monograph_volume", "expression": "grel:value.replace(/\\u000a/,'').replace(/\\u00A0/,'')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : suppression du caractère d'espace insécable", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "monograph_edition", "expression": "grel:value.replace(/\\u000a/,'').replace(/\\u00A0/,'')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : suppression du caractère d'espace insécable", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "first_editor", "expression": "grel:value.replace(/\\u000a/,'').replace(/\\u00A0/,'')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : suppression du caractère d'espace insécable", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "parent_publication_title_id", "expression": "grel:value.replace(/\\u000a/,'').replace(/\\u00A0/,'')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : suppression du caractère d'espace insécable", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "access_type", "expression": "grel:value.replace(/\\u000a/,'').replace(/\\u00A0/,'')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/column-addition-by-fetching-urls", "description": "Script sémantique : création d'une colonne contenant les informations du Sudoc à partir du online_identifier grâce au webservice 'isbnbacon'", "engineConfig": { "mode": "row-based", "facets": [] }, "newColumnName": "E-ISBN_sudoc_json", "columnInsertIndex": 25, "baseColumnName": "online_identifier", "urlExpression": "grel:if(value!=null,'https://bacon.abes.fr/isbnbacon/'+value+'.json','')", "onError": "set-to-blank", "delay": 10 }, { "op": "core/column-addition", "description": "Script sémantique : création d'une colonne contenant le publication_title nettoyé", "engineConfig": { "facets": [], "mode": "row-based" }, "newColumnName": "pub_title_clean", "columnInsertIndex": 25, "baseColumnName": "publication_title", "expression": "grel:toLowercase(trim(value.replace(/\\u00A0/, ' '))).replace(/\\p{Punct}/,' ').replace(/\\u2019/, ' ').replace(/\\u200E/, ' ').replace(/\\s+/, ' ')", "onError": "set-to-blank" }, { "op": "core/text-transform", "description": "Script syntaxique : remplace le x minuscule par un X majuscule pour les p-ISBN", "engineConfig": { "mode": "row-based", "facets": [] }, "columnName": "print_identifier", "expression": "grel:value.replace(\"x\",\"X\")", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : remplace le x minuscule par un X majuscule pour les e-ISBN", "engineConfig": { "mode": "row-based", "facets": [] }, "columnName": "online_identifier", "expression": "grel:value.replace(\"x\",\"X\")", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/column-addition", "description": "Script sémantique : création d'une colonne contenant le titre sudoc", "engineConfig": { "facets": [], "mode": "row-based" }, "newColumnName": "E-sudoc_title", "columnInsertIndex": 25, "baseColumnName": "E-ISBN_sudoc_json", "expression": "grel:value.parseJson()['sudoc']['ppn']['title']", "onError": "set-to-blank" }, { "op": "core/column-addition", "description": "Script sémantique : création d'une colonne contenant le E-sudoc_title nettoyé", "engineConfig": { "facets": [], "mode": "row-based" }, "newColumnName": "E-sudoc_title_clean", "columnInsertIndex": 25, "baseColumnName": "E-sudoc_title", "expression": "grel:toLowercase(trim(value.replace(/\\u00A0/, ' '))).replace(/\\p{Punct}/,' ').replace(/\\u2019/, ' ').replace(/\\u200E/, ' ').replace(/\\s+/, ' ')", "onError": "set-to-blank" }, { "op": "core/column-addition", "description": "Script sémantique : préparation du calcul de distance", "engineConfig": { "facets": [], "mode": "row-based" }, "newColumnName": "E-min_clean_title", "columnInsertIndex": 25, "baseColumnName": "pub_title_clean", "expression": "grel:min(length(value),length(cells['E-sudoc_title_clean'].value))", "onError": "set-to-blank" }, { "op": "core/column-addition", "description": "Script sémantique : résultat du calcul de distance", "engineConfig": { "facets": [], "mode": "row-based" }, "newColumnName": "E-dist_title", "columnInsertIndex": 25, "baseColumnName": "E-min_clean_title", "expression": "grel:jarowinkler(stripAccents(substring(cells['pub_title_clean'].value,0,value)),stripAccents(substring(cells['E-sudoc_title_clean'].value,0,value)))", "onError": "set-to-blank" }, { "op": "core/column-removal", "description": "Suppression d'une colonne devenue inutile", "columnName": "E-sudoc_title" }, { "op": "core/column-removal", "description": "Suppression d'une colonne devenue inutile", "columnName": "E-min_clean_title" }, { "op": "core/column-addition", "description": "Script sémantique : création d'une colonne contenant la valeur 'NOK' si l'ISBN n'est pas électronique", "engineConfig": { "mode": "row-based", "facets": [] }, "newColumnName": "error_online_media", "columnInsertIndex": 25, "baseColumnName": "E-ISBN_sudoc_json", "expression": "grel:if(value!=null,if(value.parseJson()['sudoc']['ppn']['media']!='l','NOK',''),'')", "onError": "set-to-blank" }, { "op": "core/column-addition", "description": "Gestion des ppn multiples", "engineConfig": { "mode": "row-based", "facets": [] }, "newColumnName": "E-ISBN_multi-ppn", "columnInsertIndex": 25, "baseColumnName": "E-ISBN_sudoc_json", "expression": "grel:forEach(value.parseJson().sudoc,v,[v.ppn.media,v.ppn.content].join(':')).join(' ')", "onError": "set-to-blank" }, { "op": "core/column-addition", "description": "Test sur le type de média", "engineConfig": { "mode": "row-based", "facets": [] }, "newColumnName": "E-ISBN_multi-ppn_final", "columnInsertIndex": 25, "baseColumnName": "E-ISBN_multi-ppn", "expression": "grel:if(isBlank(value)==false,if(value.match(/.*l.*/)==null,value,''),'')", "onError": "set-to-blank" }, { "op": "core/column-split", "description": "Séparer le contenu de la colonne P-ISBN_multi_ppn_final en autant de colonnes qu'il y a de ppn", "engineConfig": { "mode": "row-based", "facets": [] }, "columnName": "E-ISBN_multi-ppn_final", "guessCellType": true, "removeOriginalColumn": true, "mode": "separator", "separator": " ", "regex": false, "maxColumns": 0 }, { "op": "core/column-addition", "description": "Script sémantique : création d'une colonne contenant le first_author nettoyé", "engineConfig": { "facets": [], "mode": "row-based" }, "newColumnName": "first_author_clean", "columnInsertIndex": 25, "baseColumnName": "first_author", "expression": "grel:toLowercase(trim(value.replace(/\\u00A0/, ' '))).replace(/\\p{Punct}/,' ').replace(/\\u2019/, ' ').replace(/\\u200E/, ' ').replace(/\\s+/, ' ')", "onError": "set-to-blank" }, { "op": "core/column-addition", "description": "Script sémantique : extraire l'auteur pour comparaison", "engineConfig": { "facets": [], "mode": "row-based" }, "newColumnName": "E-sudoc_author", "columnInsertIndex": 25, "baseColumnName": "E-ISBN_sudoc_json", "expression": "grel:value.parseJson()['sudoc']['ppn']['marcautrel']", "onError": "set-to-blank" }, { "op": "core/column-addition", "description": "Script sémantique : création d'une colonne contenant l'auteur sudoc nettoyé", "engineConfig": { "facets": [], "mode": "row-based" }, "newColumnName": "E-sudoc_author_clean", "columnInsertIndex": 25, "baseColumnName": "E-sudoc_author", "expression": "grel:toLowercase(trim(value.replace(/\\u00A0/, ' '))).replace(/\\p{Punct}/,' ').replace(/\\u2019/, ' ').replace(/\\u200E/, ' ').replace(/\\s+/, ' ')", "onError": "set-to-blank" }, { "op": "core/column-addition", "description": "Script sémantique : préparation du calcul de distance", "engineConfig": { "facets": [], "mode": "row-based" }, "newColumnName": "E-min_clean_author", "columnInsertIndex": 25, "baseColumnName": "first_author_clean", "expression": "grel:min(length(value),length(cells['E-sudoc_author_clean'].value))", "onError": "set-to-blank" }, { "op": "core/column-addition", "description": "Script sémantique : résultat du calcul de distance", "engineConfig": { "facets": [], "mode": "row-based" }, "newColumnName": "E-dist_author", "columnInsertIndex": 25, "baseColumnName": "E-min_clean_author", "expression": "grel:if(value!=0,(jarowinkler(stripAccents(substring(cells['first_author_clean'].value,0,value)),stripAccents(substring(cells['E-sudoc_author_clean'].value,0,value)))),'')", "onError": "set-to-blank" }, { "op": "core/column-removal", "description": "Suppression d'une colonne devenue inutile", "columnName": "E-sudoc_author" }, { "op": "core/column-removal", "description": "Suppression d'une colonne devenue inutile", "columnName": "E-min_clean_author" }, { "op": "core/column-addition-by-fetching-urls", "description": "Script sémantique : création d'une colonne contenant les informations du Sudoc à partir du print_identifier grâce au webservice 'isbnbacon'", "engineConfig": { "mode": "row-based", "facets": [] }, "newColumnName": "P-ISBN_sudoc_json", "columnInsertIndex": 25, "baseColumnName": "print_identifier", "urlExpression": "grel:if(value!=null,'https://bacon.abes.fr/isbnbacon/'+value+'.json','')", "onError": "set-to-blank", "delay": 10 }, { "op": "core/column-addition", "description": "Script sémantique : création d'une colonne contenant le titre sudoc", "engineConfig": { "facets": [], "mode": "row-based" }, "newColumnName": "P-sudoc_title", "columnInsertIndex": 25, "baseColumnName": "P-ISBN_sudoc_json", "expression": "grel:if(cells['E-ISBN_sudoc_json']==null,value.parseJson()['sudoc']['ppn']['title'],'')", "onError": "set-to-blank" }, { "op": "core/column-addition", "description": "Script sémantique : création, en 16ème position, d'une colonne contenant le P-sudoc_title nettoyé", "engineConfig": { "facets": [], "mode": "row-based" }, "newColumnName": "P-sudoc_title_clean", "columnInsertIndex": 25, "baseColumnName": "P-sudoc_title", "expression": "grel:toLowercase(trim(value.replace(/\\u00A0/, ' '))).replace(/\\p{Punct}/,' ').replace(/\\u2019/, ' ').replace(/\\u200E/, ' ').replace(/\\s+/, ' ')", "onError": "set-to-blank" }, { "op": "core/column-addition", "description": "Script sémantique : préparation, en 17ème position, du calcul de distance", "engineConfig": { "facets": [], "mode": "row-based" }, "newColumnName": "P-min_clean_title", "columnInsertIndex": 25, "baseColumnName": "pub_title_clean", "expression": "grel:min(length(value),length(cells['P-sudoc_title_clean'].value))", "onError": "set-to-blank" }, { "op": "core/column-addition", "description": "Script sémantique : résultat du calcul de distance, en 18ème position", "engineConfig": { "facets": [], "mode": "row-based" }, "newColumnName": "P-dist_title", "columnInsertIndex": 25, "baseColumnName": "P-min_clean_title", "expression": "grel:if(cells['P-min_clean_title'].value!=0,jarowinkler(stripAccents(substring(cells['pub_title_clean'].value,0,value)),stripAccents(substring(cells['P-sudoc_title_clean'].value,0,value))),'')", "onError": "set-to-blank" }, { "op": "core/column-removal", "description": "Suppression d'une colonne devenue inutile", "columnName": "P-sudoc_title" }, { "op": "core/column-removal", "description": "Suppression d'une colonne devenue inutile", "columnName": "P-min_clean_title" }, { "op": "core/column-addition", "description": "Script sémantique : création d'une colonne contenant la valeur 'NOK' si l'ISBN n'est pas papier", "engineConfig": { "mode": "row-based", "facets": [] }, "newColumnName": "erreur_print_media", "columnInsertIndex": 25, "baseColumnName": "P-ISBN_sudoc_json", "expression": "grel:if(value!=null,if(value.parseJson()['sudoc']['ppn']['media']!='a','NOK',''),'')", "onError": "set-to-blank" }, { "op": "core/column-addition", "description": "Gestion des ppn multiples", "engineConfig": { "mode": "row-based", "facets": [] }, "newColumnName": "P-ISBN_multi-ppn", "columnInsertIndex": 25, "baseColumnName": "P-ISBN_sudoc_json", "expression": "grel:forEach(value.parseJson().sudoc,v,[v.ppn.media,v.ppn.content].join(':')).join(' ')", "onError": "set-to-blank" }, { "op": "core/column-addition", "description": "Test sur le type de média", "engineConfig": { "mode": "row-based", "facets": [] }, "newColumnName": "P-ISBN_multi-ppn_final", "columnInsertIndex": 25, "baseColumnName": "P-ISBN_multi-ppn", "expression": "grel:if(isBlank(value)==false,if(value.match(/.*a.*/)==null,value,''),'')", "onError": "set-to-blank" }, { "op": "core/column-split", "description": "Séparer le contenu de la colonne P-ISBN_multi_ppn_final en autant de colonnes qu'il y a de ppn", "engineConfig": { "mode": "row-based", "facets": [] }, "columnName": "P-ISBN_multi-ppn_final", "guessCellType": true, "removeOriginalColumn": true, "mode": "separator", "separator": " ", "regex": false, "maxColumns": 0 }, { "op": "core/column-addition", "description": "Script sémantique : extraire l'auteur du json pour comparaison", "engineConfig": { "facets": [], "mode": "row-based" }, "newColumnName": "P-sudoc_author", "columnInsertIndex": 25, "baseColumnName": "P-ISBN_sudoc_json", "expression": "grel:if(cells['E-sudoc_author']==null,value.parseJson()['sudoc']['ppn']['marcautrel'],'')", "onError": "set-to-blank" }, { "op": "core/column-addition", "description": "Script sémantique : création d'une colonne contenant l'auteur sudoc nettoyé", "engineConfig": { "facets": [], "mode": "row-based" }, "newColumnName": "P-sudoc_author_clean", "columnInsertIndex": 25, "baseColumnName": "P-sudoc_author", "expression": "grel:toLowercase(trim(value.replace(/\\u00A0/, ' '))).replace(/\\p{Punct}/,' ').replace(/\\u2019/, ' ').replace(/\\u200E/, ' ').replace(/\\s+/, ' ')", "onError": "set-to-blank" }, { "op": "core/column-addition", "description": "Script sémantique : préparation du calcul de distance", "engineConfig": { "facets": [], "mode": "row-based" }, "newColumnName": "P-min_clean_author", "columnInsertIndex": 25, "baseColumnName": "first_author_clean", "expression": "grel:min(length(value),length(cells['P-sudoc_author_clean'].value))", "onError": "set-to-blank" }, { "op": "core/column-addition", "description": "Script sémantique : résultat du calcul de distance", "engineConfig": { "facets": [], "mode": "row-based" }, "newColumnName": "P-dist_author", "columnInsertIndex": 25, "baseColumnName": "P-min_clean_author", "expression": "grel:if(value!=0,(jarowinkler(stripAccents(substring(cells['first_author_clean'].value,0,value)),stripAccents(substring(cells['P-sudoc_author_clean'].value,0,value)))),'')", "onError": "set-to-blank" }, { "op": "core/column-removal", "description": "Suppression d'une colonne devenue inutile", "columnName": "P-sudoc_author" }, { "op": "core/column-removal", "description": "Suppression d'une colonne devenue inutile", "columnName": "P-min_clean_author" }, { "op": "core/text-transform", "description": "Script syntaxique : ne conserve que les quatre premiers caractères contenus dans le date_monograph_published_online, à condition qu'ils respectent le format YYYY. Sinon, informe d'une erreur de format", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "date_monograph_published_online", "expression": "grel:if(value.match(/.*(\\d{4}).*/)[0]==null,value+' : format incorrect',value.match(/.*(\\d{4}).*/)[0])", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : ne conserve que les quatre premiers caractères contenus dans le date_last_issue_online, à condition qu'ils respectent le format YYYY. Sinon, informe d'une erreur de format", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "date_monograph_published_print", "expression": "grel:if(isNonBlank(value),if(value.match(/.*(\\d{4}).*/)[0]==null,value+' : format incorrect',value.match(/.*(\\d{4}).*/)[0]),value)", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/column-addition", "description": "Script sémantique : extraire la date pour comparaison", "engineConfig": { "facets": [], "mode": "row-based" }, "newColumnName": "E-sudoc_date", "columnInsertIndex": 19, "baseColumnName": "E-ISBN_sudoc_json", "expression": "grel:toString(value.parseJson()['sudoc']['ppn']['pubdate'])", "onError": "set-to-blank" }, { "op": "core/column-addition", "description": "Script sémantique : crée une nouvelle colonne, résultat de la comparaison sur les dates de l'électronique", "engineConfig": { "facets": [], "mode": "row-based" }, "newColumnName": "E-sudoc_date_check", "columnInsertIndex": 20, "baseColumnName": "E-sudoc_date", "expression": "grel:if(isNonBlank(cells['date_monograph_published_online'].value),(if(contains(cells['date_monograph_published_online'].value,'format incorrect'),'',(if(value!=cells['date_monograph_published_online'].value,value,'')))),'')", "onError": "set-to-blank" }, { "op": "core/column-removal", "description": "Suppression d'une colonne devenue inutile", "columnName": "E-sudoc_date" }, { "op": "core/column-addition", "description": "Script sémantique : extraire la date pour comparaison", "engineConfig": { "facets": [], "mode": "row-based" }, "newColumnName": "P-sudoc_date", "columnInsertIndex": 18, "baseColumnName": "P-ISBN_sudoc_json", "expression": "grel:toString(value.parseJson()['sudoc']['ppn']['pubdate'])", "onError": "set-to-blank" }, { "op": "core/column-addition", "description": "Crée une nouvelle colonne, résultat de la comparaison sur les dates du papier", "engineConfig": { "facets": [], "mode": "row-based" }, "newColumnName": "P-sudoc_date_check", "columnInsertIndex": 19, "baseColumnName": "P-sudoc_date", "expression": "grel:if(isNonBlank(cells['date_monograph_published_print'].value),(if(contains(cells['date_monograph_published_print'].value,'format incorrect'),'',(if(value!=cells['date_monograph_published_print'].value,value,'')))),'')", "onError": "set-to-blank" }, { "op": "core/column-removal", "description": "Suppression d'une colonne devenue inutile", "columnName": "P-sudoc_date" }, { "op": "core/column-addition", "description": "Script syntaxique : doublons sur le publication_title", "engineConfig": { "mode": "row-based", "facets": [] }, "newColumnName": "publication_title_doublon", "columnInsertIndex": 27, "baseColumnName": "publication_title", "expression": "grel:forNonBlank(value,v,facetCount(v,'value','publication_title'),'')", "onError": "set-to-blank" }, { "op": "core/text-transform", "description": "Script syntaxique : vérifie qu'aucun champ du publication_title ne soit vide", "engineConfig": { "mode": "row-based", "facets": [] }, "columnName": "publication_title", "expression": "grel:if(isBlank(value)==true,'titre manquant',value)", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/column-addition", "description": "Script syntaxique : doublons sur le print_identifier", "engineConfig": { "mode": "row-based", "facets": [] }, "newColumnName": "print_identifier_doublon", "columnInsertIndex": 28, "baseColumnName": "print_identifier", "expression": "grel:forNonBlank(value,v,facetCount(v,'value','print_identifier'),'')", "onError": "set-to-blank" }, { "op": "core/column-addition", "description": "Script syntaxique : doublons sur le online_identifier", "engineConfig": { "mode": "row-based", "facets": [] }, "newColumnName": "online_identifier_doublon", "columnInsertIndex": 29, "baseColumnName": "online_identifier", "expression": "grel:forNonBlank(value,v,facetCount(v,'value','online_identifier'),'')", "onError": "set-to-blank" }, { "op": "core/text-transform", "description": "Script syntaxique : champ obligatoirement vide", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "date_first_issue_online", "expression": "grel:if(isBlank(value)!=true,value+' : doit être vide',value)", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : champ obligatoirement vide", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "num_first_vol_online", "expression": "grel:if(isBlank(value)!=true,value+' : doit être vide',value)", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : champ obligatoirement vide", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "num_first_issue_online", "expression": "grel:if(isBlank(value)!=true,value+' : doit être vide',value)", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : champ obligatoirement vide", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "date_last_issue_online", "expression": "grel:if(isBlank(value)!=true,value+' : doit être vide',value)", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : champ obligatoirement vide", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "num_last_vol_online", "expression": "grel:if(isBlank(value)!=true,value+' : doit être vide',value)", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : champ obligatoirement vide", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "num_last_issue_online", "expression": "grel:if(isBlank(value)!=true,value+' : doit être vide',value)", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : aucun champ vide", "engineConfig": { "mode": "row-based", "facets": [] }, "columnName": "title_url", "expression": "grel:if(isBlank(value)==true,'URL obligatoire',value)", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/column-addition", "description": "Script syntaxique : la partie fixe du title_url mise de côté, la partie évolutive restante correspond-elle au title_id ? Test I ATTENTION : A ACTUALISER AVANT D'UTILISER LE SCRIPT : remplacer [X] par la partie fixe de l'URL", "engineConfig": { "facets": [], "mode": "row-based" }, "newColumnName": "title_url_bis", "columnInsertIndex": 10, "baseColumnName": "title_url", "expression": "grel:value.replace('[X]','')", "onError": "set-to-blank" }, { "op": "core/text-transform", "description": "Script syntaxique : la partie fixe du title_url mise de côté, la partie évolutive restante correspond-elle au title_id ? Test II", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "title_id", "expression": "grel:if(cells[\"title_url_bis\"].value==cells[\"title_id\"].value,value,\"erreur ? \"+value)", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : champ obligatoirement vide", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "embargo_info", "expression": "grel:if(isBlank(value)!=true,value+' : doit être vide',value)", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : contient obligatoirement « fulltext », « selected articles » ou abstract", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "coverage_depth", "expression": "grel:if(isNotNull(value.match(/fulltext|selected articles|abstract/)),value,value+' format incorrect')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : ne peut pas être vide", "engineConfig": { "mode": "row-based", "facets": [] }, "columnName": "publisher_name", "expression": "grel:if(isBlank(value)!=false,'doit être renseigné',value)", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : contient obligatoirement « monograph »", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "publication_type", "expression": "grel:if(isNotNull(value.match(/monograph/)),value,value+' : format incorrect')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : le contenu du monograph_volume, lorsqu'il n'est pas numérique, suit-il une cohérence ?", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "monograph_volume", "expression": "grel:if(isNotNull(value.match(/[0-9]*/)),value,'cohérent ? '+value)", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : le contenu du monograph_edition, lorsqu'il n'est pas numérique, suit-il une cohérence ?", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "monograph_edition", "expression": "grel:if(isNotNull(value.match(/[0-9]*/)),value,'cohérent ? '+value)", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : le contenu du first_author est-il une suite de lettres, majuscules ou minuscules, formant un mot unique ?", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "first_author", "expression": "grel:if(isNull(value.match(/[a-zA-Z]*/))==true,value+ ' : erreur ?',value)", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : champ obligatoirement vide", "engineConfig": { "mode": "row-based", "facets": [] }, "columnName": "preceding_publication_title_id", "expression": "grel:if(isBlank(value)!=true,value+' : doit être vide',value)", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : contient obligatoirement P ou F", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "access_type", "expression": "grel:if(isNotNull(value.match(/[PF]/)),value,value+' : format incorrect')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : print_identifier et online_identifier ne peuvent être vides à la fois, TEST 1", "engineConfig": { "mode": "row-based", "facets": [] }, "columnName": "print_identifier", "expression": "grel:if(cells.print_identifier.value.length()==0,(if(cells.online_identifier.value.length()==0,'manque ISBN',value)),value)", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : print_identifier et online_identifier ne peuvent être vides à la fois, TEST 2", "engineConfig": { "mode": "row-based", "facets": [] }, "columnName": "online_identifier", "expression": "grel:if(cells.print_identifier.value=='manque ISBN',(if(cells.online_identifier.value.length()==0,'manque ISBN',value)),value)", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : aucun e-ISBN mais un p-ISBN : s'agit-il d'un e-book numérique natif ?", "engineConfig": { "mode": "row-based", "facets": [] }, "columnName": "print_identifier", "expression": "grel:if(isBlank(value)==true,'e-book natif numérique ?',value)", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : tous les eISBN doivent être renseignés, y compris si le livre a été numérisé (demande à faire auprès du CIEPS)", "engineConfig": { "mode": "row-based", "facets": [] }, "columnName": "online_identifier", "expression": "grel:if(isBlank(value)==true,'ISBN obligatoire',value)", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : p-ISBN non conforme I", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "print_identifier", "expression": "grel:value.replace('-','')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : p-ISBN non conforme II", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "print_identifier", "expression": "grel:if(value.match(/^(97(8|9))?\\d{9}(\\d|X)$/)==null,value+\" n'est pas un isbn conforme\",value)", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : e-ISBN non conforme I", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "online_identifier", "expression": "grel:value.replace('-','')", "onError": "keep-original", "repeat": false, "repeatCount": 10 }, { "op": "core/text-transform", "description": "Script syntaxique : e-ISBN non conforme II", "engineConfig": { "facets": [], "mode": "row-based" }, "columnName": "online_identifier", "expression": "grel:if(value.match(/^(97(8|9))?\\d{9}(\\d|X)$/)==null,value+\" n'est pas un isbn conforme\",value)", "onError": "keep-original", "repeat": false, "repeatCount": 10 } ]

Avant d’appliquer ces scripts dans OpenRefine et après avoir déposé les fichiers sur un serveur dédié, cinq critères syntaxiques sont préalablement vérifiés :

  • la syntaxe du nom de fichier [6.5.1] (la numérotation entre crochets renvoie à la documentation KBART Phase II)
  • la présence de vingt-cinq colonnes, correctement nommées et ordonnées [6.4.4, 6.4.5]
  • l’obligation de renseigner certaines colonnes, d’en laisser d’autres vides, selon le type de document [6.6]
  • l’encodage du texte en UTF-8 [6.4.3]
  • le séparateur de champs, qui doit être la tabulation [6.4.1]

Ces critères doivent être remplis pour passer à l’étape suivante. Ils sont par ailleurs obligatoires pour un chargement dans la base.
Si un fichier ne répond pas à l’un de ces critères, l’éditeur en est informé. L’évaluation ne peut aller plus loin avant qu’une nouvelle version, corrigée, ne nous soit parvenue.

Dans le cas contraire, le fichier est chargé dans OpenRefine et le script correspondant au type de document est appliqué. Le script applicable aux périodiques contient 97 opérations. Celui pour les e-books, 145. Ce nombre peut varier selon la qualité du fichier, certaines opérations n’ayant pas lieu si aucune correction n’est nécessaire.

Les erreurs de type syntaxique sont mentionnées directement dans la cellule qui les contient. En revanche, les opérations de type sémantique nécessitent de créer des colonnes supplémentaires pour l’affichage des erreurs. En effet, les erreurs sémantiques sont des erreurs potentielles, qui doivent être vérifiées avant d’être validées. Il est nécessaire, pour comprendre ce choix, de savoir que nous communiquons à l’éditeur un fichier, au format html, qui accompagne le rapport écrit transmis après chaque évaluation. Ce fichier est le résultat d’un différentiel entre le fichier KBART qui nous a été transmis par l’éditeur et le fichier évalué sur lequel le script a été appliqué et enrichi des corrections de celui qui l’évalue. L’outil utilisé est DAFF.

Les scripts ont donc été pensés selon le type de document, selon le type d’erreur, mais aussi selon l’usage qui en est fait par les éditeurs. Disposer de ce fichier html leur permet, grâce à un code couleur, de repérer facilement les lignes qui ont été modifiées lors de l’évaluation, qu’il s’agisse d’une modification automatisée grâce au script ou d’une modification manuelle effectuée par l’évaluateur.

Pour résumer, prenons deux exemples d’opérations : celui du format des identifiants, ISSN et ISBN, qui est une opération syntaxique ; celui des métarevues, qui permet de déceler la présence de titres non déployés dans le fichier.
Un identifiant non conforme sera décelé par le script sans équivoque. Un ISSN sans tiret ou contenant la lettre ‘X’ en deuxième position contient nécessairement une erreur.
En revanche, le script permettra de repérer une date de début de couverture (date_first_issue_online) inférieure à la date de début de la publication contenue dans le SUDOC, indice susceptible de révéler la présence d’une métarevue non déployée, mais ne sera pas en mesure d’apporter une réponse plus aboutie afin d’aider l’éditeur à corriger son fichier. Une intervention humaine sera nécessaire afin de consulter le registre ISSN et enrichir le fichier des titres de la métarevue qui en sont absents.

Vous comprenez maintenant pourquoi certaines modifications du fichier par le script doivent être faites non pas directement dans les cellules que contient la version qui nous est livrée par l’éditeur, mais dans des colonnes supplémentaires : pour les tests sémantiques, l’évaluateur modifie les cellules du fichier qui contiennent des erreurs, tout en s’appuyant sur les informations contenues dans les colonnes générées par le script.

Une fois le fichier corrigé des erreurs syntaxiques et sémantiques qu’il contient, il est exporté d’OpenRefine.
Le différentiel est alors généré et son résultat transmis à l’éditeur comme illustration des informations contenues dans le rapport.

Peut-être vous êtes-vous déjà lancé dans l’utilisation des scripts avant d’en arriver là dans la lecture du billet. J’en serais heureux ! Peut-être alors vous êtes-vous trouvé confronté à certaines incompréhensions dans l’analyse du résultat. Rien de plus normal, surtout si vos interrogations portent sur les deux points suivants :

  • les scripts ont été élaborés sous la version 2.5 d’OpenRefine, qui s’appelait encore GoogleRefine à l’époque de sa conception, c’est-à-dire en 2011. Depuis, deux nouvelles versions ont vu le jour. Mais ces dernières sont des versions beta. Nous avons préféré nous appuyer sur la dernière version stable, la 2.5. Bien que les scripts semblent compatibles avec les versions plus récentes, tous les tests n’ont pas encore été effectués pour le confirmer.
  • la colonne ‘P-dist_author’ du script e-books ne laisse apparaître aucune information, voire n’a pas été générée. Rien de plus normal : elle contient le résultat d’un calcul de distance entre les chaînes de caractères contenues dans le ‘publication_title’ et la zone 200 de la notice SUDOC renvoyée par l’ISBN papier. Or ce calcul de distance s’appuie sur une fonction présente sur le serveur qui héberge OpenRefine à l’Abes. Vous ne pouvez donc pas y faire appel. Cette restriction est valable pour d’autres opérations. Notez, pour les plus curieux, qu’OpenRefine dispose de tels outils par défaut.

Ne pas être en mesure d’exploiter pleinement ces scripts pourrait être frustrant… C’est pourquoi nous proposons à ceux qui souhaitent en savoir plus sur la manière de les utiliser de rejoindre le premier des CERCLES mené dans le cadre de BACON. Pour en savoir plus, rendez-vous au prochain (et dernier) billet de la série.

N.B. : les scripts communiqués correspondent à une version. Ils ne sont en rien figés et nous serions très heureux de les enrichir de vos suggestions.

Cyril Leroy

OpenRefine au service de BACON : quelle évaluation pour les fichiers KBART ? [2] – Un outil : OpenRefine

[Lire le billet qui introduit cette série « OpenRefine au service de BACON : quelle évaluation pour les fichiers KBART ? »]

OpenRefine est un outil open source conçu pour manipuler des données dont la qualité nécessite un traitement. Mais il permet bien plus que de nettoyer un fichier tabulé des scories qu’il contient. Comparable à Excel, son principal intérêt est de permettre l’appel à des services web. Il est alors possible, et facile, de comparer le contenu d’un fichier avec une base de référence disposant d’une API.

Ce billet est un accompagnement dans vos premiers pas avec OpenRefine : comment l’installer, charger un fichier, effectuer ses premiers traitements.
Étant donné le nombre de tutoriels déjà disponibles sur cet outil, il sera surtout l’occasion de vous communiquer une bibliographie.

     1. Installation

OpenRefine est disponible sous Windows, Mac et Linux. Son installation s’effectue sans difficulté, quel que soit l’environnement sous lequel vous évoluez : il suffit de lancer le fichier d’installation correspondant au vôtre, téléchargeable depuis le site officiel.
Un environnement Java est requis.
Vous noterez, sur la même page, la liste des extensions qu’il est possible d’installer afin, par exemple, de permettre les exports en RDF.

     2. Chargement d’un fichier

Après avoir lancé OpenRefine, votre navigateur par défaut offre un nouvel onglet. Vous voyez alors apparaître :

accueil_OR

A gauche, trois onglets permettent de créer un projet (onglet actif sur l’illustration), d’ouvrir un projet existant ou d’importer un projet précédemment exporté.

A l’import, OpenRefine accepte de multiples formats. Pour illustrer notre propos, l’exemple utilisé sera celui d’un fichier tabulé (.tsv), ayant pour séparateur la tabulation, encodé en UTF-8. Ce fichier est issu de BACON : « Lavoisier_Global_AllJournals_2016-07-01.txt »

Pour importer un tel fichier après son téléchargement, cliquer sur « Parcourir », sélectionner le fichier dans l’arborescence de l’ordinateur puis cliquer sur « Next ».

Une nouvelle fenêtre apparaît, qui permet de choisir différentes options. Cette copie d’écran reproduit la partie inférieure de l’écran :

chargement_OR

Les options sélectionnées ne correspondent pas à la configuration proposée par défaut, mais aux besoins inhérents au fichier ainsi qu’aux traitements que nous allons opérer.
Il s’agit bien d’un fichier tabulé (fenêtre de gauche à fond bleu), dont le séparateur est la tabulation (« tabs »). La première ligne contient les intitulés de colonnes et doit donc être considérée comme telle (« Parse next »). Il ne nous reste plus qu’à cliquer sur « Create Project ».

     3. Présentation de l’interface

Appliquer des traitements sur les données que contient un projet peut s’opérer de deux manières complémentaires : par l’interface graphique ou en appliquant un script. OpenRefine accepte trois langages de programmation différents : GREL (General Refine Expression Language), Jython et Clojure.
Lors de nos traitements, nous utilisons GREL. Avec une  subtilité : la fonctionnalité qui permet d’appliquer un script accepte en réalité du Json, qui encapsule l’un des trois langages, dont le GREL.

Par exemple :

 {
 "op": "core/column-addition",
 "description": "Contient obligatoirement P ou F",
 "engineConfig": {
 "mode": "row-based",
 "facets": []
 },
 "newColumnName": "access_type_format",
 "columnInsertIndex": 55,
 "baseColumnName": "access_type",
 "expression": "grel:if(isNotNull(value.match(/[PF]/)),value,value+' : format incorrect')",
 "onError": "set-to-blank"
 }

Ce script vérifie le contenu des cellules de l’access_type, cette colonne du fichier KBART qui informe sur le type d’accès pour un titre : payant (« P ») ou gratuit (« F »). Il respecte la syntaxe Json mais, comme vous pouvez le remarquer, la ligne 11, intitulée « expression » et qui comporte l’appel aux fonctions, déclare en prémisse que le contenu de l’expression suit la syntaxe « grel ».

La méthode par script n’est pas la plus évidente à mettre en œuvre lors d’une première utilisation. La prise en main d’OpenRefine gagnera à se faire par l’interface graphique. Mais, très vite, il est nécessaire d’avoir recours à l’un des langages de programmation, nombre de fonctions n’étant pas accessibles par l’interface.

En revanche, pour s’initier au GREL, l’interface est un excellent outil qui permettra d’ailleurs un gain de temps considérable. En effet, plutôt que de coder directement en Json, mieux vaut utiliser l’interface graphique pour renseigner les expressions GREL. Il sera ensuite toujours possible de récupérer, par une extraction de l’historique, les expressions GREL qui apparaîtront alors directement revêtues de leur habit de Json.
Voilà pourquoi les deux méthodes sont complémentaires.

Pour reprendre l’exemple précédent, voici la méthode a priori la plus simple pour parvenir au résultat escompté.

  • dans l’interface, sélectionner la flèche correspondant à la colonne sur laquelle mener l’opération. Sélectionner « Edit cells » > « Transform ».

access_type1_OR

  • cette action a pour conséquence l’ouverture d’une nouvelle fenêtre, depuis laquelle nous allons renseigner l’expression correspondant à l’opération que nous voulons mener (2), en GREL (1). Le résultat sur les cellules est directement visible (3).
    [Les valeurs « l » (l. 1) et « F » (l.3) ont été modifiées pour les besoins de l’exemple]

access_type2_OR

Nous ne nous arrêterons pas dans le détail sur la manière dont l’expression est construite. Ce qui nous importe ici est le résultat obtenu et le moyen de le reproduire facilement en récupérant le script au format Json.

  • pour ce faire, après avoir appliqué l’opération en cliquant sur « OK », nous allons sélectionner l’option « Extract » depuis l’historique.
    Remarquons que trois actions ont été menées jusqu’à présent sur ce projet : les opérations 1 et 2 correspondent à l’édition des lignes 1 et 3 de la colonne access_type afin de rendre l’exemple plus parlant. La troisième, celle qui nous intéresse réellement, correspond à la vérification du contenu de cette colonne : si l’une des cellules qui la constituent contient une valeur autre que « P » ou « F », alors la valeur initiale doit apparaître, suivie de la mention « format incorrect ». Dans le cas contraire, seule la valeur initiale doit apparaître.

access_type3_OR

  • après avoir cliqué sur « Extract » une nouvelle fenêtre nous permet de sélectionner la partie du code, formaté en Json, qui nous intéresse. Ici, seulement celle qui correspond à la troisième étape, d’ailleurs la seule accessible, l’édition manuelle de contenu ne pouvant être exportée.

access_type4_OR

Il est alors facile de copier le code afin de le conserver pour une utilisation ultérieure. Il suffira, sur un nouveau projet, de coller le code correspondant, au format Json, dans la fenêtre accessible en cliquant sur « Apply » dans l’historique puis de valider à l’aide de « Perform Operations »

access_type5_OR

 

access_type6_OR

Vous avez peut-être remarqué la présence d’une différence entre le script tel que je vous l’ai présenté en début de ce chapitre et celui qui a été généré par OR et copié tel quel dans la fenêtre « Apply Operation History » ci-dessus.
Il s’agit de la « description » du code. En Json, les commentaires apparaissent dans cette partie, en texte libre pourvu que le texte soit entre guillemets. Pour une meilleure lisibilité et afin d’apporter des éléments plus précis que ceux contenus dans la description générée automatiquement par OpenRefine, son contenu a été modifié dans le script du début de chapitre.

A venir : Dans le prochain billet, nous vous communiquerons les scripts utilisés afin d’évaluer les fichiers KBART.

Bibliographie :

Cyril Leroy

OpenRefine au service de BACON : quelle évaluation pour les fichiers KBART ? [1] – Introduction

Cette série de billets exposera la méthode d’évaluation appliquée aux fichiers KBART, transmis à l’Abes par les éditeurs francophones ayant accepté de collaborer avec nous.
Pour le dernier d’entre eux, l’occasion sera donnée d’exposer une nouvelle déclinaison du dispositif CERCLES, appliquée à BACON.

  1. Introduction (ce billet)
  2. Un outil : OpenRefine
  3. Cas pratique
  4. Dispositif CERCLES dans le cadre de BACON

 

 Logo Bacon

La BAse de COnnaissance Nationale (BACON) est un entrepôt de métadonnées libres pour le signalement de la documentation électronique.
Son contenu, exposé sur bacon.abes.fr, peut être interrogé et téléchargé par webservices ou via l’interface graphique du site web.

Le modèle qui organise la base est conforme à la recommandation KBART NISO-RP-9-2014. Le premier niveau d’accès au contenu est celui du titre, pour les livres électroniques comme pour les périodiques. L’ISBN et l’ISSN électroniques constituent les portes d’entrée sur l’ensemble des métadonnées contenues dans les 25 champs de la recommandation.

Au second niveau, les titres sont regroupés par bouquets et masterlists. Il est en effet possible de différencier les fichiers mis à disposition selon leur nature : les masterlists décrivent l’ensemble du contenu d’une plate-forme pour un éditeur donné ; les bouquets correspondent aux offres commerciales proposées.

BACON contient, à ce jour, 178 bouquets et masterlists de ressources proposées par l’édition scientifique francophone. Ce résultat, non définitif, a été atteint en informant les éditeurs de l’intérêt d’appliquer la recommandation KBART pour l’amélioration de la qualité des métadonnées qui permettent le signalement et l’accès à la documentation électronique. Corriger à la source bénéficie à l’ensemble des intervenants qui redistribuent ou utilisent ces métadonnées.

Les éditeurs sensibles à nos arguments, qui acceptent de mettre en place un circuit de production de fichiers au format KBART, se voient proposer une évaluation des fichiers ainsi produits et une expertise sur la recommandation, avant de voir leurs fichiers chargés dans la base.

Pour mener à bien les évaluations, nous mettons en œuvre une procédure qui s’articule principalement autour d’un outil : OpenRefine.

Cyril Leroy

CERCLES : retour d’expérience du SCD de l’Université de Picardie Jules Verne sur le corpus CAIRN

Les origines

Les questions sur SUCAT

cercles_upjv

Nouvelle adjointe à la gestion de la bibliothèque numérique dans mon établissement, et chargée du signalement des e-books, je me suis posé beaucoup de questions quant au traitement de ces ressources. J’ai étudié de près les avantages et inconvénients de l’exemplarisation automatique, notamment en terme de qualité et de complétude des notices, et lancé une question ouverte aux catalogueurs de ressources en ligne sur SUCAT (ndlr : la liste de diffusion des catalogueurs du réseau Sudoc), posant les questions qui me taraudaient, intitulée : « Aux catalogueurs des bibliothèques numériques ».

Les réponses ont afflué, l’ABES a également répondu que cela figurait parmi ses préoccupations actuelles.

La mise en place de CERCLES

Des pistes de résolution et une expérimentation avec un SCD sur le principe de mutualisation du traitement de la qualité des données de ressources électroniques dans le Sudoc étant déjà en cours, l’ABES m’a proposé de faire partie du projet naissant.

L’engagement

Avec l’accord de ma hiérarchie, un acte d’engagement a été signé entre mon établissement et l’ABES, mentionnant le périmètre d’action et les délais engagés.

Délimitation du périmètre d’action :

Un corpus clos a été établi par l’ABES, avec l’édition d’un tableau de PPN, édité à une date D, et dans lequel tout nouveau versement n’apparaîtra pas, soit une liste de 4852 notices à traiter.

Axes d’enrichissements :

L’accord initial prévoyait une mise en lien des 7xx, et le travail collatéral : indicateurs, codes de fonction, création d’autorités au besoin.

Évaluation en amont des notices du corpus :

Un travail préalable, sur un échantillon de 50 notices, m’a permis de faire une estimation du temps passé, mais aussi et surtout de constater nombre de surprises, et donc, d’élaborer quelques changements d’orientation, exposés et acceptés par l’ABES : ainsi, les notices dans lesquelles les auteurs étaient déjà liés, ont été exclues de mon champ d’action. Les notices dans lesquelles des liens étaient à créer sont restées à ma charge (1484 PPN).
Pour celles-ci, je me suis engagée, en plus de créer les liens et les notices d’autorité le cas échéant (+ travail collatéral pré-cité) :

  • à contrôler la construction des 200 ($f $g) ;
  • à redistribuer en conséquence les zones et codes de fonction en 7xx ;
  • à assurer les modifications suivantes : caractères parasites, arobase mal positionné, désordre des sous-zones en 200 ;
  • à signaler tout problème d’URL (ABES et Cairn).

Mon périmètre initial a été certes réduit (on est passé de 4852 notices à 1484), mais les modifications apportées sont finalement plus nombreuses et plus poussées.

Le chantier d’enrichissement

Traitement en pratique

By_Horla_Varlan_CC_BY

Étape 1 : j’ouvre les outils dont j’ai besoin

  • l’espace collaboratif CERCLES (les 3 documents « tableau de bord », « suivi pour info réseau » et « tableau de suivi »)
  • WinIBW
  • la plateforme « Cairn.info« 

Étape 2 : j’affiche la notice WinIBW à étudier (je copie/colle le PPN à partir de mon « tableau de suivi »)

Étape 3 : je copie/colle l’URL de la zone 859 dans « Cairn.info » pour vérifier l’URL fournisseur et accéder à la ressource

Si l’URL est erronée, je recherche par titre puis demande de modification de la zone 859 à l’ABES via le guichet d’assistance + signalement à Cairn + transmission au Correspondant Catalogage pour diffusion de l’information sur les listes, afin que les bibliothèques actualisent leur E856. Je corrige immédiatement la zone E856 de mon exemplaire.

Étape 4 : j’ouvre le document dans « Cairn.info » (en PDF ou en HTML) pour accéder à la page de titre notamment, source principale de catalogage. Je commence le travail de vérification / enrichissement :

  • vérification de la conformité de la zone 200 $a, $e ; $f ; $g, et corrections le cas échéant
    • toujours, les auteurs, toutes responsabilités confondues, sont présents en $f
    • souvent, il manque $e
    • souvent, $e est mal placée (après $f)
  • redistribution des 7XX et des codes de fonction, corrections
    • toujours, il n’y a que des 700 et 701, pas de 702 (beaucoup d’auteurs en réalité « directeurs »)
    • toujours, les indicateurs des 7XX sont erronés
  • mise en lien des 7XX
    • création d’Autorités Personnes Physiques (APP) le cas échéant
    • vérification des liens déjà faits : parfois, les liens sont erronés (homonymes)
    • vérification des données codées des APP (zone 106 en particulier)
    • si un doublon APP est identifié, transmission au Correspondant Autorité
  • vérification de l’indication du type de document : 200 $b ou 181-182
    • parfois, les deux coexistent : suppression de 200 $b
  • vérification de la zone 300, et corrections le cas échéant
    • souvent, des caractères parasites sont présents

Étape 5 : je légende mon document « tableau de suivi », selon mon code couleurs

Étape 6 : je trie et chiffre le travail effectué

Étape 7 : je reporte les informations dans le « tableau de bord » (le récit au jour le jour de mon travail, pour l’ABES et pour moi) et dans le document « Suivi pour info réseau » (les infos sur l’avancée du chantier, pour les membres du réseau).

Dans le SIGB Horizon, la mise à jour du catalogue local s’effectue au fil des corrections, par le transfert régulier quotidien.

Les moyens

Outil collaboratif et référent :

Le répertoire BOUDA (GED de l’ABES), un temps utilisé, puis le GoogleDrive permettent un accès garanti aux outils de suivi. Merci à l’ABES de les avoir mis à disposition.

Outils « maison » :

Pour gagner du temps, je me suis créé des « messages-modèles », à destination du guichet d’assistance ABESstp, des Correspondants Catalogage et Autorité de mon établissement, de mon interlocutrice chez Cairn. Je n’ai plus qu’à y remplacer les PPN et/ou URL.

Les difficultés :

  1. L’engagement dans le temps : seule sur la gestion de ce chantier, et occupée comme tout un chacun par les tâches quotidiennes et les autres projets de mon établissement, je n’ai pas pu respecter le délai imparti. De plus, l’accord initial ne prévoyant pas un travail si poussé sur les notices, l’estimation du temps de traitement s’est vite avérée complètement fausse.
  2. Les créations d’APP : elles peuvent s’avérer difficiles, si ni IdRef ni l’ouvrage lui-même ne fournissent d’information sur l’auteur. La zone 340 de l’autorité ne peut donc être renseignée.

Conclusion

Bilan quantitatif

C’est là où le bât blesse : surprises au gré du chantier, suivi du chantier en solitaire, charge de travail, … La quantité de notices traitées est loin de celle visée. Le traitement est long. En cette fin d’ année universitaire 2015-2016, 493 notices sont traitées selon les modalités approfondies, pour 814 liens en 7XX et 56 créations d’APP.

Bilan qualitatif

  1. La qualité du Sudoc : à propos du travail effectué, je suis plutôt satisfaite. Une satisfaction à la fois personnelle, parce que le format des notices d’e-books, nouveau à mes yeux n’a plus de secret pour moi, et aussi professionnelle, de par la contribution à l’enrichissement de ces notices, et ceci non seulement pour mon établissement, mais à l’échelle du réseau (ndlr : depuis avril 2016, la BNU de Strasbourg s’est aussi lancée dans un chantier CERCLES sur les monographies encyclopédiques CAIRN).
  2. La qualité des notices fournies par l’éditeur : mon interlocutrice chez Cairn compile les types de problèmes rencontrés, et veille à l’amélioration future de la fourniture des métadonnées, afin de ne pas reproduire ces problèmes désormais identifiés.

L’ABES et moi

cercles_rond

Mon référent est toujours disponible. Merci à Kattialyn G. et aussi à Laurent P. ! J’ai été très honorée que l’ABES m’ait proposé ce projet. Je me sens d’autant plus active au sein du réseau que mon établissement participe à un chantier de mutualisation d’enrichissement des données.

La valorisation et la visibilité des données n’est pas une mince affaire, mais à l’heure de l’évolution des catalogues de bibliothèques, une collaboration entre les éditeurs et l’ABES, mise en pratique par les membres du réseau, est capitale.

Aurélie Bec, pour le SCD de l’université de Picardie Jules Verne  logo_scd_upjv

 

 

Récit d’une immersion. Traiter les ebooks Dalloz avec les données Sudoc, les données de l’éditeur et les outils du hub

Ce billet relate à la première personne l’immersion effectuée par Catherine Storne (Université de Strasbourg) au sein de l’équipe hub de l’ABES, entre le 1er et le 5 février 2016. Catherine a eu l’occasion de partager cette expérience aux dernières journées ABES. Merci pour tout, Catherine !

Placée en face de la nouvelle « Metadaten Weltanschauung » au travers de la réflexion locale sur l’abonnement à un outil de découverte (discovery tool) ou sur les réalisations de la plateforme ISTEX sur les licences nationales, je ressentais le besoin de monter en compétences sur la manipulation des métadonnées. J’ai donc souhaité faire une immersion à l’ABES pour mieux comprendre les projets de l’établissement tournant autour des métadonnées dont les noms parvenaient aux confins de nos bibliothèques : BACON, hub de métadonnées, CERCLES, ainsi que les liens entre eux. Mon objectif étant de travailler au rapprochement, au sein du SCD de Strasbourg, des équipes de la documentation électronique et du catalogage, la participation à un projet concret, au travers d’un chantier CERCLES me semblait de nature à y contribuer.

Après discussion avec quelques collègues, il est apparu que le corpus d’e-books de la bibliothèque numérique Dalloz était mal-traité, i.e mal catalogué au SCD, qu’un catalogage de qualité de ce corpus dans le Sudoc était attendu et profiterait à l’ensemble des bibliothèques du réseau.

Pour l’ABES, l’immersion devait permettre d’avancer dans la réflexion sur le rôle que certains établissements pourraient jouer dans la chaîne de traitement des métadonnées fournies par les éditeurs, avant même leur traitement par le hub de métadonnées.

Avec un peu (beaucoup) d’appréhension à l’idée de me retrouver dans l’antre de « Winnie » [WinIBW] sans savoir réellement cataloguer et sans avoir retenu de mes lectures sur RDF tout ce que j’aurais dû, je quittais mon grand Est natal pour rejoindre le temps d’une semaine Montpellier, la surdouée.

1.  Les données sur la bibliothèque numérique Dalloz

La plateforme de Dalloz http://www.dalloz-bibliotheque.fr/ , permet une recherche sur les e-books de cet éditeur par titre, auteur, domaines ou collections. La liste complète des titres sous la forme d’un tableau est quant à elle disponible à  http://www.dalloz-bibliotheque.fr/listing.php (appelée par la suite « Tableau-Dalloz »).

Par ailleurs, Dalloz met à disposition un entrepôt OAI : http://logistic.book-vision.com/services/oai/act68.php?verb=ListRecords&metadataPrefix=onix_dc (appelé par la suite « OAI-Dalloz ».)

1.1  Premier constat

Les deux sources ne comportent pas un nombre identique de titres (1939 pour Tableau-Dalloz, 1626 pour OAI-Dalloz) ni les mêmes données.

Tableau-Dalloz contient l’ISBN électronique, l’ISBN papier correspondant, le titre, le n° de l’édition, la collection. Pas même l’URL de consultation. Les données d’OAI-Dalloz sont plus riches ; parmi elles : titre, auteur, sujet, résumé, éditeur, date d’édition, ISBN électroniques, les informations pour la reconstitution d’une URL de consultation, etc.

1.2  Deuxième constat, dû à l’œil expert des collègues de l’ABES

Tous les titres, ou presque, sont catalogués dans le Sudoc, pour la version papier du livre. Le web service isbn2ppn de l’ABES permet, à partir des ISBN-papier du tableau-Dalloz d’obtenir la liste des ppn (de la version papier) correspondants ; une extraction du Sudoc de ces titres à partir de la liste des ppn (de la version papier) constitue la troisième source de données (appelée Sudoc-Dalloz),

1.3  Directions de travail

A partir de ces deux constats, s’esquissent quelques lignes de travail :

  • vérifier la qualité des notices du Sudoc, pour s’assurer que les liens sont présents (6XX et 7XX, collection)
  • comparer les 3 sources entre elles.

Pour les notices Sudoc :

  • tous les 7XX ont un lien vers un ppn autorités
  • tous les 410 ont un lien vers le ppn de la collection

Sur les 1939 du Tableau-Dalloz :

  • 38 titres ne sont pas catalogués dans le Sudoc dans leur version papier
  • 38 autres titres sont déjà catalogués dans le Sudoc dans leur version électronique
  • 1 titre du Tableau-Dalloz contient une erreur d’ISBN électronique
  • 31 ppn sont écartés car il faut vérifier s’ils sont des doublons

Au final, il reste 1832 titres qui ne posent aucun problème.

En règle générale, le hub de métadonnées part des données des éditeurs pour créer les notices d’e-books. Dans le cas du corpus Dalloz, la réflexion est différente car la pré-existence dans le Sudoc des notices des documents papier, complètes, constitue une base de départ fiable.Il est donc décidé de créer les notices des e-books dans le Sudoc à partir des notices correspondantes des livres-papier puis d’utiliser les données venues des sources Dalloz pour enrichir ou corriger les notices créées dans le Sudoc en utilisant pour cela des outils développés dans le cadre du Hub de métadonnées.

2.  Création par copie de notices d’e-books dans le Sudoc

Pour chaque ppn indiqué, le script de création de notices a dupliqué la notice du livre imprimé en y apportant les modifications du tableau ci-dessous :

Notice papier Notice d’e-book correspondante
001 Non repris
002 Non repris
003 Non repris
008 Par défaut :

$aOax3

010 Non repris
020 Non repris
021 Non repris
033 Non repris
034 Non repris
035 Remplacé par défaut par :

##$aBNDalloz

073 Non repris
106 Non repris
135 Ajout par défaut :

##$av$br$cm$e#$gm$ia$ja

181 Ajout par défaut :

##$P01$ctxt

182 Ajout par défaut :

##$P01$cc

215 Non repris
225 Non repris
230 Ajout par défaut :

##$aDonnées textuelles

337 Ajout par défaut :

##$aNécessite un logiciel capable de lire un fichier au(x) format(s)Widelook ou Widelook Flash

410 Non repris
452 Ajout par défaut :

##$0″ + ancienPpn

801 Non repris
802 Non repris
830 Non repris

 

3.  Les enrichissements du hub de métadonnées (ABES)

Les notices d’e-books ont été enrichies par le hub de métadonnées.

Pour ce faire, le fichier « Tableau-Dalloz » a été complété via l’outil Openrefine (téléchargeable à openrefine.org/), des données suivantes :

  • ppn papier (obtenu grâce au web service isbn2ppn)
  • ppn électronique (équivalence p-ppn/e-ppn obtenue par le compte-rendu du script de création)

Il a ensuite été transformé en RDF.

Par ailleurs, les données « OAI-Dalloz » ont été converties en RDF/XML et chargées dans la base XML Oracle de l’ABES. Plusieurs notices étant en doublon dans le moissonnage OAI, le nombre final d’e-books distincts est de 1566.

3.1  RDF

3.1.1  En trois mots

RDF est le langage du web sémantique.

« RDF (Resource Description Framework) est un modèle de représentation de données élaboré sous l’égide du W3C (World Wide Web Consortium). Il attribue à des ressources, identifiées par des URI, des propriétés et des classes (ou catégories), permettant de les définir, les décrire, ou d’établir des relations entre elles. […]

Les données sont découpées en entités élémentaires pour former des triplets : <sujet> <prédicat> <objet>

  • le sujet est l’identifiant de la ressource ;
  • le prédicat est une propriété ou une relation, elle-même identifiée par une URI (le plus souvent représentée par un préfixe) ;
  • l’objet est l’identifiant d’une autre ressource en relation avec la première, une valeur ou un littéral. »

Définition trouvée dans : http://documentation.abes.fr/sudoc/manuels/pdf/sudoc-rdf.pdf (consulté 06/03/2016)

3.1.2  Choix de construction des URI

Pour que les sujets, prédicats, éventuellement objets puissent être identifiés de manière unique, il faut leur attribuer des identifiants, construits sous forme d’URI.

Voici les choix qui ont été faits dans le cas de la bibliothèque numérique Dalloz pour construire un modèle de création des URI pour les œuvres et les manifestations.

  • Pour l’œuvre :
  • Pour la manifestation :
    • Manifestation électronique :
      • champs attribués à la manifestation électronique : issn (électronique), ppn (électronique), numéros permettant de reconstituer l’url de consultation (n° puc, n° nu), date de publication
      • identifiant choisi : ISBN électronique
    • Exemple : http://www.hub.abes.fr/bndalloz/ebook/9782247103713/m/web (/m pour préciser qu’il s’agit d’une manifestation ; /web pour préciser qu’elle est électronique)
    • Manifestation imprimée (papier) :
      • champs attribués à la manifestation électronique : issn (papier), ppn (papier), date de publication
      • identifiant choisi : ISBN électronique
    • Exemple : http://www.hub.abes.fr/bndalloz/ebook/9782247103713/m/print (/m pour préciser qu’il s’agit d’une manifestation ; /print pour préciser qu’elle est imprimée)

3.1.3  Exemples de triplets

<http://www.hub.abes.fr/bndalloz/ebook/9782247103713/w> dcterms:title "50 droits contre l'exclusion " ;

<http://rdaregistry.info/Elements/w/P10072> <http://www.hub.abes.fr/bndalloz/ebook/9782247103713/m/web>, <http://www.hub.abes.fr/bndalloz/ebook/9782247103713/m/print> .

Signifie : L’oeuvre dont l’identifiant (l’ISBN électronique) est 9782247103713 a pour titre « 50 droits contre l’exclusion » ; elle a deux propriétés dont on retrouve la définition dans rdaregistry : P10072 correspond à « has manifestation of work ; donc, l’oeuvre a deux manifestations : l’une  électronique, l’autre imprimée.

<http://www.hub.abes.fr/bndalloz/ebook/9782247103713/m/web> <http://purl.org/ontology/bibo/isbn> "9782247103713" ;

<http://www.hub.abes.fr/namespaces/ppn> "191163120" ;

dcterms:isPartOf <http://www.hub.abes.fr/bndalloz/collection/asavoir> ;

<http://purl.org/ontology/bibo/edition> "1" .

Signifie : la manifestation électronique a pour ISBN électronique 9782247103713 et  pour ppn (défini dans le vocabulaire du hub) 191163120 ; elle appartient à la collection « asavoir » (A savoir) et en est à la première édition

<http://www.hub.abes.fr/bndalloz/ebook/9782247103713/m/print> <http://purl.org/ontology/bibo/isbn> "9782247070602" ;
<http://www.hub.abes.fr/namespaces/ppn> "134600878"

Signifie : la manifestation papier a pour ISBN papier 97822470706020 et pour ppn 134600878.

RDF, par les déclarations  et les triplets, décrit des relations. Ces relations peuvent être décrites sous forme de représentations graphiques, composées d’ovales, flèches, rectangles.

dalloz_graphe

 

3.1.4  Les graphes

On obtient deux sous-ensembles séparés dans la base RDF (ce qu’on appelle des « graphes ») :

  • celui des données du « Tableau-Dalloz » enrichi :

<http://www.hub.abes.fr/dalloz/DALLOZ_4FEV2016/tableaudalloz>

  • celui des données « OAI-Dalloz :

<http://www.hub.abes.fr/dalloz/DALLOZ_4FEV2016/>

Les URI des documents étant dans chacun d’eux construits sur l’ISBN électronique, les données peuvent être fusionnées facilement.

3.2  Le programme MARCEDMOD

L’ABES a récemment développé un programme expérimental de modification de notices du Sudoc, répondant au doux nom de MARCEDMOD [pour Marc-édition-modification ? eux, comme ils veulent toujours créer du lien, l’appellent plutôt Marc et Maud ! Il faudra quand même leur demander la source de leur inspiration !].

Ce programme interroge les données auparavant converties en RDF, avec des requêtes SPARQL (SPARQL n’est rien d’autre que le langage de requête des données en RDF). Ces requêtes permettent de sélectionner les triplets correspondant aux critères choisis. Ensuite, pour chaque type de modification à faire dans le Sudoc, un script va chercher les notices correspondantes dans le Sudoc et opérer la transformation souhaitée en remplaçant la donnée présente dans le Sudoc par celle issue de RDF.

Par exemple, pour ajouter la Dewey issue de OAI-Dalloz sur les notices du Sudoc qui n’en ont pas, MARCEDMOD fait ce qui suit :

select distinct ?eppn

# Je sélectionne tous les ppn électroniques

from <http://www.hub.abes.fr/dalloz/DALLOZ_4FEV2016/tableaudalloz>
from <http://www.hub.abes.fr/dalloz/DALLOZ_4FEV2016>

# à la fois dans les données Tableau-Dalloz et OAI-Dalloz désormais présentes en RDF dans la base du hub

where {

?work <http://rdaregistry.info/Elements/w/P10072> ?manif.

?manif <http://iflastandards.info/ns/isbd/elements/P1003> <http://iflastandards.info/ns/isbd/terms/mediatype/T1002>.

?manif <http://www.hub.abes.fr/namespaces/ppn> ?eppn.

# pour lesquels une œuvre a une manifestation, manifestation qui est de type électronique et qui a dans le hub un ppn électronique

} LIMIT 1000

Script :

J’injecte cette liste de ppn électroniques dans le Sudoc :

Node zone=Notice.find("676");

Je recherche toutes les zones « 676 »

if (zone == null)
{
Notice.Insert("676","#","#","a","340");

S’il n’y a pas de Dewey présente, j’insère 676##a340

}
else
{
Notice.alert("la zone existe dejà");
}

Sinon, je ne fais rien et je dis que « la zone existe déjà »

3.3  Enrichissements faits par le hub

  • Résumé : prévu, sera bientôt fait
  • ISBN électronique (tirés du tableau-Dalloz)
  • Dates d’édition : dates du tableau-Dalloz ajoutées en 100$a et 210$d (par écrasement de celles éventuellement présentes)
  • Edition : pour les titres du tableau-dalloz ayant un numéro d’édition autre que 1, ce numéro d’édition a remplacé celui présent dans le Sudoc
  • Dewey : pour les notices sans 676, ajout d’un 676 avec le code dewey 340 tiré d’OAI-Dalloz
  • URL : le champ 859 a été créé pour les seules les notices de OAI-Dalloz ont pu être traitées car les numéros permettant de reconstituer l’URL ne sont pas présents ailleurs.
  • Editeur : seules les notices de OAI-Dalloz ont pu être traitées

4.  Le programme de travail du chantier CERCLES

Récapitulatif des travaux catalographiques (vérifications ou corrections) à faire dans le Sudoc par le SCD de Strasbourg :

  • Catalogage des notices qui n’ont de ppn papier : 38 titres
  • Vérification et enrichissement des notices d’e-book qui existaient déjà dans le Sudoc : 35 titres
  • Vérification d’1 titre du Tableau-Dalloz qui contient une erreur d’ISBN électronique
  • Catalogage des 31 ppn écartés car il faut vérifier s’ils sont des doublons
  • Vérification des notices pour lesquelles la date d’édition entre le Sudoc et le tableau-Dalloz sont différentes : 59 titre
  • Enrichissement manuel des notices ne figurant pas dans OAI-Dalloz : 382 titres
    • ajout de l’url
    • modifier l’année
    • modifier l’éditeur
    • ajouter le code Dewey “340” si aucun Dewey n’est présent dans la notice
  • Titres présents dans OAI-Dalloz mais absents de tableau-Dalloz : 29 titres à traiter dans un second temps
  • Travail sur les notices d’e-books créées par l’ABES :
    • collections numériques : récupération du ppn ou demande de création
    • Envoi à l’ABES des ppn des collections numériques, en regard des URI fournis par l’ABES
    • Vérifier nécessité de créer et comment les champs 303,304,305,307,339
    • Vérifier les 13 notices signalées par l’ABES pour lesquelles plusieurs urls de consultations sont associées (liste fournie par l’ABES)

Conclusion

La durée de l’immersion n’a pas encore permis de répondre aux questionnements de l’ABES sur une implication d’établissements volontaires dépassant le cadre du catalogage et s’attachant  à des manipulations préparatoires sur les données soit pour participer à la mise à jour régulière des corpus  soit pour alimenter aussi BACON . Cette réflexion est encore en cours et fera l’objet vraisemblablement d’un autre billet.
Il nous faudra également revenir sur le chantier CERCLES en cours et et sur la question du fichier KBART, qui dépend de l’action de l’éditeur lui-même.

 

Catherine STORNE,

Responsable du département du système d’information documentaire,

SCD de l’université de Strasbourg

Mettre nos données en réseau – un démonstrateur. [1] Introduction.

Ce démonstrateur est un plaidoyer en faveur d’une approche “web sémantique” de l’interopérabilité des données de l’IST. Mais, cette fois, il s’agit de montrer et non d’argumenter. Il s’agit de défendre, en illustrant cette approche par des études de cas. Alors, si vous fuyez les plaidoyers, si vous exigez du concret, de la donnée (RDF), de la requête (SPARQL), passez cette introduction et lisez l’un des billets suivants :

  1. Introduction (ce billet)
  2. Inventaire des données
  3. Suivez le guide ! Le modèle de données
  4. Études de cas

SPARQL endpoint : https://lod.abes.fr/sparql
Interface de recherche full text et de navigation : https://lod.abes.fr/fct

Pourquoi ce démonstrateur

Mettre nos données en réseau, c’est structurer et publier nos données conformément aux principes et aux bonnes pratiques du web sémantique.
Nos données, ce sont à la fois les données produites par les réseaux ABES (Sudoc, Sudoc PS, Thèses, Calames) mais également  toutes ces données voisines, complémentaires produites par les éditeurs, l’administration, les institutions culturelles, les institutions dédiées à l’information scientifique et technique (IST).
Ce périmètre est par définition extensible : par exemple, si nos données, ce sont d’abord les métadonnées de thèse électronique produites ou importées dans STAR, ce sont également les informations sur l’équipe de recherche (RNSR, HAL, IdRef), l’école doctorale (Ministère, IdRef), l’entreprise qui finance le contrat CIFRE (ANRT), les articles du doctorant (HAL et autres archives, éditeurs), la production du directeur de thèse (HAL, éditeurs), les vocabulaires contrôlés qui décrivent le contenu (RAMEAU, MeSH, tel vocabulaire spécialisé, etc.), les bibliothèques qui possèdent telle thèse, etc.
Second exemple : nos données, ce sont d’abord les métadonnées des articles acquis dans le cadre d’ISTEX (ISSN, Sudoc), mais ce sont également les métadonnées des revues, des fascicules et des volumes, les métadonnées des auteurs (IdRef, ISNI, VIAF, ORCID, HAL, Persée, Wikipedia, etc.), les affiliations, les vocabulaires contrôlés, les métadonnées sur le package commercial correspondant à l’acquisition (BACON, GoKB), la licence, les bibliothèques couvertes par la licence, etc.

lodcloud
Troisième et dernier exemple : pour savoir que tel auteur est affilié à l’université Paris 4, on a besoin de remonter le courant : de telle notice Sudoc à tel auteur IdRef, puis à tel auteur HAL, puis à tel document HAL, puis à telle équipe de recherche du référentiel HAL, puis à cette même équipe dans le référentiel RNSR, équipe rattachée à Paris 4. Il existe un chemin plus court, mais dans tous les cas, il faut être agile, rebondir d’une base à l’autre, d’un organisme à l’autre.
ist_organismes

L’information est par définition extensible. On ne peut définir a priori le périmètre des données qui correspond à nos besoins. La gestion de l’information doit être aussi extensible que l’information elle-même.
Et précisément, les technologies du web sémantique sont faites pour ça : établir des liens effectifs entre données complémentaires, sans fixer à l’avance ni le périmètre des données, ni la nature de ces liens.

Une base RDF + des requêtes SPARQL

Ce démonstrateur n’est rien d’autre que l’agrégation de données RDF brutes au sein d’une seule base de données. Si ce n’est préparer et documenter ces données, nous n’avons rien fait d’autre : ni construction d’index pour interroger les données, ni développement d’un web service de recherche, ni réalisation d’une interface graphique. Nous nous sommes contentés de charger ces données brutes dans une base RDF supportant le langage de requête SPARQL : ipso facto, nos données sont devenues interrogeables, consultables, navigables.

Pour interroger nos données, il suffit de se rendre à cette adresse : https://lod.abes.fr/sparql et de lancer une requête SPARQL. SPARQL est un langage très puissant, qui demande un apprentissage progressif. Mais tous les billets de cette série proposent des exemples de requête. Ce sont de bons points de départ. Si vous vous prenez au jeu, forgez vos propres requêtes et les jugez intéressantes, merci de les partager en commentaires.
SPARQL est un langage mais également un protocole web , c’est-à-dire un web service : https://lod.abes.fr/sparql n’est donc pas seulement une page web pour fans des données, mais également l’URL principale d’un web service de recherche qui permet à n’importe quel programme d’interroger une base RDF et d’en exploiter les résultats sous différents formats (HTML, XML, CSV, JSON, etc.). Grâce  à SPARQL, nous pourrons offrir une API standard pour interroger de manière sophistiquée les corpus ISTEX, par exemple, en complément de l’API de recherche développée par l’INIST. On a besoin des deux : une base de données ouverte et un moteur de recherche ouvert.
Si vous n’êtes ni un geek ni un programme, vous avez la possibilité de vous promener dans les données de notre base via cette interface, livrée avec le logiciel qui gère notre base de données : https://lod.abes.fr/fct. Chaque page de cette interface correspond à une entité de notre base (un article, une personne, un concept, etc.). Ainsi, la page https://lod.abes.fr/describe/?url=http://hub.abes.fr/springerB/ebook/3540183000/w décrit l’ebook identifié par : http://hub.abes.fr/springerB/ebook/3540183000/w. (Si vous activez cette URL, conformément aux principes des linked data (par TBL, il y a dix ans), vous serez redirigé vers une page qui décrit ce document : ne pas confondre la chose et sa description).
Cet ebook est caractérisé par des attributs (son titre, sa langue) et par des relations : relations vers les concepts dont parlent ce livre, relations vers l’éditeur, relations vers les auteurs (via le concept de contribution), etc. Ce sont ces relations qui permettent de naviguer d’entité en entité, comme on parcourt une encyclopédie. On croit naviguer d’une page à l’autre, mais en fait on navigue aussi d’une chose à l’autre : d’un laboratoire vers une personne, d’une personne vers un document, d’un document vers un concept, etc. De proche en proche, l’ensemble de ces relations constitue un réseau de données, un web de données.

Stratégie du coucou ? Pourquoi mettre tous ces données dans le même panier ?

Il sera naturel de soulever l’objection suivante : vous n’allez pas prétendre enfermer le web de données dans le monde clos de votre base ? Par définition, le web est décentralisé et il doit en être de même pour le web de données.
Cette objection est tout à fait légitime : il y a quelque chose d’artificiel à vouloir démontrer l’efficacité du web sémantique comme solution d’interopérabilité en rassemblant au sein d’une même base tous les jeux de données qu’on veut interconnecter et faire interagir. Nous justifions ainsi notre choix :
La plupart des données que nous voulions entrelacer n’existent pas (encore) sous forme RDF. On s’y est collé, à des fins pédagogiques.
Les solutions pour interroger un web de données décentralisé ne sont pas encore tout à fait mûres. SPARQL prévoit bien la recherche fédérée mais, quel que soit le type de technologies, ce type de recherche achoppe toujours sur les mêmes difficultés (disponibilités des bases à interroger, performances).
Il va de soi que ce n’est pas à l’ABES de produire, maintenir et publier en RDF les données du RNSR, de HAL, de Paris 4 ou d’ORCID, voire de Nature ou Springer (d’ailleurs, la plupart de ces initiatives sont précisément en train de construire leur offre de service RDF – disons, à notre connaissance, 4 sur 6 – nous vous laissons deviner). Ce qu’on espère c’est précisément un monde où les uns et les autres, sans concertation, sans négociation, sans plan quinquennal, font le pari du web sémantique et, comme par miracle, contribuent à construire un espace public de données, souvent complémentaires, parfois redondantes, parfois dissonantes.
Il ne s’agit pas de s’accorder entre nous (même si ça aide et fait plaisir), mais de s’accorder sur les mêmes bonnes pratiques internationales, sur l’état de l’art.

Affirmons à nouveau que chaque producteur est responsable de publier ses données et que le consommateur a le choix des moyens pour les exploiter : requête SPARQL fédérée, navigation à travers des browsers sémantiques, récupération de données en local (ne serait-ce que pour leur faire jouer le rôle d’un cache). Chaque solution a ses avantages et ses contextes d’utilisation privilégiés.

Caveat emptor

  • Ce démonstrateur est un démonstrateur.
  • Ce démonstrateur est vivant et donc périssable. Nous nous réservons le droit d’y ajouter des données, d’en retirer et même de le passer par pertes et profits.
  • Les URLs de ressources commençant par http://hub.abes.fr n’ont pas de durée de vie garantie. Encore moins les URLS pour les ressources de BACON,  HAL, de Persée ou du RNSR.
  • Certains jeux de données de la base sont complets (ORCID, Nature), d’autres ne sont que des échantillons (Annuaire Paris 4, Sudoc, IdRef, Oxford UP).
  • L’approche web sémantique n’est pas l’alpha et l’oméga de l’interopérabilité. A côté de la puissance de SPARQL, coûteuse et pas toujours performante, il y a de la place pour des API hyperspécialisées et hyperoptimisées, comme les micro web services du Sudoc ou d’IdRef.