Retirer le nom de l'auteur colle en fin de titre BnF
Cas mesure, ISBN 9782749942636 : dc:title = "Le plus grand defi ... (Nouvelle ed. augmentee) Aurélien Barrau" dc:creator = "Barrau, Aurélien (1973-....). Auteur du texte" Le nom est recolle en fin de titre sans le separateur ISBD « / », donc la regle de nettoyage existante ne peut rien y faire : la notice est sale a la source. L'heuristique est volontairement stricte — comparaison en fin de chaine uniquement, contre un auteur deja nettoye, et seulement si le nom commence sur une frontiere de mot. « Lettre a Émile Zola » n'est pas touche, et un titre qui EST le nom de l'auteur (biographie, recueil) est laisse intact plutot que reduit a rien. La comparaison passe par CompareOptions.IgnoreNonSpace plutot que par une normalisation NFD : elle ignore les accents sans changer les longueurs, donc les indices calcules restent valables sur la chaine d'origine. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
using System.Globalization;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace MaBibli.Api.Services.Isbn;
|
||||
@@ -43,6 +44,71 @@ public static partial class NettoyageIsbd
|
||||
return s.Length == 0 ? null : s;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retire du titre le nom d'auteur qui y est collé en fin de chaîne.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Cas réel mesuré, ISBN <c>9782749942636</c> :
|
||||
/// <c>dc:title</c> vaut « Le plus grand défi … (Nouvelle éd. augmentée) <b>Aurélien Barrau</b> »
|
||||
/// alors que <c>dc:creator</c> vaut « Barrau, Aurélien (1973-....) ». Le nom est recollé
|
||||
/// <b>sans</b> le séparateur ISBD « / », donc <see cref="Titre"/> ne peut rien y faire : la
|
||||
/// notice est sale à la source.
|
||||
/// <para>
|
||||
/// L'heuristique est volontairement stricte — comparaison en <b>fin de chaîne</b> uniquement,
|
||||
/// et seulement contre un auteur déjà nettoyé. Un titre qui contient légitimement un nom de
|
||||
/// personne ailleurs (« Lettre à Émile Zola ») n'est pas touché, et un titre qui <i>est</i>
|
||||
/// le nom de l'auteur (biographie, recueil) est laissé intact plutôt que réduit à rien.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public static string? RetirerAuteurEnFin(string? titre, IEnumerable<string?> auteurs)
|
||||
{
|
||||
var s = titre?.Trim();
|
||||
if (string.IsNullOrEmpty(s))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
foreach (var auteur in auteurs)
|
||||
{
|
||||
var nom = auteur?.Trim();
|
||||
if (string.IsNullOrEmpty(nom) || nom.Length >= s.Length)
|
||||
{
|
||||
// Un nom aussi long que le titre ne laisserait rien : c'est une biographie
|
||||
// ou un recueil, pas une notice sale.
|
||||
continue;
|
||||
}
|
||||
|
||||
var debut = s.Length - nom.Length;
|
||||
|
||||
// IgnoreNonSpace ignore les accents sans changer les longueurs, contrairement à une
|
||||
// normalisation NFD : les indices calculés restent valables sur la chaîne d'origine.
|
||||
var identique = string.Compare(
|
||||
s, debut, nom, 0, nom.Length,
|
||||
CultureInfo.InvariantCulture,
|
||||
CompareOptions.IgnoreCase | CompareOptions.IgnoreNonSpace) == 0;
|
||||
|
||||
if (!identique)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Le nom doit commencer sur une frontière de mot, sinon « …Barrau » couperait aussi
|
||||
// dans un mot qui se termine par les mêmes lettres.
|
||||
if (char.IsLetterOrDigit(s[debut - 1]))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var reste = s[..debut].TrimEnd(' ', ',', ';', '.', '-', '/', ':');
|
||||
if (reste.Length > 0)
|
||||
{
|
||||
return reste;
|
||||
}
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Auteur : retirer les dates entre parenthèses, le rôle qui suit le point,
|
||||
/// puis inverser « Nom, Prénom » en « Prénom Nom ».
|
||||
|
||||
Reference in New Issue
Block a user