HTML 实体

用于在 HTML 中表示特殊字符的字符引用。以 & 开头,以 ; 结尾。

HTML 实体是用于在 HTML 文档中安全表示特殊字符的字符引用。在 HTML 语法中具有特殊含义的字符 (<、>、& 等) 如果直接书写,浏览器会将其解释为标签或语法,因此需要使用实体来明确表示"作为字符显示"。代表性的实体包括 &amp; (&)、&lt; (<)、&gt; (>)、&quot; (") 和 &apos; (')。

HTML 实体分为命名引用和数字引用两种。命名引用如 &amp; 这样具有人类易读的形式,截至 2026 年 8 月,HTML 规范定义的命名实体共有 2,231 个。其中 106 个还定义了像 &AMP、&lt 这样省略末尾分号的形式,浏览器会作为旧有兼容行为解释它们。如果自制的净化程序只考虑"以 & 开头、以 ; 结尾的形式",就会让这些省略形式蒙混过关,这一点需要注意。数字引用是用十进制 (&#38;) 或十六进制 (&#x26;) 直接指定 Unicode 码位的形式,即使是没有定义名称的字符也可以表示。

从 Web 安全角度来看,转换为 HTML 实体 (转义) 是防范 XSS (跨站脚本攻击) 的基本措施。将用户输入输出到 HTML 时,必须把 <、>、&、"、' 这 5 个字符转换为实体。忽略这一处理,就会有恶意脚本被注入的风险。许多 Web 框架在模板引擎中提供了自动转义功能,但在使用 innerHTML 或 dangerouslySetInnerHTML 的场合,开发者需要显式地进行转义。

不过,认为"只要转换这 5 个字符就安全"是危险的。转义有效的前提,仅限于输出位置是 HTML 正文,或者是被引号包围的属性值。如果输出属性值时不用引号包围,攻击者就能用空格或反引号制造属性的边界,即使转换了这 5 个字符也会被追加属性。此外,在 <script> 内部、href 或 src 的 URL 部分、内联 CSS 内部,转换为 HTML 实体并不构成防御。这些地方分别需要作为 JavaScript 字符串的转义、作为 URL 的验证等各自不同的处理。"根据输出到哪个上下文来选择转义方法",这才是实务上的判断基准。

实务中常用的实体包括不间断空格 (&nbsp;)、版权符号 (&copy;)、商标符号 (&trade;)、箭头 (&rarr;)、数学符号 (&times;、&divide;) 等。其中 &nbsp; 在想要显示连续空格,或想让表格的空单元格拥有内容时使用得尤为频繁。但 &nbsp; 展开成的 U+00A0 与普通的半角空格 (U+0020) 是不同的字符。在字符串比较中,"a b"与"a b"并不相等,因此它混入复制来的文章后会导致搜索不到,或作为数值的位分隔符混入而导致解析失败等故障。正如其名,它同时也禁止换行,所以在长词句中大量使用会使折行失效、内容向横向溢出。如果目的只是保持空单元格的高度,现在用 CSS 的 empty-cells 或 min-height 来处理更为自然。

一个常见的误解是"使用 UTF-8 就不需要实体了"。虽然 UTF-8 确实可以直接书写中文和表情符号,但 HTML 语法字符 (<、>、&) 的转义与字符编码无关,始终是必须的。此外,HTML 属性值中的双引号 (") 也需要转换为 &quot;。

从字符计数角度看,HTML 实体会使源代码上的字符数与浏览器显示上的字符数产生偏离。&amp; 在源代码中是 5 个字符,但在浏览器中显示为 1 个字符的"&"。&nbsp; 是 6 个字符变成 1 个空格。计算 HTML 源代码的字符数与计算渲染后文本的字符数,结果差异很大,因此意识到字符计数工具以哪一种为对象非常重要。

分享这篇文章