HTML 中的字符引用
在解释什么是不明确的 &
符号之前,让我们先谈谈字符引用。
有不同种类的字符引用。 HTML 4.01 规范将它们分为两组,但实际上是三组:
-
十进制数字字符引用,例如
©
-
十六进制数字字符引用,例如
©
-
命名字符引用,例如
©
字符引用应始终以 U+0026 AMPERSAND 字符 (&
) 开头并以 U+003B 分号字符 (;
) 结尾。
有趣的事实:HTML 规范中的命名字符引用列表包括
&
和&
,还有&
和&
(没有尾随分号)。 其他一些实体也是如此。 这样做是出于向后兼容的原因。 这样,规范规定foo & bar
应该呈现为“foo & bar”,即使它是无效标记(因为缺少尾随分号)。 稍后会详细介绍……
在这篇文章中,我们将仔细研究如果在我们的 HTML 代码中有一个未编码的符号不是字符引用的一部分,会发生什么。 有效吗? 无效吗? “模棱两可的符号”与这一切有什么关系?
HTML4 中未编码的符号
HTML 4.01 规范提到了这一点:
提交表单时构建的 URI 可用作锚式链接(例如,
<a>
元素的 href 属性)。 不幸的是,使用&
字符来分隔表单字段与其在 SGML 属性值中用于分隔字符实体引用的使用相互作用。 例如,要使用 URIhttp://host/?x=1&y=2
作为链接 URI,它必须写成<a href="http://host/?x=1&y=2 ">
或<a href="http://host/?x=1&y=2">
。
这意味着如果你想让它有效,你不能只是将 URL 复制粘贴到你的 HTML4 文档中——你必须首先对任何 &
字符进行编码。
HTML5 中的歧义符号
在 HTML5 中,添加了第一个含糊不清的 &
符号的定义:
不明确的
&
符号是 U+0026 AMPERSAND (&
) 字符,它不是文件中的最后一个字符,后面没有空格字符,后面没有没有被省略的开始标记,并且不是 后跟另一个 U+0026 AMPERSAND (&
) 字符。
模棱两可的&
符号是不合格的(无效的); 明确的&
符号通常是一致的(有效的)。 (如前所述:不以分号结尾的命名字符引用中的 &
符号是明确的,但仍然无效。)
换句话说,如果未编码的 &
符号后跟 EOF、空格字符、**<** 或 & ,则它是完全有效的。
根据这个定义,这个例子中的 &
符号都是有歧义的,因此是无效的:
<a href="https://example.com/?x=1&y=2">foo</a>
&123
&abc
foo &0 bar
foo &lolwat bar
然而,这是有效的 HTML:
foo & bar
foo&<i>bar</i>
foo&&& bar
后来规范发生了变化,HTML 规范现在定义了不明确的 &
符号,如下所示:
歧义符号是一个 U+0026 AMPERSAND 字符 (
&
),其后跟一个或多个 U+0030 DIGIT ZERO (0) 到 U+0039 DIGIT NINE (9)、U+0061 拉丁文小写字母 A 到 U+007A 拉丁文小写字母 Z,和 U+0041 拉丁文大写字母 A 到 U+005A 拉丁文大写字母 Z,后跟 U+003B 分号字符 (;),其中这些字符与 命名字符参考部分。
这个定义作为正则表达式可能更容易理解:如果字符串匹配 /&([0-9a-zA-Z]+;)/
并且如果第一个反向引用 ($1
) 不是 已知字符参考。
此示例中的 &
符号都是不明确的,因此无效:
&123;
&abc;
foo &0; bar
foo &lolwat; bar
然而,所有这些都是明确的:
foo & bar
foo&<i>bar</i>
foo&&& bar
<!-- …even the ones that were invalid as per the old definition, are now valid: -->
<a href="http://example.com/?x=1&y=2">foo</a>
&123
&abc
foo &0 bar
foo &lolwat bar
使用新定义,这是完全有效的 HTML——尽管我所知道的 HTML 验证器还没有识别出这一点。
所以我们已经确定并不是所有的符号字符都需要在 HTML 中转义。 半相关的有趣事实:在大多数情况下,也不需要转义
>
字符。 它没有特殊含义(因此是明确的),除非它是标记的一部分或未加引号的属性值。 例如,<p>foo > bar</p>
是完全有效且可靠的 HTML。
造成歧义的本质原因
如前所述,一些命名字符引用在没有尾随分号(例如 &
)的情况下工作,即使它是无效标记。 更复杂的是,这些实体在属性值中的处理方式不同。
如果字符引用作为属性的一部分使用,并且最后匹配的字符不是 U+003B 分号字符 (
;
),并且下一个字符是 U+003D 等号字符 (=
) 或字母数字 ASCII 字符,那么,由于历史原因,在 U+0026 AMPERSAND 字符 (&
) 之后匹配的所有字符必须是未使用的,并且不返回任何内容。 但是,如果下一个字符实际上是 U+003D EQUALS SIGN 字符 (=
),那么这是一个解析错误,因为在这些情况下,某些旧版用户代理会误解标记。
以这个(显然无效的)HTML 为例:
<p title="foo&bar">
foo&bar
</p>
在浏览器中尝试一下。 你会看到段落的文本内容显示为“foo&bar”,而标题属性值显示为“foo&bar”。
总结一下:未编码的 &
符号(有时有效)、模糊的 &
符号(始终无效)和编码的 &
符号(始终有效)之间存在差异。 未编码的 &
符号并不总是有歧义的 &
符号。 明确的 &
符号仍然无效。
在我看来,这有点令人困惑。 但它不一定是! 如有疑问,只需对你的 effin 符号进行编码。
对于希望处理 HTML 实体的库开发者来说,了解什么是不明确的 &
符号以及它们的工作原理尤为重要。 不考虑这些边缘情况可能会导致代码中出现 XSS 或其他安全漏洞。
相关文章
使用 Python 将 Pandas DataFrame 保存为 HTML
发布时间:2024/04/21 浏览次数:106 分类:Python
-
本教程演示如何将 Pandas DataFrame 转换为 Python 中的 HTML 表格。
使用 jQuery 更新 innerHTML
发布时间:2024/03/24 浏览次数:65 分类:JavaScript
-
在今天的文章中,我们将学习如何使用 jQuery 更新或替换元素的内部 HTML。
在 JavaScript 中获取 HTML 表单值
发布时间:2024/03/22 浏览次数:122 分类:JavaScript
-
本文展示了如何通过 id 和 name 属性检索 select-option 元素和一般 case input 文本元素的值。我们将在 JavaScript 中使用获取的值进行进一步的工作。
使用 JavaScript 将 HTML 表格导出到 Excel
发布时间:2024/03/21 浏览次数:176 分类:JavaScript
-
本教程演示了如何使用 JavaScript 将 HTML 表格数据导出到 Excel。
使用 JavaScript 编码 HTML
发布时间:2024/03/20 浏览次数:93 分类:JavaScript
-
本教程将教你如何使用不同的方法对 HTML 字符串进行编码。这些方法的共同点是字符串替换,它替换了具有潜在危险的字符。
使用 JavaScript 加载外部 HTML 文件
发布时间:2024/03/20 浏览次数:147 分类:JavaScript
-
本文演示了如何使用 JavaScript 和 jQuery 加载外部 html 文件。
使用 JavaScript 在 HTML 中使用按钮清除文本区域
发布时间:2024/03/20 浏览次数:97 分类:JavaScript
-
本教程提供了有关什么是事件侦听器、如何在 JavaScript 中添加事件侦听器以及如何使用 JavaScript 在 HTML 中通过按钮清除文本区域的信息。