XML作为一种常用的数据交换格式,对文档结构的规范性有严格要求,其中部分特殊字符属于XML的语法保留字符,如果直接出现在元素内容或属性值中,会被解析器误认为是标签或语法符号,导致解析错误。因此掌握XML特殊字符的转义处理方法是XML相关开发的基础技能。

需要转义的XML特殊字符
XML中共有5个预定义的需要转义的特殊字符,这些字符在XML语法中有特定含义,直接使用时必须替换为对应的字符实体:
| 特殊字符 | 字符实体 | 字符含义 |
|---|---|---|
| < | < | 标签开始符号 |
| > | > | 标签结束符号 |
| & | & | 字符实体开始符号 |
| " | " | 属性值引号 |
| ' | ' | 属性值单引号 | >
字符实体转义的使用场景
元素内容中的转义
当元素内容中包含上述特殊字符时,必须使用对应的字符实体替换。比如要表示一个包含小于号的内容,不能直接写<5,而要转义为<5。
错误的XML示例:
<message>数值小于5</message>
正确的XML示例:
<message>数值<5</message>
属性值中的转义
属性值如果用双引号包裹,内部的双引号需要转义为";如果用单引号包裹,内部的单引号需要转义为'。同时属性值中的&和<也必须转义。
正确的属性值转义示例:
<user desc="他说"你好"" age="<18">张三</user>
CDATA区块的使用
如果元素内容中包含大量特殊字符,逐个转义会非常繁琐,此时可以使用CDATA区块。CDATA区块中的内容会被XML解析器视为纯文本,不会解析其中的任何XML语法符号。
CDATA的语法格式为:
<![CDATA[ 文本内容 ]]>
使用CDATA改写前面的示例:
<message><![CDATA[数值小于5]]></message>
需要注意的是,CDATA区块中不能包含字符串]]>,否则会被解析器认为是CDATA的结束标记,这种情况下还是需要手动转义其中的特殊字符。
代码层面的转义实现
在实际开发中,我们通常会通过代码自动处理XML特殊字符的转义,避免手动转义遗漏。以下是Java和Python两种常见语言的转义实现示例。
Java实现
public class XmlEscapeUtil {
public static String escapeXml(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 = "数值<5,他说"你好"";
System.out.println("转义前:" + content);
System.out.println("转义后:" + escapeXml(content));
}
}
Python实现
import html
def escape_xml(input_str):
if input_str is None:
return None
# python的html.escape默认会转义& < >,需要补充转义单双引号
escaped = html.escape(input_str, quote=False)
escaped = escaped.replace('"', '"').replace("'", ''')
return escaped
if __name__ == "__main__":
content = "数值<5,他说"你好""
print(f"转义前:{content}")
print(f"转义后:{escape_xml(content)}")
另外很多XML处理库都内置了转义方法,比如Java的DOM、Python的lxml库,在生成XML节点内容时会自动处理特殊字符转义,开发时优先使用库提供的方法可以减少出错概率。
转义处理的注意事项
- 不要对已经转义过的字符实体再次转义,否则会出现双重转义问题,比如
&lt;会被解析为<而不是<。 - CDATA区块不能嵌套使用,且不能出现在属性值中,只能用于元素内容。
- 不同XML解析器对特殊字符的处理严格程度不同,遵循标准转义规则可以保证所有解析器都能正确解析文档。