Java-код / ​​библиотека для генерации слагов (для использования в красивых URL) - PullRequest
34 голосов
/ 01 ноября 2009

Веб-фреймворки, такие как Rails и Django, имеют встроенную поддержку «слагов», которые используются для создания читаемых и оптимизированных для SEO URL-адресов:

Строка слагов обычно содержит только символы a-z, 0-9 и - и, следовательно, может быть записана без экранирования URL (например, "foo% 20bar").

Я ищу функцию slug Java, которая при наличии любой допустимой строки Unicode вернет представление slug (a-z, 0-9 и -).

Тривиальная функция слага будет выглядеть примерно так:

return input.toLowerCase().replaceAll("[^a-z0-9-]", "");

Однако эта реализация не будет обрабатывать интернационализацию и акценты (ë> e). Одним из способов обойти это было бы перечисление всех особых случаев, но это было бы не очень элегантно. Я ищу что-то более продуманное и общее.

Мой вопрос:

  • Каков наиболее общий / практичный способ генерирования слагов типа Django / Rails в Java?

Ответы [ 5 ]

38 голосов
/ 01 ноября 2009

Нормализуйте вашу строку, используя каноническое разложение:

  private static final Pattern NONLATIN = Pattern.compile("[^\\w-]");
  private static final Pattern WHITESPACE = Pattern.compile("[\\s]");

  public static String toSlug(String input) {
    String nowhitespace = WHITESPACE.matcher(input).replaceAll("-");
    String normalized = Normalizer.normalize(nowhitespace, Form.NFD);
    String slug = NONLATIN.matcher(normalized).replaceAll("");
    return slug.toLowerCase(Locale.ENGLISH);
  }

Хотя это все еще довольно наивный процесс. Он не будет ничего делать для s-sharp (& # xDF; - используется на немецком языке) или любого алфавита, не основанного на латинице (греческий, кириллица, CJK и т. Д.).

Будьте осторожны при изменении регистра строки. Прописные и строчные буквы зависят от алфавита. На турецком языке заглавная буква U + 0069 ( i ) равна U + 0130 ( & # x130; ), а не U + 0049 ( I ) рискуете ввести нелатинский символ 1 обратно в строку, если вы используете String.toLowerCase() в турецкой локали.

12 голосов
/ 17 июля 2012

http://search.maven.org/#search|ga|1|slugify

А вот репозиторий GitHub, чтобы взглянуть на код и его использование:

https://github.com/slugify/slugify

2 голосов
/ 31 мая 2016

Предложение McDowel почти работает, но в подобных случаях Hello World !! возвращает hello-world-- (обратите внимание на -- в конце строки) вместо hello-world.

Фиксированная версия может быть:

private static final Pattern NONLATIN = Pattern.compile("[^\\w-]");
private static final Pattern WHITESPACE = Pattern.compile("[\\s]");
private static final Pattern EDGESDHASHES = Pattern.compile("(^-|-$)");

public static String toSlug(String input) {
    String nowhitespace = WHITESPACE.matcher(input).replaceAll("-");
    String normalized = Normalizer.normalize(nowhitespace, Normalizer.Form.NFD);
    String slug = NONLATIN.matcher(normalized).replaceAll("");
    slug = EDGESDHASHES.matcher(slug).replaceAll("");
    return slug.toLowerCase(Locale.ENGLISH);
}
2 голосов
/ 20 ноября 2015

Я расширил ответ @McDowell, добавив в него дефисы в качестве дефисов и удалив дубликаты и начальные / конечные дефисы.

  private static final Pattern NONLATIN = Pattern.compile("[^\\w_-]");  
  private static final Pattern SEPARATORS = Pattern.compile("[\\s\\p{Punct}&&[^-]]");  

  public static String makeSlug(String input) {  
    String noseparators = SEPARATORS.matcher(input).replaceAll("-");
    String normalized = Normalizer.normalize(noseparators, Form.NFD);
    String slug = NONLATIN.matcher(normalized).replaceAll("");
    return slug.toLowerCase(Locale.ENGLISH).replaceAll("-{2,}","-").replaceAll("^-|-$","");
  }
1 голос
/ 02 июля 2012

справочная библиотека, для других языков: http://www.codecodex.com/wiki/Generate_a_url_slug

...