前段时间, 完成了一个HTML危险标记删除安全项目。 项目里, 把所有必要的字符进行实体转换。 做完了心想, 这次总不会弄出什么bug吧。 这个代码经过了非常严格的测试, 也是我基于测试驱动开发的不多的尝试。 结果还是有个恶心的bug. 发现单引号(' ) 实体转化(' )后, 不能被IE6解释解释,显示成原型了, FF等其他的经过测试都能正确显示。, 简直是气人, 翻阅资料后发现, 原来W3C并没有规定HTML里的单引号需要经过实体转化, 这个转义是XML的标准。 微软这回还可真遵循了标准!!!
发现问题后, 为了防止出现HTML格式破损。 还是把单引号实体转化成' 这样可以避免显示数据在标记属性里的问题。可能有人会问我为什么不使用jakarta commons包里的StringEscapedUtil的方法。没错, 这个东西是很好。 我的项目对性能要求非常高, 我修正了这个StringEscapedUtil。htmlEscaped()方法, 提高了很多性能。并且我原来是使用nekohtml的转义函数, 就是他对单引号做了转义。
==============================================
下面这个代码演示了节约内存分配的办法, 小技巧而已。
- //大部分字符串是不需要转移的, 因此避免内存分配是必要的。
- public String escape(String str) {
- if (str == null) {
- return null;
- }
- StringBuilder buffer = null;
- int len = str.length();
- char ch;
- char[] entityName;
- for (int i = 0; i < len; i++) {
- ch = str.charAt(i);
- entityName = getEntity(ch);
- if (entityName == null) {
- if (buffer != null) {
- buffer.append(ch);
- }
- } else {
- if (buffer == null) {
- buffer = new StringBuilder(str.length() << 1);
- buffer.append(str, 0, i);
- }
- buffer.append(entityName);
- }
- }
- if (buffer != null) {
- return buffer.toString();
- } else {
- return str;
- }
- }