Я, конечно, знаком с классами java.net.URLEncoder
и java.net.URLDecoder
. Однако мне нужна кодировка в стиле HTML. (Я не хочу, чтобы ' '
заменен на '+'
и т.д.). Я не знаю, какой JDK построен в классе, который будет делать только HTML-кодирование. Есть ли это? Я знаю другие варианты (например,
Есть ли класс JDK для кодирования HTML (но не для кодирования URL)?
Ответ 1
По-видимому, ответ: "Нет". К сожалению, это был случай, когда я должен был что-то сделать, а не мог добавить новую внешнюю зависимость для него - в ближайшей перспективе. Я согласен со всеми, что использование Commons Lang - лучшее долгосрочное решение. Это то, что я поеду, когда я смогу добавить в проект новую библиотеку.
Стыдно, что что-то подобное не используется в Java API.
Ответ 2
Для этого нет встроенного класса JDK, но он является частью библиотеки Jakarta commons-lang.
String escaped = StringEscapeUtils.escapeHtml3(stringToEscape);
String escaped = StringEscapeUtils.escapeHtml4(stringToEscape);
Посмотрите JavaDoc
Добавление зависимостей обычно так же просто, как сбросить jar где-то, и commons-lang имеет так много полезных утилит, что часто стоит иметь его на борту.
Ответ 3
Простой способ выглядит следующим образом:
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
Ответ 4
Я обнаружил, что все существующие решения (библиотеки), которые я просмотрел, пострадали от одного или нескольких из нижеперечисленных проблем:
- Они не говорят вам в Javadoc точно, что они заменяют.
- Они избегают слишком многого... что делает HTML намного труднее читать.
- Они не документируют, когда возвращаемое значение безопасно для использования (безопасно для использования для HTML-объекта?, для атрибута HTML?) и т.д.
- Они не оптимизированы для скорости.
- У них нет функции для избежания двойного экранирования (не избегайте того, что уже экранировано)
- Они заменяют одиночную кавычку
'
(неверно!)
Вдобавок к этому у меня также возникла проблема неспособности подключить внешнюю библиотеку, по крайней мере, не без определенного количества волокиты.
Итак, я откатился. Guilty.
Ниже показано, как это выглядит, но последнюю версию всегда можно найти в этот смысл.
/**
* 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>
* <div title="value-from-this-method" > ....
* </pre>
* Putting attribute values in double quotes is always a good idea anyway.
*
* <p>The following characters will be escaped:
* <ul>
* <li>{@code &} (ampersand) -- replaced with {@code &}</li>
* <li>{@code <} (less than) -- replaced with {@code <}</li>
* <li>{@code >} (greater than) -- replaced with {@code >}</li>
* <li>{@code "} (double quote) -- replaced with {@code "}</li>
* <li>{@code '} (single quote) -- replaced with {@code '}</li>
* <li>{@code /} (forward slash) -- replaced with {@code /}</li>
* </ul>
* It is not necessary to escape more than this as long as the HTML page
* <a href="https://en.wikipedia.org/wiki/Character_encodings_in_HTML">uses
* a Unicode encoding</a>. (Most web pages uses UTF-8 which is also the HTML5
* recommendation.). Escaping more than this makes the HTML much less readable.
*
* @param s the string to make HTML safe
* @param avoidDoubleEscape avoid double escaping, which means for example not
* escaping {@code <} one more time. Any sequence {@code &....;}, as explained in
* {@link #isHtmlCharEntityRef(java.lang.String, int) isHtmlCharEntityRef()}, will not be escaped.
*
* @return a HTML safe string
*/
public static String htmlEscape(String s, boolean avoidDoubleEscape) {
if (s == null || s.length() == 0) {
return s;
}
StringBuilder sb = new StringBuilder(s.length()+16);
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
switch (c) {
case '&':
// Avoid double escaping if already escaped
if (avoidDoubleEscape && (isHtmlCharEntityRef(s, i))) {
sb.append('&');
} else {
sb.append("&");
}
break;
case '<':
sb.append("<");
break;
case '>':
sb.append(">");
break;
case '"':
sb.append(""");
break;
case '\'':
sb.append("'");
break;
case '/':
sb.append("/");
break;
default:
sb.append(c);
}
}
return sb.toString();
}
/**
* Checks if the value at {@code index} is a HTML entity reference. This
* means any of :
* <ul>
* <li>{@code &} or {@code <} or {@code >} or {@code "} </li>
* <li>A value of the form {@code &#dddd;} where {@code dddd} is a decimal value</li>
* <li>A value of the form {@code &#xhhhh;} where {@code hhhh} is a hexadecimal value</li>
* </ul>
* @param str the string to test for HTML entity reference.
* @param index position of the {@code '&'} in {@code str}
* @return
*/
public static boolean isHtmlCharEntityRef(String str, int index) {
if (str.charAt(index) != '&') {
return false;
}
int indexOfSemicolon = str.indexOf(';', index + 1);
if (indexOfSemicolon == -1) { // is there a semicolon sometime later ?
return false;
}
if (!(indexOfSemicolon > (index + 2))) { // is the string actually long enough
return false;
}
if (followingCharsAre(str, index, "amp;")
|| followingCharsAre(str, index, "lt;")
|| followingCharsAre(str, index, "gt;")
|| followingCharsAre(str, index, "quot;")) {
return true;
}
if (str.charAt(index+1) == '#') {
if (str.charAt(index+2) == 'x' || str.charAt(index+2) == 'X') {
// It presumably a hex value
if (str.charAt(index+3) == ';') {
return false;
}
for (int i = index+3; i < indexOfSemicolon; i++) {
char c = str.charAt(i);
if (c >= 48 && c <=57) { // 0 -- 9
continue;
}
if (c >= 65 && c <=70) { // A -- F
continue;
}
if (c >= 97 && c <=102) { // a -- f
continue;
}
return false;
}
return true; // yes, the value is a hex string
} else {
// It presumably a decimal value
for (int i = index+2; i < indexOfSemicolon; i++) {
char c = str.charAt(i);
if (c >= 48 && c <=57) { // 0 -- 9
continue;
}
return false;
}
return true; // yes, the value is decimal
}
}
return false;
}
/**
* Tests if the chars following position <code>startIndex</code> in string
* <code>str</code> are that of <code>nextChars</code>.
*
* <p>Optimized for speed. Otherwise this method would be exactly equal to
* {@code (str.indexOf(nextChars, startIndex+1) == (startIndex+1))}.
*
* @param str
* @param startIndex
* @param nextChars
* @return
*/
private static boolean followingCharsAre(String str, int startIndex, String nextChars) {
if ((startIndex + nextChars.length()) < str.length()) {
for(int i = 0; i < nextChars.length(); i++) {
if ( nextChars.charAt(i) != str.charAt(startIndex+i+1)) {
return false;
}
}
return true;
} else {
return false;
}
}
}
TODO: сохранить последовательные пробелы.
Ответ 5
Пожалуйста, не сворачивайте. Используйте Jakarta Commons Lang. Он проверен и проверен на работоспособность. Не пишите код, пока не потребуется. "Не изобретено здесь" или "Не какая-то другая зависимость" - не очень хорошая основа для принятия решения о том, что выбрать/написать.
Ответ 6
Нет. Я бы рекомендовал использовать упомянутый StringEscapeUtils или, например, JTidy (http://jtidy.sourceforge.net/multiproject/jtidyservlet/apidocs/org/w3c/tidy/servlet/util/HTMLEncode.html).
Ответ 7
Я предлагаю использовать org.springframework.web.util.HtmlUtils.htmlEscape(ввод строки)
Возможно, это поможет.