(X)HTML中的未定义行为是什么?

25

(X)HTML 中是否存在未定义行为?

在尝试使用 <button> 标签进行渲染后,我开始思考这个问题。但是这并没有什么新意……

但我注意到也可以使用 <a> 标签。下面是完整的示例:

<button>
    normal text
    <b>bold text</b>
    <a href="http://www.example.com/">linked text</a>
</button>

这在Firefox中显示为以下内容:

而在Google Chrome中:

现在,在Firefox中,链接目标不可点击,只有按钮可以...但是,在Chrome中,链接是可点击的,并将重定向到IANA RFC2606 Page

这是未定义行为吗?还有没有其他可能被描述为未定义行为的(X)HTML情况?

4个回答

25

我需要做的不仅仅是像Yi Jiangmu is too short所给出的DTD一样进行检查,这比较复杂。

的确,XHTML 1.0 DTD明确禁止在您的问题中给出的情况下,将<a>元素作为<button>元素的子元素。然而,它并没有禁止<a>元素作为<button>元素的后代

因此

<button>
    normal text
    <b>bold text</b>
    <span><a href="http://www.example.com/">linked text</a></span>
</button>

这是XHTML 1.0 Strict DTD符合标准的。但它与问题中的按钮片段一样,在Firefox和Chrome之间存在行为差异。

现在,已知DTD在描述后代关系限制方面存在问题,因此上述示例符合DTD可能并不令人惊讶。

然而,XHTML 1.0规范的附录B除了DTD外还规范了后代限制。它说:

以下元素对它们可以包含哪些元素有禁止规定(请参阅SGML Exclusions)。该禁令适用于所有嵌套深度,即它包含所有后代元素。

button
不能包含input、select、textarea、label、button、form、fieldset、iframe或isindex元素。

请注意,它没有排除<a>元素。因此,似乎XHTML 1.0不禁止<a>元素成为<button>的非子后代,这种情况下的行为确实未定义。

这个遗漏几乎肯定是一个错误。在附录B中,<a>元素应该被列入禁止作为button后代的元素列表中。

HTML5(包括XHTML5)在这方面更加彻底。它说:

4.10.8 按钮元素

内容模型: 构成语段的内容,但不能有交互式内容后代。

其中交互式内容被定义为

交互式内容是专门用于用户交互的内容。
以下元素属于交互式内容:
- a - audio(如果存在controls属性) - button - details - embed - iframe - img(如果存在usemap属性) - input(如果type属性不处于隐藏状态) - keygen - label - menu(如果type属性处于工具栏状态) - object(如果存在usemap属性) - select - textarea - video(如果存在controls属性)
因此,在(X)HTML5中,<a>元素被禁止作为<button>元素的后代。

非常有趣。然而,我觉得你提到*(X)HTML5*有点奇怪。原本只计划推出XHTML2(但后来被放弃了),所以HTML5不应该是HTML4和XHTML1的下一个版本吗? - Yi Jiang
3
HTML5的命名本身就非常复杂。W3C称之为“HTML5”,而WHATWG则称其为“living HTML”。它包含了覆盖HTML序列化(语法)和XHTML序列化以及许多共同点(例如内容模型)的规范。然而,仍有很多人认为HTML5不包括XHTML,因此我只是用(X)HTML5作为一种简略表述,以明确说明两种序列化都被包括在内。 - Alohci
2
你可能忽略了<A>元素是锚点元素的事实,因此可以用于书签文档的一部分。因此,它不应被视为<BUTTON>元素的无效后代。也许这表明<A>元素被过度使用而不是你的推理有问题(我同意你的推理)。 - Dancrumb
1
@Dancrumb - 很好的观点。然而,如果这是允许<button>的非子级<a>后代的原因,为什么直接子级会被禁止呢?考虑到在HTML4中任何元素都可以作为锚点的目标,以及需要将锚点目标放置在按钮内的用例非常薄弱,我怀疑这不足以证明允许这种情况的正当性。 - Alohci
@Dancrumb:请记住,在HTML 5中使用a元素创建命名锚点已经过时了(顺便说一下,WHATWG最近才将其称为这样的子元素,之前他们称之为滚动发布结构)。 - Marcel Korpel

4

XHTML中关于<button>的说明如下:

<!-- button uses %Flow; but excludes a, form and form controls -->
<!ENTITY % button.content
   "(#PCDATA | p | %heading; | div | %lists; | %blocktext; |
    table | %special; | %fontstyle; | %phrase; | %misc;)*">

因此,在XHTML中,<a>被明确地排除在外。在<button>内允许的元素似乎与HTML-4.0中几乎相同。


这是更正确的答案,因为 OP 特别要求 XHTML,而不是 HTML4。 - jamesmortensen
@jmort253:谢谢,但这可能会有两种方式,因为XHTML更多地是将HTML4转化为XML(因此是严格的),所以如果您忽略HTML允许的松散性,它们通常是相同的。从XHTML规范的XSD版本中引用会更加严谨,但我发现DTD比XSD更容易阅读。 - mu is too short

4

HTML 4 规范<button> 定义为:

<!ELEMENT BUTTON - -
     (%flow;)* -(A|%formctrl;|FORM|FIELDSET)
     -- push button -->

如果我对DTD的解读正确的话(我并不是非常熟悉它),<a>元素被明确禁止嵌套在button中,因此你看到的HTML是无效的,因此它是未定义的行为。

你能澄清一下DTD的哪个部分意味着<a>是被禁止的吗?XHTML呢?OP是在问关于XHTML的吗?谢谢。 - jamesmortensen
@jmort253: "-(A|%formctrl;|FORM|FIELDSET)" 禁止使用 <a>, <form>, <fieldset> 和表单控件(如 <button>, <input> 等)。 - mu is too short
@jmort253:我已经添加了一个带有XHTML DTD参考的答案。 - mu is too short

3
补充Alohci的好回答,更具体地回答问题:如果您的(X)HTML是无效的,则行为始终未定义。在这种情况下,浏览器可以自由解释标记,或者根据机会进行解释,甚至拒绝解释(没有真正的浏览器会这样做)。这正是标记混乱引入的问题,也是XML严格解析规则和HTML5规范增长到> 500页的起源。

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