在HTML中使用"""实体的用途

62

我正在修改由他人编写的一些 XHTML 文件。作为这个过程的一部分,我正在使用 Linq to XML 进行批量编辑。

我刚刚注意到,一些原始的 XHTML 文件在文本节点中包含 " HTML 实体。例如:

<p>Greeting: &quot;Hello, World!&quot;</p>

通过XElement.ToString()恢复XHTML文本时,&quot;实体被替换为普通双引号

<p>Greeting: "Hello, World!"</p>
问题:有人能告诉我为什么原作者要使用&quot;实体而不是普通的双引号吗?这些实体是否有我无法完全理解的用途?或者,正如我怀疑的那样,它们真的是不必要的吗?

我确实理解,在某些情况下需要使用&quot;,例如需要在HTML属性中放置双引号的情况。例如:

<a href="/images/hello_world.jpg" alt="Greeting: &quot;Hello, World!&quot;">
  Greeting</a>

有可能会感兴趣的是:寻找特殊字符的搜索引擎?。例如,通过SymbolHound搜索**&quot;**。 - DavidRR
http://www.fileformat.info/format/w3c/htmlentity.htm - firstpostcommenter
所以,双引号看起来像是双倍而不是单引号。 - Timo
一个防止 XSS 的保护?参考 https://www.youtube.com/watch?v=gd0EjD9_H5A - Alexred
5个回答

49

在元素内容中使用 &quot; 的动机是不可能的,也是没有必要的,但是可能的动机包括:对 HTML 规则的误解;使用生成此类代码的软件(可能是因为其作者认为这样更“安全”);以及对 &quot; 的含义的误解:许多人似乎认为它会产生“智能引号”(他们显然从未看过实际结果)。

无论如何,在 HTML(XHTML 或任何其他 HTML 版本)的元素内容中都永远没有必要使用 &quot;。在任何 HTML 规范中都没有任何东西将任何特殊含义分配给纯字符 "。

正如问题所述,它在属性值中具有作用,但即使在其中,如果值包含双引号,仍然大多数情况下可以简单地使用单引号作为定界符,例如 alt='Greeting: "Hello, World!"',或者如果您被允许更正自然语言文本中的错误,则可以使用正确的引号,例如alt="Greeting: “Hello, World!”"


有趣的是,在我正在处理的原始源文件中,存在左双引号(&ldquo;)右双引号(&rdquo;)的出现。 - DavidRR
1
HTML中有252个字符实体引用(在XHTML中有253个),详见HTML字符实体引用列表 - DavidRR
有没有想过为什么Jekyll总是使用这些转义的HTML符号来转换HTML正文?比如...当我将我的Tumblr博客转换为Jekyll时,它会这样做:<blockquote>“你成为成功企业家的能力在于... - Jwan622
1
我知道这个问题很久以前就被问过了,但如果内容是动态生成的(使用JS或其他东西),可能需要使用&quot;。例如:element.innerHTML = "Greeting: &quot;Hello World!&quot;";以避免破坏字符串。现在,当然有其他方法可以做到这一点(模板文字或单引号),但对于这种情况,它是一个可行的解决方案。 - applemonkey496
我在 Django 模板中遇到了问题,使用了 |safe 进行解决,谢谢。 - josue

17

原因 #1

曾经有一段时间,HTML/XHTML渲染器中存在许多错误/懒惰的实现,比正确的实现更为普遍。很多年前,我经常遇到在主流浏览器中使用未编码引号字符作为HTML/XHTML文档常规文本内容而导致的渲染问题。尽管HTML规范从未禁止在文本内容中使用这些字符,但通常会对它们进行编码,以便非规范兼容的浏览器和其他处理器可以更优雅地处理它们。因此,许多“老手”可能仍然会下意识地这样做。虽然这种方法并没有错,但现在可能已经不必要了,除非你的目标是一些非常古老的平台。

原因 #2

当HTML内容是动态生成的时候,例如通过将简单字符串值从数据库填充到HTML模板中,必须在嵌入生成的内容之前对每个值进行编码。一些常见的服务器端语言提供了一个单一函数来实现此目的,该函数仅编码所有可能在HTML文档中某些上下文中无效的字符。值得注意的是,PHP的htmlspecialchars()函数就是这样一个例子。虽然htmlspecialchars()有一些可选参数可以使其忽略引号,但这些参数很少被基本模板驱动系统的作者使用。结果是所有“特殊字符”都在它们出现在生成的HTML中的任何位置进行编码,而不考虑它们出现的上下文。再次强调,这并不是错误,只是不必要的。

8
根据我的经验,这可能是由基于字符串的工具自动生成的结果,作者不了解HTML规则。
当一些开发人员在没有使用特殊的XML导向工具的情况下生成HTML时,他们可能会采取确保所得到的HTML有效的方法,即必须转义所有内容
关于你提到的例子,之所以每个"出现的位置都被表示为&quot;,是因为使用这种方法可以安全地在属性和值中使用这样的“特殊”字符。
我还见过另一个动机,那就是人们认为,“我们必须明确表明我们的符号不是语法的一部分。”然而,通过使用正确的字符串操作工具,可以创建有效的HTML,请再看一遍上一段。
以下是一些基于C#的伪代码,但最好使用有效的方法和工具:
public class HtmlAndXmlWriter
{
    private string Escape(string badString)
    {
        return badString.Replace("&", "&amp;").Replace("\"", "&quot;").Replace("'", "&apos;").Replace(">", "&gt;").Replace("<", "&lt;");

    }

    public string GetHtmlFromOutObject(Object obj)
    {
        return "<div class='type_" + Escape(obj.Type) + "'>" + Escape(obj.Value) + "</div>";    

    }

}

很常见采用这种方法来生成HTML。


2
嗯,如果不使用特殊的面向XML的工具,通常无法区分包围属性值的引号和可能出现在属性值内部的引号。 - DavidRR
无,看起来像这样:void SerializeAsXml(MyStructure obj,TextWriter out){out.WriteLine("<start>");out.WriteLine("<item id=""+obj.Id+"" code=""+escaped(obj.Code)+"">"+escaped(obj.Value)+"</item></start>");猜猜“escaped(str)->str”是什么意思)) - 字符串导向的工具总是这样不太好看... - comdiv
是的,我明白了!在你的例子中,生成HTML的代码仅转义每个属性的值。那么,escaped()是自己编写的转义函数吗?还是来自诸如.NET Framework之类的库?(我鼓励您将代码示例纳入答案中。) - DavidRR
这只是一段糟糕的代码示例,用C#编写,因为它是我的主要语言。在PHP、Python、Java、C#、C、Erlang和LISP中都有这样的编码方式。虽然有大量适当的模块可以很好地完成它(例如,在.NET中,它是XElement家族)。但是糟糕的代码是永恒的东西。特别是在不同的页面生成器和mvc视图引擎中存在-它们进行这样的转义以不关心有效结构。 - comdiv

5
正如其他答案所指出的那样,它很可能是由某个工具生成的。
但如果我是文件的原始作者,我的答案将是:一致性。
如果我不允许在属性中使用双引号,为什么要将它们放在元素内容中?为什么这些规范总是有这些特殊情况.. 如果我必须编写HTML规范,我会说所有双引号都需要编码。完成。
今天的情况是这样的:在属性值中,我们需要编码双引号,除非属性值本身由单引号定义。在元素内容中,双引号可以被编码,但不是必须的。(我肯定还忘记了一些情况)。
双引号是规范的关键字,编码它们。小于/大于也是规范的关键字,编码它们等等。

1
很可能是因为他们使用了一个函数来转义属性和文本节点。 &amp; 不会造成任何伤害,所以为什么要通过使用两个转义函数并在它们之间进行选择来使代码变得更加复杂和容易出错呢?

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