在 XML、XHTML 和 HTML 中,如何处理控制字符(即 “C0” U+0000-U+001F 和 “C1” U+007F-U+009F 范围)?
旧系统有时会生成包含控制字符的数据。因此,在将这些系统或其数据迁移到 Web 时,了解标记语言对控制字符的支持情况可能非常重要。
Unicode 字符集有两个范围被指定为控制字符。Unicode 标准本身并未对这些控制字符作特定用途的规定,而是将其定义交由应用程序。如果应用程序未指定其使用方式,则应按照 ISO/IEC 6429 的语义来解释。大多数人会熟悉许多 6429 控制字符:ACK、NAK、BEL、LF、FF、VT、CR 等。ISO 8859 系列及其他字符标准的控制字符都是基于 ISO 6429 标准的。
范围 U+0000-U+001F 内的控制字符被称为 “C0” 范围。该范围以 NUL(空字符)U+0000 开始。范围 U+0080-U+009F 内的控制字符被称为 “C1” 范围。DEL(删除)U+007F 也属于控制字符,且紧邻 C1 范围的起始位置。
应该使用 适当的标记 来替换控制字符。由于 XML 提供了对结构化数据的标准编码方式,将控制字符表示为标记之外的形式会抵消使用 XML 的实际优势。在 HTML 和 XHTML 中使用控制字符从未合适,因为这些标记语言用于表示文本,而非数据。只有在极少数情况下,旧数据中包含控制字符且无法清理时,才可能需要以下信息。
如果数据实际上不是文本而是二进制,则可以更实际地对其进行编码,例如使用 base64 或十六进制值,以确保在标记语言文本中仅使用受支持的字符。(当然,在读取文件时需要对文本进行解码。)需要注意的是,XML Schema 为这些编码提供了相应的数据类型。
另一种方法是将数据存储在外部文档中,并在 XML 文档中进行引用。
在 XML 1.1 中,如果需要明确表示一个控制字符,最简单的方式是使用 NCR(数字字符引用)。例如,控制字符 ESC(Escape)U+001B 可以表示为 (十六进制)或 (十进制)数字字符引用。
下表概述了各标记语言对控制字符的支持情况
| 控件 | 范围 (Range) | HTML 4 | XHTML 1.0 | XML 1.0 | XML 1.1 |
|---|---|---|---|---|---|
| C0,除 HT、LF、CR 外 | U+0000(NUL) | 非法 | 非法 | 非法 | 非法 |
| U+0001-U+001F | 非法 | 非法 | 非法 | NCR | |
| HT, LF, CR | U+0009, U+000A, U+000D | 已支持 | 已支持 | 已支持 | 已支持 |
| DEL + C1 | U+007F-U+009F | 非法 | 非法 | 已支持 | NCR |
| NEL | U+0085 | 非法 | 非法 | (允许) | 已支持 |
NUL(空)控制字符是非法的,不能通过 NCR 表示或直接在标记语言中编码。
HTML、XHTML 和 XML 1.0 不支持 C0 范围,唯有 HT(水平制表符)U+0009、LF(换行)U+000A 和 CR(回车)U+000D 除外。C1 范围则受支持,即可以直接对这些控制字符进行编码,或使用 NCR(数字字符引用)来表示它们。
XML 1.1 限制了 C1 范围,除 NEL U+0085(EBCDIC 换行)外,以及 C0 范围。然而,XML 1.1 仍允许使用 NCR(数字字符引用)来表示这些控制字符。
ISO 8859 系列将 C1 范围保留给控制字符,而 Microsoft 的字符集(如 1250-1258)则在该范围内放置字符。有时内容作者在创建 NCR 时误将 Microsoft 的字符编码点用作 Unicode 值。由于这种错误的普遍性,许多浏览器会显示该范围内的 Microsoft 字符。这是一种不正确的行为,并进一步误导开发者,使其错误地确认了该值。该问题最终可能在某些应用程序处理数据时被发现,或在符合标准的浏览器未能显示预期字符时显现。
关于 C0 范围的更多细节,请参阅 Unicode 代码表:C0 控制字符和基本拉丁文
更多关于 C1 范围的细节,请参阅 Unicode 代码表:C1 控制字符和拉丁文-1 补充
文档 Unicode in XML and other Markup Languages(《XML 与其他标记语言中的 Unicode》)提供了在 XML 等标记语言中使用 Unicode 标准的指导原则。