2009-11-01 12 views
31

sieci ram takich jak Rails i Django ma wbudowane wsparcie dla „ślimaki”, które są wykorzystywane do generowania czytelnych i SEO przyjaznych adresów URL:kod Java/biblioteki do generowania ślimaki (do zastosowania w ładnych adresów URL)

ciąg ślimak zazwyczaj zawiera tylko znaki a-z, 0-9 i - i stąd mogą być pisane bez ucieczki URL (myślę „foo% 20ba r ").

Poszukuję funkcji wtyczki Java, która podając dowolny poprawny ciąg znaków Unicode zwróci reprezentację wtyczki (a-z, 0-9 i -).

Trywialny funkcja ślimak byłoby coś wzdłuż linii:

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

Jednak ta realizacja nie będzie obsługiwać umiędzynarodowienie i akcenty (ë>e). Jednym ze sposobów byłoby wyliczenie wszystkich specjalnych przypadków, ale nie byłoby to zbyt eleganckie. Szukam czegoś bardziej przemyślanego i ogólnego.

Moje pytanie:

  • Co jest najbardziej ogólnym/praktyczny sposób, aby wygenerować ślimaki typu Django/Rails w Java?

Odpowiedz

34

Normalize ciąg przy użyciu rozkładu kanonicznego:

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); 
    } 

To wciąż dość naiwny proces, choć. Nie zrobi nic dla s-sharp (ß - używane w języku niemieckim) ani alfabetu innego niż łaciński (grecki, cyrylica, CJK itp.).

Należy zachować ostrożność przy zmianie obudowy sznurka. Formy wielkie i małe są zależne od alfabetów. Po turecku, kapitalizacja U + 0069 (i) to U + 0130 (İ), nie U + 0049 (I) więc ryzyko wprowadzenia non-latin1 znak z powrotem do napisu jeśli używasz String.toLowerCase() w tureckiej lokalizacji.

+1

wygląda obiecująco, ale normalizacja nie wydaje się działać: „foobar” zostanie przetłumaczone na „FBR” zamiast oczekiwanego „foobar”. Wiesz dlaczego? – knorv

+1

Dziwne - kiedy wstawiam ciąg '' f \ u00F3 \ u00F2b \ u00e2r "' za pomocą metody, otrzymuję '" foobar "'. Być może popełniłeś błąd kodowania w źródle lub pliku danych; zobacz http://illegalargumentexception.blogspot.com/2009/05/java-rough-guide-to-character-encoding.html – McDowell

+0

McDowell: Masz całkowitą rację - był to błąd kodowania. Dzięki za doskonałą odpowiedź! – knorv

1

ja już rozszerzyłem odpowiedź @McDowell, dodając myślnik interpunkcyjny jako myślniki i usuwając myślniki dwukierunkowe i początkowe/końcowe.

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

Propozycja McDowel prawie działa, ale w takich przypadkach Hello World !! zwraca hello-world-- (uwaga -- na końcu łańcucha) zamiast hello-world.

Stały wersja może być:

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(text).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); 
} 
Powiązane problemy