Identifier les auteurs de HAL avec IdRef

logo-idref   C’est une histoire déjà ancienne à l’Abes que celle de l’identification automatique des Personnes impliquées dans des ressources documentaires. Du moins, est-ce un sujet qui, depuis plusieurs années, aiguillonne des études et aboutit progressivement à des réalisations intéressantes. En voici une illustration avec des corpus extraits de HAL.

Corpus SHS – 2011

Entre octobre 2010 et novembre 2011, dans le cadre du projet SudocAd, un premier prototype a été développé avec pour objectif l’enrichissement des métadonnées du moteur de recherche ISIDORE par l’ajout de lien aux autorités Sudoc (IdRef). Le prototype exploita un échantillon de 13 444 notices d’articles issues du portail Persée – domaine «Économie » – en identifiant, quand elle existait, l’autorité IdRef correspondant à chacun des auteurs. Une fois traitées, les notices furent livrées à ADONIS et à l’équipe Persée. Côté performance, le prototype SudocAD atteignait un très bon niveau : sur un échantillon vérifié de 150 notices Persée, 80% étaient estimées comme de « bonnes décisions » (liage ou non liage), et surtout, le taux d’erreur (création de liens erronés) était inférieur à 2%.

Corpus SHS – septembre 2015

Depuis, le projet Qualinca a repris le flambeau, avec une approche plus globale. En septembre 2015, une nouvelle expérimentation d’identification automatique est menée sur un corpus de HAL : 1 900 documents du domaine SHS sont puisés dans l’entrepôt OAI-PMH. Après traitement, 3 200 formes-auteurs sont extraites et passées à la moulinette du prototype. Lors du développement de l’outil, seuls 2 critères de matching -appelés également dans ce cadre « heuristiques »- sont utilisés (« co-auteur » et « unica »). Sur la base de ces critères,  1 100 entités – soit 34% des formes-auteurs – seront matchées, puis rattachées à une notice d’autorité dûment identifiée.

Corpus Astrophysique – avril 2016

Les disciplines ayant des pratiques de publication fort diverses, le choix s’est porté sur le traitement de 300 articles issus du domaine « Astrophysique » et leurs 1 242 formes-auteurs.  L’astrophysique étant un domaine dans lequel les publications sont hautement internationalisées, la proportion d’auteurs étrangers y est importante. De plus, l’interdisciplinarité y étant élevée, on trouvera parmi les auteurs des chercheurs physiciens, biologistes, ingénieurs, océanographes, chimistes, mathématiciens…

La qualité de l’identification finale dépendant largement de la qualité des données de départ, on notera que les données en entrée sont majoritairement de qualité basse, un aspect amplifié par l’absence de normalisation dans l’écriture des appellations. Quelle sera l’incidence de ces variantes orthographiques sur la couverture du corpus par IdRef ?

Le corpus comportait : 406 appellations d’auteur avec nom + prénom (soit 33%) et 836 appellations d’auteur avec nom + initiale du prénom (soit 66%). Les 1 242 formes-auteurs ont d’abord été ramenées à 1 156, suite à la suppression de 43 doublons évidents (avec accent vs. sans accent ; initiale du Prénom vs. Prénom développé).

Premier  constat : le prototype a appris à gérer de façon très satisfaisante ce paramètre de variabilité des graphies. Ainsi, 467 appellations (soit 37,6%) ont été identifiées avec les heuristiques «co-auteur», «titre» et «unica» – pour ce dernier critère, les appellations « Nom, P. » furent mises de côté. Second constat : sur les 775 appellations restantes, 57 -soit 4,6%- correspondaient à des auteurs dont des homonymes ont été correctement écartés par la machine. Afin de tester la couverture d’IdRef, une deuxième passe a ensuite été effectuée, sous forme d’une recherche manuelle rapide, qui a permis d’identifier 95 auteurs supplémentaires.
En valeur absolue,  autant d’auteurs avec « Nom, Prénom » qu’avec « Nom, P. » ont été identifiés. En valeur relative, le résultat est évidemment en faveur des auteurs avec « Nom, Prénom » – 66 % – contre 33% pour les auteurs avec « Nom, P. »  Dans ce cas également, le fait de disposer de notices d’autorité est très intéressant puisque dans la majorité des cas d’appellations avec « Nom, P. »,  le prénom développé a été retrouvé. Ces éléments permettent d’estimer le potentiel de clusterisation apportée par une notice d’autorité grâce aux variantes de formes.

Au final, ce sont 561 auteurs qui ont été identifiés, soit 45% d’identification des auteurs du corpus Astrophysique de HAL. A titre de comparaison, on remarquera que les requêtes lancées sur AuréHAL  sur les formes-auteurs présentes, en demandant pour chacune si elle correspondait à une forme présente dans un idHal, a donné un résultat de seulement 3,5 % des appellations du corpus « Astrophysique ».

Corpus idHal – janvier 2017

Le corpus idHal – identifiants uniques gérés dans HAL- en progression continue, constitue un nouvel enjeu majeur en termes d’alignement d’identifiants – notamment sur fond de projet Conditor. L’exploitation de ce service de HAL est importante à plusieurs égards : outre la sensibilisation auprès des chercheurs quant à la question de l’identification pérenne et unique, idHal permet de tirer parti du travail de validation d’attribution de publication réalisés par les chercheurs eux-mêmes.
Récemment,  un alignement vers IdRef des auteurs – publiant dans HAL et disposant d’un idHAL- a été tenté. En 5 étapes, cela a donné :
1)    identifier tous les auteurs HAL ayant un idHal
2)    récupérer les documents liés à ces idHal
3)    les convertir et les charger dans la base RDF de l’Abes
4)    lancer les heuristiques d’alignements
5)    extraire les premiers résultats : 11 000 auteurs à lier pour 6 400 alignés ( soit 58,2 %)

Ainsi, grâce aux puissants algorithmes d’alignement élaborés en interne, une bonne partie du chemin semble parcourue. Mais aller plus loin – beaucoup plus loin !-  est envisageable. En effet, il est désormais tout à fait possible de lancer les heuristiques sur l’intégralité de HAL.

De belles perspectives

Depuis 2010 à l’Abes, les avancées de la réflexion et des outils en matière de données d’autorité ont construit une approche intellectuellement et technologiquement performante, ce qui permet  de promouvoir, désormais preuves à l’appui, l’offre de service d’IdRef auprès des opérateurs de l’IST en France.
En effet, si le taux de couverture des auteurs de publications de recherche est proche de 50%, il est de l’ordre de 90% pour les auteurs français – ce qui confirme la portée réelle d’IdRef en termes de référentiel des auteurs de l’Enseignement Supérieur et de la Recherche.
Dans les mois à venir, le programme de travail ira en ce sens. La consolidation des process constitue l’axe prioritaire : il s’agira tout d’abord de les automatiser intégralement afin de moissonner de très gros volumes de données. La redistribution de ces alignements constitue le second axe.

Sur le même concept que le web service de récupération des alignements – idref2id,  le stock d’alignements disponibles va s’accroitre  pour mettre en vitrine tout ce que nous avons déjà en « arrière-boutique ». De belles perspectives donc.

François Mistral, responsable IdRef

STAR : les statistiques 2016

starDepuis l’ouverture en 2006 de l’application nationale STAR, développée suite à l’arrêté du 7 août 2006  relatif aux modalités de dépôt, de signalement, de reproduction, de diffusion et de conservation des thèses électroniques, outre la garantie d’un signalement et d’un archivage numérique fiable,  c’est bien également in fine la valorisation et la diffusion des thèses françaises que le dispositif mis en œuvre par l’Abes soutient. Un dispositif qui devrait se renforcer suite à la parution de l’arrêté du 25 mai 2016  rendant obligatoire le dépôt de la thèse dans sa version électronique  pour tous les établissements à partir du 1er septembre 2016. 

Outre un éclairage original sur la richesse de la production et sur la dynamique de diffusion des « documents Thèses », la publication des statistiques 2016 se veut un indicateur d’activité au service des établissements membres du réseau Star.

Volumétrie de la base de données STAR

Au 1er janvier 2017,  56 287 thèses déposées et archivées  sont recensées dans la base de données STAR/CINES. On constate que, depuis 3 ans, le volume de thèses traitées annuellement tend à se stabiliser autour de 10 000 thèses par an – 11 258 en 2016 pour être précis. Il est prévisible que cette moyenne augmente sensiblement en fonction du nouvel arrêté rendant le dépôt électronique des thèses obligatoire.

depot-annuel

Indicateurs d’activité dans STAR

Calculée en fonction du nombre de thèses traitées, l’activité dans l’application STAR se caractérise par un relatif lissage tout au long de l’année. Cependant, tout comme en 2015, on constate un léger pic d’activité lors du premier trimestre de l’année civile.

Le délai de traitement moyen d’une thèse dans STAR, donnée statistique présente dans l’application de pilotage Webstats, est calculé en fonction de l’écart entre  la date de soutenance et la date de validation finale.  Alors qu’en 2015 ce délai de traitement était en moyenne de 293 jours,  il est de 317  jours en 2016.

ration-mensuel

delai-traitement

Diffusion des thèses : l’accès libre largement privilégié

Illustration d’une belle dynamique d’ouverture et de libre accès,  le pourcentage de thèses déposées dans STAR diffusées sur Internet, stable depuis 2013, est évalué à 75%. On note qu’est privilégiée la diffusion des thèses sur plusieurs plateformes en simultané, cette diffusion s’appuyant sur la plateforme Thèses-en-Ligne (TEL) du CCSD, la plateforme des établissements de soutenance et la plateforme ABES.

Signe que les automatisations introduites entre les différents systèmes -et notamment entre STAR et TEL –  favorisent la politique de dépôt en open access ?  Quoiqu’il en soit, comme l’indiquent les statistiques publiées récemment par le CCSD, en 2016, on peut se réjouir que 72% des thèses déposées dans TEL – soit 5 731 thèses – l’aient été à partir de l’application STAR.  En 2014,  cela ne représentait que 39% des cas…

Type de diffusion

diffusion

plate-forme

Olivier CIAN, responsable fonctionnel de l’application STAR

 

Calames : les statistiques 2016

calamesTout en inaugurant la prise de relais entre le blog Calames, qui cesse ses publications en ce début d’année, et  Punktokomo, blog technique de l’ABES, ce billet vise prioritairement à fournir aux établissements membres du réseau Calames des éléments complémentaires aux statistiques générales accessibles via l’application Webstats.

Les statistiques présentées ici  fournissent des tendances et des indicateurs, mais ne prétendent pas donner d’information sur la qualité, la précision, la pertinence des encodages adoptés, ni sur la part de travail récurrent ou rétrospectif touchant des niveaux descriptifs pré-existants. En effet, le caractère hybride de l’instrument de recherche EAD – partagé entre la volonté de mettre en forme des documents et la tendance à l’usage de référentiels et autres données destinés aux traitements informatiques –  explique en partie cette difficulté à prendre tout le recul souhaitable sur ces ensembles de fichiers : bien souvent, seul un regard humain est à même de juger complètement de la qualité des encodages. Ces diagrammes sectoriels sont néanmoins des témoins sûrs de l’implication des établissements dans le signalement de leurs archives et manuscrits, de leur importance dans le paysage patrimonial de l’ESR en général et dans la vie du réseau Calames en particulier.

État de la base publique Calames au 31 décembre 2016

Répartition du 3/4 de million de composants publiés dans Calames par établissements

repartition-c-publies-fin-2016-par-rcr

Répartition des composants publiés dans Calames par origine (rétroconversions nationales originelles ou production/ attribution d’ID par l’outil)

originedonneescalames2016

Répartition  des composants publiés dans Calames par cercles de déploiement (1er cercle déployé en 2008, 7e et 8e cercles en 2014)

repartition-c-publies-fin-2016-par-cercles

Nouvelles données publiées dans Calames en 2016

La quantité de données nouvellement publiées est restée notablement élevée en 2016, bien que le surcroît soit moins spectaculaire qu’en 2015 et qu’il soit beaucoup plus également réparti entre une bonne dizaine de sources de signalement. origine-surcroit-c-publies-courant-2016

Neuf ans après son lancement, Calames dépasse ainsi les trois quarts de million de niveaux descriptifs publiés :

evolution-c-publies-2007-2016

Travaux de catalogage dans l’outil Calames Prod en 2016

La quantité de <c> nouvellement identifiés par l’outil Calames est très proche du niveau de l’année précédente : environ 126.000 composants ont été créés courant 2016 par le réseau Calames.

On constate que très peu d’établissements dérogent à la recommandation de cataloguer en-dehors de la base de production (env. 4000 <c> répondent à ce cas de figure après analyse), et le cas n’échoit que pour de bonnes raisons (emplois d’exports spécifiques ou volonté de faire des publications tests notamment).
Les 5 établissements ayant créé la plus grande quantité de niveaux descriptifs dans Calames depuis son origine sont ceux-là mêmes qui représentent à eux seuls plus de 60% des données actuellement publiées : Muséum National d’Histoire Naturelle (158067 <c> créés dans l’outil depuis 2008), BDIC (110203), Institut de France (86941), Bibliothèque Littéraire Jacques Doucet (65668) et Académie de Médecine (60648).

catalogage-dans-calames-2016

Depuis l’an dernier, nous disposons d’une statistique certes un peu complexe, mais complémentaire à la précédente, qui nous renseigne sur la fréquence du recours à l’outil de catalogage Calames Prod (au-delà du seul nombre de nouveaux <c> créés). Le graphique ci-dessous doit être ainsi lu : en 2016, la BLJD a effectué 839 interventions quotidiennes sur fichiers EAD unitaires (ou 839 « jours-fichiers »).

L’existence pour un même établissement d’un grand nombre de fichiers EAD favorise certes l’élévation des chiffres, quelques établissements ayant à gérer des dizaines d’instances distinctes. Le graphique témoigne aussi, en comparaison de 2015, d’un recours à la fois plus intense et fréquent à l’outil Calames Prod (plus de 1100 jours-fichiers supplémentaires pour une quantité de composants créés équivalente) ainsi que d’une part non négligeable de travaux rétrospectifs (retours sur des instances dont l’architecture au moins avait été créée les années précédentes).

temps-frequence-catalogage-calames-2016

Ventilation de 9  années de catalogage -aussi bien en production qu’en publication/indexation- dans Calames

production-c-2008-2016

Le décalage entre ces deux représentations des composants créés via l’outil Calames (<c> publiés / <c> créés) est une donnée structurelle depuis plusieurs années : de l’ordre de 100.000 composants présents mais n’ayant jamais connu de première publication. Les <c> créés en base de formation ont été « purgés » au maximum des rebuts, données de tests, et doublons de fait (ID différents mais données identiques à des niveaux descriptifs publiés en base de production). A noter aussi, une forte tendance à l’accélération des publications d’inventaires, puisque seuls 1/4 des <c> créés en 2016 n’ont pas connu de première indexation à la fin de leur année de naissance.

Statistiques de consultation 

Comme en 2015, la hausse continue de la quantité de données exposées, ainsi que plusieurs épisodes de popularité liés aux recherches ponctuelles de certains mots-clés sur les moteurs de recherche généralistes, se sont soldés par un nombre de visites sur le catalogue public en sensible accroissement.

Ainsi, la moyenne annuelle est de l’ordre de 16 000 visites/mois (soit 5.000 de plus qu’en 2013-2014) ; un phénomène corollaire est la recrudescence du « zapping » des internautes (durées moyennes de visites raccourcies), mais en restant bien loin des niveaux liés au sur-référencement que la nouvelle interface Calames avait connu dans ses premiers mois d’existence.

Jean-Marie Feurtet, responsable Calames

Webservice AlgoLiens : remédier à l’absence de liens dans les données du Sudoc

imagealogoliens

Expo Asterix BNF / Manuel F. Picaud / CC BY-NC-SA 2.0, via Flickr

L’ABES vient de mettre en production un nouveau web service, baptisé AlgoLiens. Ce dernier détecte les notices du Sudoc dans lesquelles une zone de liens aux autorités n’est pas liée. En mettant à la disposition de leurs créateurs les notices présentant une telle anomalie afin de les amener à la corriger, l’objectif est d’atteindre à un signalement documentaire total.

A l’origine d’AlgoLiens, nouvel outil à la disposition des catalogueurs du réseau Sudoc, se trouve une question que plus d’une fois nous nous sommes collectivement posée : comment améliorer les données du Sudoc ? Cette question à peine énoncée, le doute s’instille. Finalement, est-ce tout simplement possible ? Ecrasante, la recherche de la réponse est repoussée à un horizon de pieuse espérance habité par de dociles machines… Pourtant, insistons car le jeu, en vaut la chandelle et répond à quatre enjeux MAJEURS :

  • l’exhaustivité du signalement catalographique,
  • la valorisation scientifique de l’IST,
  • la valorisation patrimoniale des BU,
  • la contribution des données Sudoc au Web de données liées.

Commençons par rendre la question moins effrayante : comment approcher la notion de qualité du catalogue Sudoc et prendre à bras le corps les anomalies qu’immanquablement les données contiennent ? Avec le webservice Algoliens, la porte d’entrée retenue concerne les zones de liens aux notices d’autorité. En effet, les notices d’autorité ont pour fonction de normaliser les points d’accès autorisés des notices – bibliographiques et d’autorités. De plus, elles recensent les variantes de formes. Enfin, elles ont vocation, dans les notices bibliographiques comme dans les notices d’autorité, à être liées à tous les points d’accès.

Conçu sous forme d’un web service, AlgoLiens détecte les notices dans lesquelles une zone de lien n’est pas liée. Ce servicepermet de générer à la demande un « rapport d’absence de liens dans les zones de lien du Sudoc » qui se présente sous forme d’un fichier .csv contenant les résultats des tests de l’algorithme.

L’algorithme porte, en premier lieu, sur la présence d’un lien situé dans les zones de lien des notices. Mais il fait bien plus en permettant de croiser de nombreux critères. Il est ainsi possible de filtrer les résultats souhaités par établissement, depuis une date fixée, pour un type de document précis, pour les unicas uniquement.

Voici par exemple la requête qui permet de remonter les notices des documents imprimés créées et modifiées par l’ILN 100 depuis le 10 mars 2015 dans lesquels des zones d’indexation ne sont pas liées :

http://www.idref.fr/AlgoLiens?typdoc=Aa&iln=100&code=B60X&date=20150310

Pour chaque PPN en anomalie, le catalogueur est invité à corriger la notice dans WinIBW ou IdRef. Le rapport dynamique lui suggère d’intervenir à tel ou tel endroit de la notice :

Aujourd’hui, des dizaines de milliers d’anomalies sont détectées. Face à l’ampleur de la tâche, il est nécessaire d’organiser le travail de correction. En utilisant des paramètres dans l’url de génération du rapport dynamique, il est possible de définir des lots personnalisés.

La documentation de ce webservice est disponible à cette adresse. Le J-e.cours de présentation de ce service qui a eu lieu le 1er décembre 2016 est accessible sur notre plateforme de formation.

Nous espérons que ce webservice sera l’occasion pour les établissements de mettre en place des chantiers de corrections ciblés, à l’instar de la démarche CERCLES. Et si vous ne savez pas par où commencer, songez à vos corpus préférés, vos petits trésors documentaires ou vos unicas… et testez des requêtes !!!

De son côté, l’ABES utilisera AlgoLiens pour suivre l’avancement des corrections de manière globale. De même, elle s’en servira pour déterminer des corpus pertinents sur lesquels l’apport d’algorithmes correctifs s’avérerait pertinent.

Enfin, un jour – que nous espérons le plus proche possible, ce webservice deviendra inutile car l’algorithme ne détectera plus aucune anomalie. Ce jour, nous pourrons être encore plus fiers du travail collectif accompli.

François Mistral, responsable du référentiel IdRef

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.

Cyril Leroy

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