Как удалить недопустимые символы при создании удобного URL-адреса (например, как создать ярлык)?

Скажем, у меня есть эта веб-страница:
http://ww.xyz.com/Product.aspx?CategoryId=1

Если имя CategoryId = 1 - "Dogs", я хотел бы преобразовать URL-адрес в нечто вроде этого:
http://ww.xyz.com/Products/Dogs

Проблема в том, что название категории содержит посторонние (или недопустимые для URL-адреса) символы. Если имя CategoryId = 2 - «Göra äldre», каким должен быть новый URL?

Логически это должно быть:
http://ww.xyz.com/Products/G%C3%B6ra äldre
но это не сработает. Во-первых, из-за пробела (который я легко могу заменить, например, тире), но как насчет иностранных символов? В Asp.net я мог бы использовать функцию URLEncode, которая выдала бы что-то вроде этого:
http://ww.xyz.com/Products/G%c3%b6ra+%c3%a4ldre
но я не могу сказать, что он лучше исходного URL (http://ww.xyz.com/Product.aspx?CategoryId=2)

В идеале я хотел бы сгенерировать этот, но как я могу сделать это автоматически (т.е. преобразовать иностранные символы в «безопасные» символы URL-адреса):
http://ww.xyz.com/Products/Gora-aldre


person Anthony    schedule 18.07.2010    source источник


Ответы (4)


Я придумал 2 следующих метода расширения (asp.net / C #):

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

    public static string Slugify(this string phrase)
    {
        string str = phrase.RemoveAccent().ToLower();
        str = System.Text.RegularExpressions.Regex.Replace(str, @"[^a-z0-9\s-]", ""); // Remove all non valid chars          
        str = System.Text.RegularExpressions.Regex.Replace(str, @"\s+", " ").Trim(); // convert multiple spaces into one space  
        str = System.Text.RegularExpressions.Regex.Replace(str, @"\s", "-"); // //Replace spaces by dashes
        return str;
    }
person Anthony    schedule 18.07.2010
comment
Я написал огромный метод, полный операторов if, используя класс char, пока не нашел его. Хорошая вещь. - person The Muffin Man; 28.09.2012
comment
Я думаю, что ISAPI делает то же самое, но мне нужен больший контроль над своими URL-адресами. Это хорошее решение. - person Erik Bergstedt; 15.03.2013
comment
Спасибо за функцию. Мне пришлось добавить еще один кусок в конце, чтобы заменить два или более дефиса одним дефисом. str = System.Text.RegularExpressions.Regex.Replace (str, @ \ - +, -); // конвертируем несколько дефисов в один дефис - person Richard Edwards; 09.07.2014
comment
Я использовал это красивое решение, но я сохранил акценты и заменил [^ a-z0-9 \ s-] на этот [^ \ w \ d \ s-] для поддержки URL-адресов Unicode. Проголосуй за это или обними меня. - person Shadi Namrouti; 22.08.2017

Транслитерируйте символы, отличные от ASCII, в ASCII, используя что-то вроде этого:

var str = "éåäöíØ";
var noApostrophes = Encoding.ASCII.GetString(Encoding.GetEncoding("Cyrillic").GetBytes(str)); 

=> "eaaoiO"

(Источник)

person Sjoerd    schedule 18.07.2010
comment
Что делать, если некоторые символы не кириллические? Мне нужно решение, которое всегда будет работать. - person Anthony; 18.07.2010
comment
Затем вам нужно будет добавить дополнительные проверки для разных типов кодирования. К сожалению, здесь нет волшебной палочки, если вы не используете библиотеку, которая все сделает за вас. - person hollsk; 18.07.2010
comment
Возможно, вам нужна библиотека UnidecodeSharp: unidecode.codeplex.com - person Sjoerd; 18.07.2010

Еще одна вещь, на которую стоит обратить внимание:

Если пользователь предоставляет строку, например 好听的音乐, которую вы хотите преобразовать в понятный URL-адрес заголовок, вам следует подумать об использовании IdnMapping

Например:

string urlFriendlyTitle = Slugify(url);

public static string Slugify(string text)
{
    IdnMapping idnMapping = new IdnMapping();
    text = idnMapping.GetAscii(text);

    text = RemoveAccent(text).ToLower();

    //  Remove all invalid characters.  
    text = Regex.Replace(text, @"[^a-z0-9\s-]", "");

    //  Convert multiple spaces into one space
    text = Regex.Replace(text, @"\s+", " ").Trim();

    //  Replace spaces by underscores.
    text = Regex.Replace(text, @"\s", "_");

    return text;
}

public static string RemoveAccent(string text)
{
    byte[] bytes = Encoding.GetEncoding("Cyrillic").GetBytes(text);

    return Encoding.ASCII.GetString(bytes);
}

Без этого 好听的音乐 будет преобразован в string.Empty. При этом xn--fjqr6lw2ek78az68a, который является punycode

person Sean Anderson    schedule 08.10.2014

Я использую функцию, описанную на http://www.blackbeltcoder.com/Articles/strings/converting-text-to-a-url-friendly-slug. Он не поддерживает напрямую неанглийские символы, но может быть легко обновлен для поддержки дополнительных символов.

Мне это нравится, потому что он производит очень чистый вид пули.

person Jonathan Wood    schedule 17.12.2010
comment
Что, если в вашей функции TextToSlug преобразуемая строка содержит акцент? Например, «жених», что является прекрасным английским словом. Подобных примеров на английском языке предостаточно. IsLetterOrDigit вернет true для символа é, поэтому вы получите его в своем URL-адресе, который будет неправильным, поскольку в идеале é следует преобразовать в e в URL-адресе. - person Anthony; 18.12.2010
comment
Что здесь идеально значит? Вы говорите, что жених недопустим в URL-адресе? Этого не произошло, пока я использую свой код, но я более чем счастлив изменить его, если это вызовет проблемы. - person Jonathan Wood; 18.12.2010