Существует ли класс JDK для кодирования HTML (но не для кодирования URL)? - PullRequest
31 голосов
/ 17 марта 2009

Я, конечно, знаком с классами java.net.URLEncoder и java.net.URLDecoder. Однако мне нужна только кодировка в стиле HTML. (Я не хочу заменять ' ' на '+' и т. Д.). Я не знаю ни одного встроенного в JDK класса, который будет выполнять только кодирование HTML. Есть один? Мне известны другие варианты (например, Jakarta Commons Lang 'StringEscapeUtils' , но я не хочу добавлять другую внешнюю зависимость в проект, где мне это нужно.

Я надеюсь, что что-то было добавлено в недавний JDK (5 или 6), что сделает это, о чем я не знаю. В противном случае я должен свернуть свой собственный.

Ответы [ 7 ]

45 голосов
/ 18 марта 2009

Для этого не существует встроенного в JDK класса, но он является частью библиотеки Jakarta commons-lang.

String escaped = StringEscapeUtils.escapeHtml3(stringToEscape);
String escaped = StringEscapeUtils.escapeHtml4(stringToEscape);

Проверьте JavaDoc

Добавление зависимости обычно так же просто, как сбросить банку куда-нибудь, и у commons-lang есть так много полезных утилит, что часто стоит иметь их на борту.

13 голосов
/ 12 января 2012

Вот простой способ:

public static String encodeHTML(String s)
{
    StringBuffer out = new StringBuffer();
    for(int i=0; i<s.length(); i++)
    {
        char c = s.charAt(i);
        if(c > 127 || c=='"' || c=='<' || c=='>')
        {
           out.append("&#"+(int)c+";");
        }
        else
        {
            out.append(c);
        }
    }
    return out.toString();
}

Источник: http://forums.thedailywtf.com/forums/p/2806/72054.aspx#72054

9 голосов
/ 09 сентября 2009

Видимо, ответ "Нет" К сожалению, это был случай, когда я должен был что-то сделать, и не смог добавить для него новую внешнюю зависимость - в краткосрочной перспективе. Я согласен со всеми, что использование Commons Lang является лучшим долгосрочным решением. Это то, с чем я пойду, когда смогу добавить новую библиотеку в проект.

Жаль, что что-то такого общего использования отсутствует в Java API.

4 голосов
/ 22 мая 2016

Я обнаружил, что все существующие решения (библиотеки), которые я рассмотрел, страдали одной или несколькими из следующих проблем:

  • Они не говорят вам в Javadoc, что именно они заменяют.
  • Они избегают слишком много ... что делает HTML намного труднее для чтения.
  • Они не документируют , когда возвращаемое значение безопасно использовать (безопасно использовать для сущности HTML ?, для атрибута HTML? И т. Д.)
  • Они не оптимизированы для скорости.
  • У них нет возможности избежать двойного побега (не избегайте того, что уже сбежало)
  • Они заменяют одинарные кавычки на &apos; (неправильно!)

Кроме того, у меня также была проблема с невозможностью ввести внешнюю библиотеку, по крайней мере, без определенного количества красной ленты.

Итак, я свернул свой. Guilty.

Ниже это выглядит, но последнюю версию всегда можно найти в этой сущности .

<code>/**
 * HTML string utilities
 */
public class SafeHtml {

    /**
     * Escapes a string for use in an HTML entity or HTML attribute.
     * 
     * <p>
     * The returned value is always suitable for an HTML <i>entity</i> but only
     * suitable for an HTML <i>attribute</i> if the attribute value is inside
     * double quotes. In other words the method is not safe for use with HTML
     * attributes unless you put the value in double quotes like this:
     * <pre>
     *    &lt;div title="value-from-this-method" &gt; ....
     * 
* В любом случае помещать значения атрибутов в двойные кавычки - это всегда хорошая идея. * *

Будут экранированы следующие символы: *

  • {@ code &} (амперсанд) - заменено на {@code & amp;}
  • {@ code <} (меньше чем) - заменено на {@code & lt;} </li> *
  • {@ code>} (больше чем) - заменено на {@code & gt;}
  • {@ code "} (двойная кавычка) - заменено на {@code & quot;}
  • {@ code '} (одинарная кавычка) - заменено на {@code'}
  • {@ code /} (косая черта) - заменено на {@code /}
* Нет необходимости избегать большего, чем эта, пока HTML-страница * использует * кодировка Unicode . (Большинство веб-страниц использует UTF-8, который также является HTML5 * рекомендация.). Экранирование больше, чем это делает HTML гораздо менее читабельным. * * @param s строка, чтобы сделать HTML безопасным * @param избежатьDoubleEscape избежать двойного побега, что означает, например, не * избегая {@code & lt;} еще раз. Любая последовательность {@code & ....;}, как описано в * {@link #isHtmlCharEntityRef (java.lang.String, int) isHtmlCharEntityRef ()} не будет экранирован. * * @ вернуть HTML безопасную строку * / public static String htmlEscape (String s, логическое избежатьDoubleEscape) { if (s == null || s.length () == 0) { возврат с; } StringBuilder sb = new StringBuilder (s.length () + 16); for (int i = 0; i ': sb.append ( "& GT;"); перерыв; дело '"': sb.append ( "& Quot;"); перерыв; дело '\'': sb.append ( "'"); перерыв; дело '/': sb.append ( "/"); перерыв; дефолт: sb.append (с); } } return sb.toString (); } / ** * Проверяет, является ли значение в {@code index} ссылкой на сущность HTML. это * означает любой из: * * {@ code & amp;} или {@code & lt;} или {@code & gt;} или {@code & quot;} * Значение в форме {@code & # dddd;}, где {@code dddd} - десятичное значение * Значение в форме {@code & # xhhhh;}, где {@code hhhh} - шестнадцатеричное значение * * @param str строка для проверки ссылки на сущность HTML.* @param индексная позиция {@code '&'} в {@code str} * @вернуть * / public static boolean isHtmlCharEntityRef (String str, int index) { if (str.charAt (index)! = '&') { вернуть ложь; } int indexOfSemicolon = str.indexOf (';', index + 1); if (indexOfSemicolon == -1) {// есть точка с запятой через некоторое время? вернуть ложь; } if (! (indexOfSemicolon> (index + 2))) {// строка достаточно длинная вернуть ложь; } if (followCharsAre (str, index, "amp;") || followCharsAre (str, index, "lt;") || followCharsAre (str, index, "gt;") || followCharsAre (str, index, "quot;")) { вернуть истину; } if (str.charAt (index + 1) == '#') { if (str.charAt (index + 2) == 'x' || str.charAt (index + 2) == 'X') { // Предположительно это шестнадцатеричное значение if (str.charAt (index + 3) == ';') { вернуть ложь; } for (int i = index + 3; i = 48 && c <= 57) {// 0 - 9 Продолжить; } if (c> = 65 && c <= 70) {// A - F Продолжить; } if (c> = 97 && c <= 102) {// a - f Продолжить; } вернуть ложь; } вернуть истину; // да, значение является шестнадцатеричной строкой } еще { // Предположительно это десятичное значение for (int i = index + 2; i <indexOfSemicolon; i ++) { char c = str.charAt (i); if (c> = 48 && c <= 57) {// 0 - 9 Продолжить; } вернуть ложь; } вернуть истину; // да, значение десятичное } } вернуть ложь; } / ** * Проверяет, если символы после позиции <code>startIndex в строке * str это то, что nextChars. * * Оптимизировано для скорости. В противном случае этот метод был бы точно равен * {@code (str.indexOf (nextChars, startIndex + 1) == (startIndex + 1))}. * * @param str * @param startIndex * @param nextChars * @вернуть * / private static boolean followCharsAre (String str, int startIndex, String nextChars) { if ((startIndex + nextChars.length ()) TODO: сохранить последовательный пробел.
1 голос
/ 17 марта 2009

Пожалуйста, не катите свои собственные. Используйте Джакарта Commons Lang. Это проверено и доказано, что работает. Не пишите код, пока не придется. «Не изобретено здесь» или «Не другая зависимость» не очень хорошая основа для принятия решения, что выбрать / написать.

0 голосов
/ 28 июля 2017

Я предлагаю использовать org.springframework.web.util.HtmlUtils.htmlEscape (String input)

может быть, это поможет.

0 голосов
/ 17 марта 2009

Нет. Я бы порекомендовал использовать упомянутые вами StringEscapeUtils или, например, JTidy (http://jtidy.sourceforge.net/multiproject/jtidyservlet/apidocs/org/w3c/tidy/servlet/util/HTMLEncode.html).

...