在纯Java代码中输出HTML时,是否有一种推荐的方法来转义<,>,"和&字符?(除了手动执行以下操作之外)。

String source = "The less than sign (<) and ampersand (&) must be escaped before using them in HTML";
String escaped = source.replace("<", "&lt;").replace("&", "&amp;"); // ...

当前回答

StringEscapeUtils from Apache Commons Lang:

import static org.apache.commons.lang.StringEscapeUtils.escapeHtml;
// ...
String source = "The less than sign (<) and ampersand (&) must be escaped before using them in HTML";
String escaped = escapeHtml(source);

版本3:

import static org.apache.commons.lang3.StringEscapeUtils.escapeHtml4;
// ...
String escaped = escapeHtml4(source);

其他回答

虽然@dfa答案的org.apache.commons.lang.StringEscapeUtils.escapeHtml是很好的,我过去使用过它,它不应该用于转义HTML(或XML)属性,否则空白将被规范化(意味着所有相邻的空白字符成为一个单独的空格)。

我知道这一点,因为我的库(JATL)中有一些没有保留空白的属性的bug。因此,我有一个drop in (copy n’paste)类(其中一些是从JDOM中偷来的)来区分属性和元素内容的转义。

虽然这在过去可能没有那么重要(适当的属性转义),但考虑到HTML5的数据属性使用,它变得越来越有趣。

Java 8+解决方案:

public static String escapeHTML(String str) {
    return str.chars().mapToObj(c -> c > 127 || "\"'<>&".indexOf(c) != -1 ?
       "&#" + c + ";" : String.valueOf((char) c)).collect(Collectors.joining());
}

String#chars返回String中的char值的IntStream。然后,我们可以使用mapToObj来转义字符代码大于127的字符(非ascii字符)以及双引号(")、单引号(')、左尖括号(<)、右尖括号(>)和&号(&)。收藏家。join将字符串连接在一起。

为了更好地处理Unicode字符,可以使用String#codePoints代替。

public static String escapeHTML(String str) {
    return str.codePoints().mapToObj(c -> c > 127 || "\"'<>&".indexOf(c) != -1 ?
            "&#" + c + ";" : new String(Character.toChars(c)))
       .collect(Collectors.joining());
}

对于使用谷歌番石榴的人:

import com.google.common.html.HtmlEscapers;
[...]
String source = "The less than sign (<) and ampersand (&) must be escaped before using them in HTML";
String escaped = HtmlEscapers.htmlEscaper().escape(source);

简单的方法:

public static String escapeHTML(String s) {
    StringBuilder out = new StringBuilder(Math.max(16, s.length()));
    for (int i = 0; i < s.length(); i++) {
        char c = s.charAt(i);
        if (c > 127 || c == '"' || c == '\'' || c == '<' || c == '>' || c == '&') {
            out.append("&#");
            out.append((int) c);
            out.append(';');
        } else {
            out.append(c);
        }
    }
    return out.toString();
}

基于https://stackoverflow.com/a/8838023/1199155(放大器不在那里)。根据http://www.w3.org/TR/html4/sgml/entities.html的说法,if子句中选中的四个字符是唯一低于128的字符

StringEscapeUtils from Apache Commons Lang:

import static org.apache.commons.lang.StringEscapeUtils.escapeHtml;
// ...
String source = "The less than sign (<) and ampersand (&) must be escaped before using them in HTML";
String escaped = escapeHtml(source);

版本3:

import static org.apache.commons.lang3.StringEscapeUtils.escapeHtml4;
// ...
String escaped = escapeHtml4(source);