有没有一种Java工具可以验证一个字符串是否为有效的HTML转义字符?

5
我希望有一个以下格式的方法:

public boolean isValidHtmlEscapeCode(String string);

使用方法如下:

isValidHtmlEscapeCode("A") == false
isValidHtmlEscapeCode("ש") == true // Valid unicode character
isValidHtmlEscapeCode("ש") == true // same as 1513 but in HEX
isValidHtmlEscapeCode("�") == false // Invalid unicode character

我找不到任何可以做到这一点的工具 - 有没有能够做到这一点的实用程序? 如果没有,有没有更聪明的方法来做到这一点?

&ä&customEntity;怎么处理? - Konrad Rudolph
我不介意有一个处理它们的函数,但这不是我的要求(换句话说,我对此持中立态度)。 - RonK
为什么你不能只检查它是否以&开头,以;结尾,并且中间部分由以下内容组成:(i) a-z, 0-9 (ii) #后跟数字 (iii) #x后跟十六进制数字? - Salman A
1
@SalmanA 我希望有更聪明的方法来做这件事 - 我不喜欢重复造轮子。 - RonK
5个回答

2

不确定这是否是一个完美的解决方案,但您可以使用Apache Commons Lang:

try {
    return StringEscapeUtils.unescapeHtml4(code).length() < code.length();
} catch (IllegalArgumentException e) {
    return false;
}

StringEscapeUtils无法处理任何以&#xxx;格式表示的内容。因此,基于它的代码将无法工作。 - RonK
确实如此,unescapeHtml4包含NumericEntityUnescaper,因此它应该可以处理它们。 - hoaz
看起来当您传递无效实体时,它会抛出“IllegalArgumentException”,因此我稍微更新了我的解决方案。 - hoaz

2

2
public static boolean isValidHtmlEscapeCode(String string) {
    if (string == null) {
        return false;
    }
    Pattern p = Pattern
            .compile("&(?:#x([0-9a-fA-F]+)|#([0-9]+)|([0-9A-Za-z]+));");
    Matcher m = p.matcher(string);

    if (m.find()) {
        int codePoint = -1;
        String entity = null;
        try {
            if ((entity = m.group(1)) != null) {
                if (entity.length() > 6) {
                    return false;
                }
                codePoint = Integer.parseInt(entity, 16);
            } else if ((entity = m.group(2)) != null) {
                if (entity.length() > 7) {
                    return false;
                }
                codePoint = Integer.parseInt(entity, 10);
            } else if ((entity = m.group(3)) != null) {
                return namedEntities.contains(entity);
            }
            return 0x00 <= codePoint && codePoint < 0xd800
                    || 0xdfff < codePoint && codePoint <= 0x10FFFF;
        } catch (NumberFormatException e) {
            return false;
        }
    } else {
        return false;
    }
}

这是一组命名实体 http://pastebin.com/XzzMYDjF


谢谢,这是我问题的最佳解决方案 - 我稍微修改了它,添加了一个^在模式的开头和一个$在结尾,所以对于像hello &#123; world这样的字符串,它将不会返回true - RonK
@RonK 感谢,是的,我使用这个正则表达式来提取HTML实体并忘记修改它了^^ - Esailija

1

这应该是你想要的方法:

public static boolean isValidHtmlEscapeCode(String string) {
String temp = "";
try {
    temp = StringEscapeUtils.unescapeHtml3(string);
} catch (IllegalArgumentException e) {
    return false;
}
return !string.equals(temp);
}

0
尝试使用正则表达式进行匹配:
public boolean isValidHtmlEscapeCode(String string) {
    return string.matches("&;#([0-9]{1,4}|x[0-9a-fA-F]{1,4});");
}

或者为了节省一些处理周期,您可以重用正则表达式进行多次比较:

Pattern pattern = Pattern.compile("&;#([0-9]{1,4}|x[0-9a-fA-F]{1,4});");

public boolean isValidHtmlEscapeCode(String string) {
    return pattern.matches(string);
}

正则表达式的源代码可在 RexLib.com 找到。

还不错 - 但是 isValidHtmlEscapeCode("&#99999;") 将会返回 true。 - RonK
@RonK 正则表达式已更改以修正长度约束。 - Brent Worden
@RonK &#99999; 是有效的...在十进制中,直到 &#1114111; 是有效的。 - Esailija
@Esailija - 谢谢,因此仅长度验证是不够的 - 数字的值也需要进行验证。 - RonK
@RonK 其他一些问题包括字符引用,这些引用将被视为单个代理项,我认为 htmlUnescape 没有考虑到这一点。即使是 Chrome 和 Firefox 也不一致地将 &#xd801; 视为有效实体,并将其转换为 &#xFFFD; - Esailija

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接