我是否在 < a href... > 中编码 & 符号?

我正在编写自动生成 HTML 的代码,我希望它能正确地进行编码。

假设我正在生成一个指向以下 URL 的链接:

http://www.google.com/search?rls=en&q=stack+overflow

我假设所有属性值都应该是 HTML 编码的。(如果我说错了,请纠正我。)这意味着如果我把上面的 URL 放到一个锚标记中,我应该把与号编码为 &amp;,像这样:

<a href="http://www.google.com/search?rls=en&amp;q=stack+overflow">

是这样吗?

66952 次浏览

是的,没错。HTML 实体在 HTML 属性中进行解析,而偏离的 &将产生歧义。这就是为什么应该始终在 所有HTML 属性中编写 &amp;而不仅仅是 &的原因。

也就是说,只有 &和引号 需要被编码。如果在属性中有特殊字符(如 é) ,则不需要对这些字符进行编码以满足 HTML 解析器的要求。

通常情况下,URL 需要使用非 ASCII 字符(如 é)进行特殊处理。您必须使用百分比转义对它们进行编码,在本例中,它将给出 %C3%A9,因为它们是由 RFC 1738定义的。然而,RFC1738已经被 RFC 3986(URI,统一资源标识符)和 RFC 3987(IRI,国际化资源标识符)所取代。因此,现在可以安全地在 URL 中包含非 ASCII 字符,无论是否采用百分比编码。

根据当前官方的 HTML 建议,与号必须转义,例如在这样的上下文中转义为 &amp;。然而,浏览器并不需要它,HTML5CR 建议将其设置为 规则,以便在属性值中应用特殊规则。目前的 HTML5验证器在这方面已经过时了(请参阅带注释的 漏洞报告)。

在属性值中转义 & 符号仍然是可能的,但是除了使用当前的工具进行验证之外,实际上没有必要在 href值中转义它们(如果开始转义它们,犯错误的风险很小)。

是的,你应该把 &转换成 &amp;

W3C 的这个 HTML 验证器工具对于这样的问题很有帮助。它将告诉您特定页面的错误和警告。

关于链接中的 URL,您有两个标准(<a href)。

第一个标准是 RFC 1866 (HTML 2.0)。“数据字符”可以读取在作为 HTML 属性的值时需要转义的字符。(属性本身根本不允许使用特殊字符,例如 <a hr&ef="http://...<a hr&amp;ef="http://...。)

后来这已经进入了 < strong > HTML 4 标准,你需要转义的字符是:

<   to   &lt;
>   to   &gt;
&   to   &amp;
"   to   &quote;
'   to   &apos;

另一个标准是 RFC 3986 “通用 URI 标准”,其中处理 URL (当浏览器将要跟踪某个链接时,因为用户单击了 HTML 元素,所以会发生这种情况)。

reserved    = gen-delims / sub-delims


gen-delims  = ":" / "/" / "?" / "#" / "[" / "]" / "@"


sub-delims  = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="

转义这些字符以便客户端知道它们是表示数据还是分隔符非常重要。

例如:

https://example.com/?user=test&password&te&st&goto=https://google.com

例如,一个完全合法的 URL

https://example.com/?user=test&password&te%26st&goto=https%3A%2F%2Fgoogle.com

HTML 属性值中的完全合法 URL 示例:

https://example.com/?user=test&amp;password&amp;te%26st&amp;goto=https%3A%2F%2Fgoogle.com

同样重要的情况是:

  • JavaScript 代码作为一个值:

    (是的,;;是正确的。)

  • JSON 作为一个值:

    <a href="..." data-analytics="{&quot;event&quot;: &quot;click&quot;}">...</a>

  • 转义的东西里面转义的东西,双重编码,URL 里面的 URL 里面的参数,等等..。

    http://x.com/?passwordUrl=http%3A%2F%2Fy.com%2F%3Fuser%3Dtest&amp;password=&quot;&quot;123

我发布了一个新的答案,因为我发现 zneak 的答案没有足够的例子,没有显示 HTML 和 URI 处理作为不同的方面和标准,并有一些小的东西缺失。