HTML、XHTML、XML 与控制字符

问题

在 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 非法 非法 (允许) 已支持

顺便说一下

ISO 8859 系列将 C1 范围保留给控制字符,而 Microsoft 的字符集(如 1250-1258)则在该范围内放置字符。有时内容作者在创建 NCR 时误将 Microsoft 的字符编码点用作 Unicode 值。由于这种错误的普遍性,许多浏览器会显示该范围内的 Microsoft 字符。这是一种不正确的行为,并进一步误导开发者,使其错误地确认了该值。该问题最终可能在某些应用程序处理数据时被发现,或在符合标准的浏览器未能显示预期字符时显现。