Question

Le EST CE QUE JE Le système n'impose fondamentalement aucune limitation utile sur ce qui constitue un identifiant raisonnable.Cependant, être capable d'extraire des DOI de fichiers PDF, de pages Web, etc.est très utile pour les informations de citation, etc.

Existe-t-il un moyen fiable d'identifier un DOI dans un bloc de texte sans utiliser le préfixe « doi : » ?(n'importe quelle langue acceptable, les expressions régulières sont préférées et il est indispensable d'éviter les faux positifs)

Était-ce utile?

La solution

Ok, j'extrais actuellement des milliers de DOI à partir de texte libre (XML) et j'ai réalisé que mon approche précédente J'ai eu quelques problèmes, notamment concernant les entités codées et la ponctuation finale, j'ai donc continué à lire la spécification et c'est le mieux que je puisse proposer.


Le préfixe DOI doit être composé d’un indicateur de répertoire suivi de un code de titulaire.Ces deux composantes doivent être séparées par un stop (point final).

L'indicateur d'annuaire doit être "10".L’indicateur d’annuaire distingue l’ensemble des chaînes de caractères (préfixe et suffixe) en tant qu’identificateurs d’objets numériques dans le système de résolution.

Assez simple, l'initiale \b nous empêche de "faire correspondre" un "DOI" qui ne commence pas par 10.:

$pattern = '\b(10[.]';

Le deuxième élément du préfixe DOI sera le code du déclarant.Le Le code du titulaire est une chaîne unique attribuée à un titulaire.

De plus, tous les codes de déclarant attribués sont numériques et comportent au moins 4 chiffres, donc :

$pattern = '\b(10[.][0-9]{4,}';

Le code du titulaire peut être divisé en sous-éléments pour commodité administrative si vous le souhaitez.Chaque sous-élément de l' Le code du titulaire doit être précédé d’un point.

$pattern = '\b(10[.][0-9]{4,}(?:[.][0-9]+)*';

La syntaxe DOI doit être composée d’un préfixe DOI et d’un suffixe DOI séparés par une barre oblique.

Cependant, ce n'est pas absolument nécessaire, la section 2.2.3 indique que les systèmes de suffixes peu courants peuvent utiliser d'autres conventions (telles que 10.1000.123456 au lieu de 10.1000/123456), mais réduisons un peu le temps.

$pattern = '\b(10[.][0-9]{4,}(?:[.][0-9]+)*/';

Le nom DOI n’est pas sensible à la casse et peut incorporer n’importe quel caractères des caractères graphiques légaux d’Unicode.Le DOI suffixe doit être constitué d’une chaîne de caractères de n’importe quelle longueur choisie par le Déclarant.Chaque suffixe doit être unique à l’élément de préfixe qui le précède.Le suffixe unique peut être un nombre séquentiel, ou il peut incorporer un identificateur généré à partir d’un autre système ou basé sur celui-ci.

Maintenant, c'est là que ça devient plus délicat, parmi tous les DOI que j'ai traités, j'ai vu les caractères suivants (en plus [0-9a-zA-Z] bien sûr) dans leur suffixes: .-()/:- -- donc, même s'il n'existe pas, le DOI 10.1016.12.31/nature.S0735-1097(98)2000/12/31/34:7-7 est tout à fait plausible.

Le choix logique serait d'utiliser \S ou la [[:graph:]] Classe PCRE POSIX, alors faisons ça :

$pattern = '\b(10[.][0-9]{4,}(?:[.][0-9]+)*/\S+'; // or
$pattern = '\b(10[.][0-9]{4,}(?:[.][0-9]+)*/[[:graph:]]+';

Nous sommes maintenant confrontés à un problème difficile, le [[:graph:]] la classe est un super-ensemble de [[:punct:]] classe, qui comprend des caractères faciles à trouver dans le texte libre ou dans n'importe quel langage de balisage : "'&<> entre autres.

Filtrons simplement ceux du balisage pour l'instant en utilisant une analyse anticipée négative :

$pattern = '\b(10[.][0-9]{4,}(?:[.][0-9]+)*/(?:(?!["&\'<>])\S)+'; // or
$pattern = '\b(10[.][0-9]{4,}(?:[.][0-9]+)*/(?:(?!["&\'<>])[[:graph:]])+';

Ce qui précède devrait couvrir les entités codées (&), les guillemets d'attribut (["']) et ouvrir/fermer les balises ([<>]).

Contrairement aux langages de balisage, le texte libre n'utilise généralement pas de caractères de ponctuation à moins qu'ils ne soient délimités par au moins un espace. ou placé à la fin d'une phrase, par exemple :

Il s'agit d'un long DOI : 10.1016.12.31/nature.S0735-1097(98)2000/12/31/34:7-7!!!

La solution ici est de fermer notre groupe de capture et d'affirmer une autre limite de mots :

$pattern = '\b(10[.][0-9]{4,}(?:[.][0-9]+)*/(?:(?!["&\'<>])\S)+)\b'; // or
$pattern = '\b(10[.][0-9]{4,}(?:[.][0-9]+)*/(?:(?!["&\'<>])[[:graph:]])+)\b';

Et voilà, voici une démo.

Autres conseils

@Silas La vérification de la santé mentale est une bonne idée.Cependant, l'expression régulière ne couvre pas tous les DOI.Le premier élément doit (actuellement) être 10, et le deuxième élément doit (actuellement) être numérique, mais le troisième élément est à peine restreint :

"Les caractères légaux sont les caractères graphiques légaux d'Unicode.Cela exclut spécifiquement les plages de caractères de contrôle 0x00-0x1F et 0x80-0x9F..."

et c'est là que réside le vrai problème.Dans la pratique, je n'ai jamais vu d'espaces utilisés, mais la spécification le permet spécifiquement.Fondamentalement, il ne semble pas y avoir de moyen sensé de détecter le fin d'un DOI.

CrossRef a une recommandation, qu'ils ont testé avec succès sur 99,3% des DOI :

/^10.\d{4,9}/[-._;()/:A-Z0-9]+$/i

Je suis sûr que ce n'est pas très utile pour le PO à ce stade, mais j'ai pensé que je publierais ce que j'essaie au cas où quelqu'un d'autre comme moi tomberait sur ceci :

(10.(\d)+/(\S)+)

Cela correspond :"Un numéro à 10 points coupe tout ce qui n'est pas un espace"

Mais pour mon utilisation (grattage HTML), il s'agissait de trouver des faux positifs, j'ai donc dû faire correspondre ce qui précède, en plus de me débarrasser des guillemets et des valeurs supérieur/inférieur à :

(10.(\d)+/([^(\s\>\"\<)])+)

Je suis encore en train de les tester, mais j'ai bon espoir jusqu'à présent.

Voici mon essai :

(10[.][0-9]{4,}[^\s"/<>]*/[^\s"<>]+)

Et quelques cas limites valides où cela n'échoue pas, mais d'autres semblent le faire :

En outre, supprime correctement certains éléments faux (X|HT)ML tels que :

  • <geo coords="10.4515260,51.1656910"></geo>

C'est une question très ancienne et sans réponse, mais voici un autre substitut potentiel.

\b10\.(\d+\.*)+[\/](([^\s\.])+\.*)+\b

Cela suppose que les espaces blancs ne font pas partie du DOI.

Je n'ai pas testé cela pour les faux positifs, mais il semble être capable de trouver tous les cas extrêmes mentionnés dans cette page.

L'expression régulière suivante devrait faire l'affaire (syntaxe regex Perl) :

/(10\.\d+\/\d+)/

Vous pouvez effectuer des vérifications supplémentaires en ouvrant les URL.

http://hdl.handle.net/<doi>

et

http://dx.doi.org/<doi>

où est le candidat doi,

et tester que vous a) obtenez un statut http 200 OK, et b) la page renvoyée n'est pas la page "DOI introuvable" pour le service.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top