在XML和HTML这类标记语言中,部分特殊字符被赋予了特定的语法含义,比如小于号<用于标识标签的开始,大于号>用于标识标签的结束,如果直接在文档内容中使用这些字符,解析器会将其误判为标签语法,进而引发文档解析错误。因此我们需要使用转义字符来替代这些特殊字符,让解析器能够正确识别内容。

为什么需要转义字符
标记语言的解析器会按照预设的语法规则解析文档内容,当遇到特殊字符时,会优先按照语法规则处理,而不是作为普通文本内容。比如我们在HTML中想要展示一段包含<div>的文字,如果直接写<div>,解析器会认为这是一个div标签的开始,而不是要展示的文本内容,就会导致显示异常。使用转义字符可以让解析器明确这些字符是普通内容,避免语法冲突。
HTML常用转义字符
HTML中需要转义的字符主要有5个,对应的转义实体如下:
| 特殊字符 | 转义字符(实体名称) | 转义字符(实体编号) | 说明 |
|---|---|---|---|
| & | & | & | 与号,用于连接URL参数等场景,必须转义 |
| < | < | < | 小于号,标签开始标识 |
| > | > | > | 大于号,标签结束标识 |
| " | " | " | 双引号,属性值包裹符号 |
| ' | ' | ' | 单引号,属性值包裹符号 |
下面是一个HTML中转义字符使用的示例:
<!-- 错误写法,解析器会认为<div>是标签 --> <p>这是一个div标签:<div></p> <!-- 正确写法,使用转义字符 --> <p>这是一个div标签:<div></p> <!-- 属性值中包含双引号的转义示例 --> <input type="text" value="他说:"你好"" />
XML常用转义字符
XML的转义规则和HTML基本一致,同样需要处理5个核心特殊字符,不过XML对语法的要求更严格,所有在文本内容中出现的特殊字符都必须转义,否则文档会直接判定为无效。XML的转义字符和HTML的对应实体完全相同,具体对应关系如下:
- 与号&转义为&
- 小于号<转义为<
- 大于号>转义为>
- 双引号"转义为"
- 单引号'转义为'
XML文档中转义字符的使用示例如下:
<?xml version="1.0" encoding="UTF-8"?>
<user>
<name>张三'小名</name>
<desc>年龄小于18岁,爱好是<跑步></desc>
<link>https://ipipp.com/api?name=张三&age=17</link>
</user>
转义注意事项
在实际开发中,转义处理需要注意以下几点:
1. 转义范围
只有出现在文本内容、属性值中的特殊字符需要转义,标签本身的语法字符不需要转义。比如在<div class="test">中,标签的<、>、"都是语法的一部分,不需要转义,而属性值test外面的双引号如果出现在属性值内部才需要转义。
2. 实体名称和编号的选择
实体名称可读性更强,比如<一看就知道是小于号的转义,但是部分较老的解析器可能不支持部分实体名称,实体编号的兼容性更好,如果对兼容性要求高,可以优先使用实体编号。
3. 动态内容的转义
如果是后端动态生成XML或HTML内容,比如从数据库读取的用户输入内容,一定要在输出前对特殊字符进行转义处理,避免用户输入的特殊字符破坏文档结构,甚至引发XSS等安全问题。
下面是一个Java中对HTML特殊字符进行转义的简单示例:
public class EscapeUtil {
public static String escapeHtml(String input) {
if (input == null) {
return null;
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < input.length(); i++) {
char c = input.charAt(i);
switch (c) {
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();
}
public static void main(String[] args) {
String content = "用户输入:<script>alert('xss')</script>";
System.out.println(escapeHtml(content));
// 输出:用户输入:<script>alert('xss')</script>
}
}