为什么迷路<p> </p>结束标记会生成一个空段落?

时间:2012-07-19 23:42:41

标签: html html5 dom syntax html-parsing

显然,如果</p>元素中的body结束标记没有匹配的开始标记,则大多数(如果不是所有)浏览器都会在其位置生成空段落:

<!DOCTYPE html>
<title></title>
<body>
</p>
</body>

即使结束标记周围存在任何文本,它们也不会成为此p元素的一部分 - 它始终为空,文本节点将始终存在:

<!DOCTYPE html>
<title></title>
<body>
some text</p>more text
</body>

如果body的上述内容包含在<p></p>标签中......我会让您猜测会发生什么:

<!DOCTYPE html>
<title></title>
<body>
<p>some text</p>more text</p>
</body>

有趣的是,如果</p>标记前面没有<body></body>标记,则除IE9及更旧版本之外的所有浏览器都会生成一个空段落(另一方面,IE≤9将始终创建一个,而IE10及更高版本的行为与所有其他浏览器相同):

<!DOCTYPE html>
<title></title>
</p>
<!DOCTYPE html>
<title></title>
</p><body>
<!DOCTYPE html>
<title></title>
</p></body>

我找不到任何引用规定没有相应的开始标记的结束标记应该生成一个空元素,但考虑到它首先不是有效的HTML,这不应该是令人惊讶的。实际上,我只发现浏览器使用p元素(以及某种程度上的br元素)执行此操作!),但没有解释为什么。

在使用传统HTML解析器和HTML5解析器的浏览器中,它非常一致,但是在怪癖模式和标准模式下都应用。因此,推断这是为了向后兼容早期规范或遗留行为,这可能是公平的。

事实上,我确实在this comment的答案中找到了a somewhat related question,这基本上证实了这一点:

  

&lt; p&gt;的原因标签有效未封闭是最初的&lt; p&gt;被定义为“新段落”标记,而不是p是容器元素。相当于&lt; br&gt;是一个“新线”标记。您可以在1992年的本文档中看到如此定义:http://www.w3.org/History/19921103-hypertext/hypertext/WWW/MarkUp/Tags.html和1993年的这个:http://www.w3.org/MarkUp/draft-ietf-iiir-html-01.txt因为有一些网页预先确定了变更,浏览器解析器始终与现有的网页尽可能向后兼容网页内容,始终可以使用&lt; p&gt;那样。

但它并没有完全解释为什么解析器将显式</p>结束标记(带斜杠)简单地视为一个标记,并在DOM中生成一个空元素。当语法不像more recently或其他什么那样严格定义时,这是一些解析器错误处理约定的一部分吗?如果是这样,它是否记录在任何地方?

2 个答案:

答案 0 :(得分:16)

HTML5中记录了所需的。请参阅http://w3c.github.io/html/syntax.html#the-in-body-insertion-mode并向下搜索An end tag whose tag name is "p",并说明:

  

如果打开元素的堆栈在按钮范围内没有元素   使用与令牌相同的标记名称,这是一个解析   错误;就像是看到标签名为“p”的开始标签一样   重新处理当前令牌。

如果p标记无法与现有的</p>标记匹配,则翻译为英语意味着创建<p>元素。

为什么它是如此,更难确定。通常,这是因为过去某些浏览器会导致这种情况发生,并且网页依赖于行为,因此其他浏览器也必须实现它。

答案 1 :(得分:1)

HTML4 DTD表示结束标记对于段落元素是可选的,但是开始标记是必需的。

HTML4的SGML declaration表示omittag为“是”,这意味着可以暗示开始标记。

结束标记遵循SGML规则:

  

结束标记关闭,返回匹配的开始标记,所有未关闭的插入开始标记,省略结束标记

Anonymous block boxes是为内联元素(如文本节点)生成的,因此它们不需要包含在段落元素中。

Mozilla错误数据库中有一个线程可以解释这种行为:

以下是Boris Zbarsky的相关评论:

  

实际上,正如我所理解的那样,正确解析SGML / HTML 需要我们   表现得这样。也就是说,'&lt;'下一个标签是一种有效的结束方式   以前标签的标记......

Ian Hickson总结:

  

在这里工作的基本原则是,标记是通过延迟任何结束标记直到所有其他打开元素都关闭之后修复的,并且没有尝试使DOM遵循HTML DTD。 / p>

<强>参考