下面给你一份深入解析 XML 中字符实体与字符数据的学习指南,涵盖概念、分类、用法、示例和注意事项,帮助你系统理解 XML 的文本处理机制。
📘 一、什么是字符实体与字符数据?
在 XML 中,**字符实体(Character Entity)和字符数据(Character Data)**是处理文本内容的两种核心机制。
- 字符数据(Character Data, CDATA):XML 中实际的文本内容,包括字母、数字、符号等。
- 字符实体(Entity):XML 为了避免保留字符冲突或便于复用文本而定义的“符号替换”。
简单理解:
CDATA 是原始文本,字符实体是“文本的别名或转义形式”。
📘 二、XML 中的字符实体分类
1️⃣ 预定义实体(最常用)
XML 定义了 5 个预定义实体,用于表示保留字符:
| 字符 | 实体 | 说明 |
|---|---|---|
< | < | 小于号 |
> | > | 大于号 |
& | & | 与号 |
" | " | 双引号 |
' | ' | 单引号 |
示例:
<note>
<text>Tom &amp; Jerry are friends &lt;not enemies&gt;</text>
</note>
解析后得到文本:
Tom & Jerry are friends <not enemies>
2️⃣ 数字字符实体(Unicode/ASCII 编码)
可使用 十进制或十六进制表示任意 Unicode 字符。
- 十进制:
&#65; <!-- A -->
&#20013; <!-- 中文“中” -->
- 十六进制(以 x 开头):
&#x41; <!-- A -->
&#x4E2D; <!-- 中文“中” -->
数字实体可避免编码问题,尤其在跨平台、跨语言场景。
3️⃣ 自定义实体(用于复用文本)
可以在 DTD 或 XML 内部声明实体:
<!ENTITY writer "阿杰">
使用:
<author>&writer;</author>
解析后得到:
阿杰
外部实体:
<!ENTITY copyright SYSTEM "copyright.txt">
在文档中用 ©right; 引入外部文件内容。
📘 三、CDATA 区块(Character Data 区块)
CDATA 是另一种处理文本的方式,用于保留原始文本,不解析实体和标签。
语法:
<![CDATA[ 文本内容 ]]>
示例:
<content><![CDATA[
<div>Tom & Jerry</div>
]]></content>
解析器输出:
<div>Tom & Jerry</div>
CDATA 内的
<、>、&不会被解析为 XML 标签或实体。
📘 四、字符实体与 CDATA 的区别与适用场景
| 特性 | 字符实体 | CDATA |
|---|---|---|
| 是否需要转义 | 是 | 否 |
| 能否包含 XML 标签 | 不可 | 可 |
| 是否可复用 | 可(实体声明) | 不可 |
| 使用场景 | 简单转义、跨平台文本 | 富文本、HTML/脚本片段 |
📘 五、解析器对实体和 CDATA 的处理
- DOM 解析器
- 实体会被解析为对应字符
- CDATA 会被解析为
CDATASection节点,可通过.data或.nodeValue获取内容
- SAX 解析器
- 实体会触发
characters()事件 - CDATA 会触发
startCDATA()/endCDATA()和characters()事件
- XSLT 处理
- 默认会解析实体
- 可以使用
<xsl:text disable-output-escaping="yes">保留特殊字符
📘 六、字符实体常见问题与注意事项
❌ 问题 1:实体未定义报错
- XML 解析器要求所有自定义实体必须在 DTD 中定义
- 预定义实体可直接使用
❌ 问题 2:数字实体编码不正确
- 确保与 XML 声明编码一致(如 UTF-8)
- 避免出现非法 Unicode 范围
❌ 问题 3:CDATA 中包含 ]]> 会导致解析错误
- 解决方法:拆分 CDATA
<![CDATA[...]]]]><![CDATA[>...]]>
❌ 问题 4:混合使用实体和 CDATA
- CDATA 内不会解析实体
- 如果希望解析实体,不要放入 CDATA
📘 七、字符实体与编码的关系
- 实体解决了 XML 保留字符问题
- 数字实体解决了不同编码环境下的字符问题
- 使用 UTF-8 + 实体 + CDATA 结合,可实现跨语言、跨平台的安全 XML 文本传输
📘 八、总结与实践建议
- 小型文本:使用预定义实体或数字实体即可
- 富文本 / HTML / 脚本:使用 CDATA 区块
- 可复用文本:使用自定义实体
- 数字实体:避免编码不一致问题
- 混合场景:注意 CDATA 内实体不会被解析
- 解析器处理:DOM 会生成 CDATASection,SAX 需要事件处理
- 避免常见坑:CDATA 内不要出现
]]>,自定义实体必须定义