96 votes

URL Slugify algorithme en C #?

J'ai donc cherché et parcouru à travers la limace tag sur SI et seulement trouvé deux solution attrayante:

Qui sont mais solution partielle à ce problème. Je pourrais manuellement le code de ce moi-même mais je suis surpris qu'il n'y a pas déjà une solution là-bas encore.

Alors, est-il un slugify alrogithm mise en œuvre en C# et/ou .NET que de traiter correctement les caractères latins, unicode et de divers autres problèmes de langue correctement?

180voto

Marcel Points 576

http://predicatet.blogspot.com/2009/04/improved-c-slug-generator-or-how-to.html

 public static string GenerateSlug(this string phrase) 
{ 
    string str = phrase.RemoveAccent().ToLower(); 
    // invalid chars           
    str = Regex.Replace(str, @"[^a-z0-9\s-]", ""); 
    // convert multiple spaces into one space   
    str = Regex.Replace(str, @"\s+", " ").Trim(); 
    // cut and trim 
    str = str.Substring(0, str.Length <= 45 ? str.Length : 45).Trim();   
    str = Regex.Replace(str, @"\s", "-"); // hyphens   
    return str; 
} 

public static string RemoveAccent(this string txt) 
{ 
    byte[] bytes = System.Text.Encoding.GetEncoding("Cyrillic").GetBytes(txt); 
    return System.Text.Encoding.ASCII.GetString(bytes); 
}
 

27voto

Joan Points 1090

Vous trouverez ici un moyen de générer un slug d’URL en c # . Cette fonction supprime tous les accents (la réponse de Marcel), remplace les espaces, supprime les caractères non valides, supprime les tirets de la fin et remplace les doubles occurrences de "-" ou "_"

Code:

 public static string ToUrlSlug(string value){

        //First to lower case
        value = value.ToLowerInvariant();

        //Remove all accents
        var bytes = Encoding.GetEncoding("Cyrillic").GetBytes(value);
        value = Encoding.ASCII.GetString(bytes);

        //Replace spaces
        value = Regex.Replace(value, @"\s", "-", RegexOptions.Compiled);

        //Remove invalid chars
        value = Regex.Replace(value, @"[^a-z0-9\s-_]", "",RegexOptions.Compiled);

        //Trim dashes from end
        value = value.Trim('-', '_');

        //Replace double occurences of - or _
        value = Regex.Replace(value, @"([-_]){2,}", "$1", RegexOptions.Compiled);

        return value ;
    }
 

19voto

dana Points 4890

Voici mon interprétation, en fonction de Jeanne et Marcel réponses. Les modifications que j'ai apportées sont comme suit:

  • Utiliser un largement acceptée méthode pour supprimer les accents.
  • Explicite de la Regex de la mise en cache de modestes améliorations de la vitesse.
  • Plus de séparateurs de mots reconnus et normalisés pour les traits d'union.

Voici le code:

public class UrlSlugger
{
    // white space, em-dash, en-dash, underscore
    static readonly Regex WordDelimiters = new Regex(@"[\s-–_]", RegexOptions.Compiled);

    // characters that are not valid
    static readonly Regex InvalidChars = new Regex(@"[^a-z0-9\-]", RegexOptions.Compiled);

    // multiple hyphens
    static readonly Regex MultipleHyphens = new Regex(@"-{2,}", RegexOptions.Compiled);

    public static string ToUrlSlug(string value)
    {
        // convert to lower case
        value = value.ToLowerInvariant();

        // remove diacritics (accents)
        value = RemoveDiacritics(value);

        // ensure all word delimiters are hyphens
        value = WordDelimiters.Replace(value, "-");

        // strip out invalid characters
        value = InvalidChars.Replace(value, "");

        // replace multiple hyphens (-) with a single hyphen
        value = MultipleHyphens.Replace(value, "-");

        // trim hyphens (-) from ends
        return value.Trim('-');
    }

    /// See: http://www.siao2.com/2007/05/14/2629747.aspx
    private static string RemoveDiacritics(string stIn)
    {
        string stFormD = stIn.Normalize(NormalizationForm.FormD);
        StringBuilder sb = new StringBuilder();

        for (int ich = 0; ich < stFormD.Length; ich++)
        {
            UnicodeCategory uc = CharUnicodeInfo.GetUnicodeCategory(stFormD[ich]);
            if (uc != UnicodeCategory.NonSpacingMark)
            {
                sb.Append(stFormD[ich]);
            }
        }

        return (sb.ToString().Normalize(NormalizationForm.FormC));
    }
}

Ce n'est toujours pas résolu non latine question de caractère. Un tout autre solution serait d'utiliser des Uri.EscapeDataString pour convertir la chaîne de sa représentation hexadécimale:

string original = "测试公司";

// %E6%B5%8B%E8%AF%95%E5%85%AC%E5%8F%B8
string converted = Uri.EscapeDataString(original);

Ensuite utiliser ces données pour générer un lien hypertexte:

<a href="http://www.example.com/100/%E6%B5%8B%E8%AF%95%E5%85%AC%E5%8F%B8">
    测试公司
</a>

De nombreux navigateurs afficher des caractères Chinois dans la barre d'adresse (voir ci-dessous), mais d'après mon test limitée, il n'est pas complètement pris en charge.

address bar with Chinese characters

REMARQUE: pour Uri.EscapeDataString travailler de cette façon, iriParsing doit être activé.


MODIFIER

Pour ceux qui cherchent à générer l'URL de Limaces en C#, je vous recommandons de vérifier cette question:

Comment Débordement de Pile générer son SEO-friendly URLs?

C'est ce que j'ai utilisé pour mon projet.

5voto

mgroves Points 8550

Un problème que j'ai eu avec slugification (nouveau mot!) Est des collisions. Si j'ai un article de blog, par exemple, appelé "Stack-Overflow" et un autre appelé "Stack Overflow", les slugs de ces deux titres sont les mêmes. Par conséquent, mon générateur de slug doit généralement impliquer la base de données d'une manière ou d'une autre. C'est peut-être pourquoi vous ne voyez pas de solutions plus génériques sur le marché.

-1voto

C.Evenhuis Points 10818

L '"algorithme" que j'ai vu avec sofar consiste simplement à utiliser une table de remplacements de / à, et à filtrer les caractères restants (par exemple, "l'alphabet" chinois dans son ensemble).

Si vous utilisez Encoding.ASCII.GetString (Encoding.ASCII.GetBytes (unicodeString)), vous filtrerez tous les caractères à l'exception des caractères ASCII de base. Les autres personnages sont convertis en points d'interrogation. Quelque chose comme ça:

 Dictionary<char, char> lReplaceValues = new Dictionary<char, char>();
lReplaceValues['ä'] = 'a';
lReplaceValues['ö'] = 'o';
lReplaceValues['ë'] = 'e';

string lSlug = "Hëllö wórld!";
foreach (KeyValuePair<char, char> lReplaceValue in lReplaceValues)
{
    lSlug = lSlug.Replace(lReplaceValue.Key, lReplaceValue.Value);
}
lSlug = Encoding.ASCII.GetString(Encoding.ASCII.GetBytes(lSlug));
 

Il doit y avoir une manière plus élégante, d'ailleurs.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X