HTML 5中哪些字符需要转义?

26

HTML 4规定了需要转义的特殊字符,这里有详细说明:

以下四个实体引用由于经常用于转义特殊字符,因此需要特别提及:

  • "&lt;"代表 < 符号。
  • "&gt;"代表 > 符号。
  • "&amp;"代表 & 符号。
  • "&quot;代表 " 符号。

如果作者希望在文本中使用字符“<”,应使用“&lt;”(ASCII十进制60),以避免可能会将其误认为是标签开始定界符(起始标记开放定界符)。同样,作者应该在文本中使用“&gt;”(ASCII十进制62)而不是“>”,以避免旧的用户代理错误地将其视为标签结束定界符(标记关闭定界符)出现在引号包含的属性值中时。

作者应该使用“&amp;”(ASCII十进制38)而不是“&”以避免与字符引用(实体引用开放定界符)的开头混淆。在CDATA属性值中允许使用字符引用,因此作者还应在属性值中使用“&amp;”。

一些作者使用字符实体引用“&quot;”来编码双引号(")的实例,因为该字符可能用于定界属性值。

我惊讶地发现在HTML 5中找不到类似的内容。通过grep的帮助,我唯一找到的非XML提及是关于已废弃的XMP元素的旁白:

改用pre和code标签,并将“<” 和 “&”字符转义为“&lt;”和“&amp;”。

有人可以指出官方的资料吗?

在语义不明确时需要转义字符。因此,在双引号属性中的 " 和单引号属性中的 ' (显然是含糊的),以及文本外的 '<' (有时只有含糊,但仍会导致验证错误)都需要进行转义。 <b>2 > 1</b> 是有效的HTML5格式。& 在含糊时也是一个错误。 - Ry-
谢谢,但是...我仍然觉得这一切都有道理,但没有规范的部分涉及它。毕竟,HTML并不是非常适合“有意义”的指导。 (比如,<p>可以明确地关闭前一个段落中所有打开的<em><strong>标签等)。为什么会有这种遗漏,而花时间去“除非元素的第一件事是注释”。感觉像是一个重大疏忽。 - ezequiel-garzon
我不确定这与转义规则有什么关系,但自动纠正未关闭的标签以形成可识别的树形结构是出于历史原因必须存在的。 - Ry-
我的意思是,我在我的例子中并不是在寻找令人信服的理由或常识,因为HTML具有(与XML不同)高度的任意性。相反,我正在寻找一个来源,你很友好地提供了它。再次感谢。 - ezequiel-garzon
这个回答解决了你的问题吗?在HTML中哪些字符需要转义? - Dan Dascalescu
3个回答

11

规范定义了普通元素的语法如下:

普通元素可以包含文本、字符引用、其他元素和注释,但文本中不能包含字符U+003C LESS-THAN SIGN (<)或不明确的&符号。一些普通元素对其所允许包含的内容有更多限制,这超出了内容模型所施加的限制以及本段描述的限制。这些限制在下面描述。

因此,当后面跟着任何可能开始字符引用的内容时,您必须转义<&。关于&的规则是引用属性的唯一规则,因为匹配的引号是唯一会终止引用属性的东西。(显然,如果您不想在那里终止属性值,请转义引号。)

这些规则不适用于<script><style>;您应避免在其中放置动态内容。(如果您必须在<script>中包含JSON,请在JSON序列化后将<替换为\x3c,将U+2028字符替换为\u2028,并将U+2029替换为\u2029。)

谢谢!我学到了,除其他事项外,我应该查看W3C文档,而不是WHATWG文档。根据模棱两可的和号&hello there的定义,它应该是可以的,因为它没有尾随分号,但是官方验证器却拒绝它。你知道为什么吗? - ezequiel-garzon
1
哇!你真的懂这个!感谢你抽出时间回答评论。我刚刚在WHATWG中找到了你提供的参考资料(这很有意义),所以我收回之前的评论。非常感谢! - ezequiel-garzon
@eze:感谢您的提问!这些都是非常重要的安全考虑因素,我很高兴现在对边缘情况有了更多的了解。 - Ry-
2
这适用于HTML5的HTML序列化。在HTML5的XHTML序列化中,所有XML规则都适用,因此“&”必须始终进行转义。 - Jukka K. Korpela

6

来自http://www.w3.org/html/wg/drafts/html/master/single-page.html#serializing-html-fragments

转义字符串(为了上述算法的目的)包括执行以下步骤:

  1. 将任何"&"字符的出现替换为字符串"&amp;"。
  2. 将U+00A0 NO-BREAK SPACE字符的任何出现替换为字符串"&nbsp;"。
  3. 如果在属性模式下调用算法,则将"""字符的任何出现替换为字符串"&quot;"。
  4. 如果未在属性模式下调用算法,则将"<"字符的任何出现替换为字符串"&lt;",将">"字符的任何出现替换为字符串"&gt;"。

* 算法是内置的序列化算法,例如通过innerHTML getter调用。

严格来说,这并不完全回答你的问题,因为它涉及序列化而不是解析。但另一方面,序列化输出旨在安全可解析。因此,暗示着在编写标记时:

  1. 应将&字符替换为&amp;
  2. 应将非断行空格转义为&nbsp;(惊喜!...)
  3. 在属性内部,应将"转义为&quot;
  4. 在属性之外,<应转义为&lt;>应转义为&gt;

我有意写“应”而不是“必须”,因为解析器可能能够纠正上述违规。


3

我强调一下,事情并不那么容易——严格来说:

情况1:HTML序列化

(最常见的情况)

如果将HTML5序列化为HTML格式,则“文本不得包含字符U+003C小于号(<)或模糊的和号”

一个模糊的和号是指“和号后面跟着一个或多个字母数字ASCII字符,再加上一个U+003B分号字符(;)”

此外,“即使省略了结束分号,某些命名字符引用在属性中的解析仍会发生”

所以,在这种情况下,editable && copy (注意&&周围的空格) 是有效的HTML5序列化为HTML的构造,因为没有一个和号后面跟着一个字母。

相反,editable&&copy不是安全的(即使这可能会起作用),因为最后一个序列&copy可能会被解释为版权符号©的实体引用。

情况2:XML序列化

(较少见)

在这种情况下,使用经典的XML规则。例如,文本或属性中的每个和号都应转义为&amp;

在这种情况下,&&(无论是否带空格)都是无效的XML,应该写成&amp;&amp;

有点棘手,是吧?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接