自关闭脚本元素为何不起作用?


1346

浏览器无法正确识别的原因是什么:

<script src="foobar.js" /> <!-- self-closing script element -->

只有这是公认的:

<script src="foobar.js"></script>

这是否打破了XHTML支持的概念?

注意:此声明至少对于所有IE(6-8 beta 2)都是正确的。


12
在Chrome和Opera中工作
corymathews

46
Chrome的某些最新版本似乎已破坏了此功能,自关闭脚本标签在Chrome中不再起作用
Adam Ness 2010年

13
不只是脚本标签。我也不相信自动关闭div标签也可以。
DOK

6
截至2011年7月,Chrome和Firefox出现此问题。“这不是错误,而是功能”-真烦人。
Martin Konicek 2011年

Answers:


481

XHTML 1规范说:

С.3。元素最小化和空元素内容

给定内容模型不EMPTY为空的元素实例(例如,空的标题或段落),请不要使用最小化形式(例如use <p> </p>和not <p />)。

XHTML DTD将脚本元素指定为:

<!-- script statements, which may include CDATA sections -->
<!ELEMENT script (#PCDATA)>

111
不过,“请勿”与“不得”相同。这是准则(出于兼容性的考虑,如本节标题所建议),而不是规则。
Konrad Rudolph

42
实际上,对于此限制,我找不到任何用处:)似乎完全是人为的。
squadette

22
olavk给出了正确的答案。XHTML 1.0的附录C并不是事物按原样进行的原因—而是如何按原样进行工作。
hsivonen

32
这不是规范的规范部分。它仅是有关如何处理不支持XHTML的
Kornel,

12
问题<script />不在于该规范不允许这样做,而是如果内容类型不是application / xhtml + xml,则浏览器不会将其解释为“非标记汤”。请参阅:stackoverflow.com/questions/348736/…@shabunc :浏览器似乎可以理解它,但实际上发生的是将内容放在段落的<p />之后,这是因为将squadette的引号解释为自< p>是非空的,它不能自动关闭。在XHTML 1.1中,它可以是自动关闭的。

241

要补充Brad和squadette所说的话,自动关闭的XML语法<script />实际上正确的XML,但是要使其在实践中起作用,您的Web服务器还需要将您的文档作为格式正确的XML发送,并带有XML模仿类型,例如application/xhtml+xmlHTTP。 Content-Type头(和作为text/html)。

但是,发送XML mimetype将导致您的网页无法被IE7解析,IE7只喜欢text/html

w3

总之,“ application / xhtml + xml”应该用于XHTML家族文档,而“ text / html”的使用应该限于与HTML兼容的XHTML 1.0文档。也可以使用'application / xml'和'text / xml',但是在适当的时候,应该使用'application / xhtml + xml'而不是那些通用的XML媒体类型。

几个月前,我对此感到困惑,唯一可行的(与FF3 +和IE7兼容)解决方案是将旧<script></script>语法与text/html(HTML语法+ HTML mimetype)一起使用。

如果您的服务器text/html在HTTP标头中发送该类型,即使使用其他格式正确的XHTML文档,FF3 +仍将使用其HTML呈现模式,这<script />将不起作用(此更改是Firefox以前不太严格的更改)。

无论您是否对http-equivmeta元素,文档中的XML序言或doctype 有任何摆弄,都会发生这种情况-Firefox在获取text/html标头后会分支,这将确定HTML或XML解析器是否在文档内部,而HTML解析器无法理解<script />


3
然后得出以下结论是否正确:如果您放弃对IE7的支持,发送text / xml将获得广泛的浏览器对<script />的支持?
克里斯·莫斯基尼

7
因此,简而言之,<script />仅在页面的MIME类型为xhtml / xml时才有效。对于常规的text / html页面,它将不起作用。并且,如果我们尝试使用“ xhtml / xml” MIME类型,则会破坏IE的兼容性。总而言之,保持冷静并使用<script> ... </ script>谢谢Joe ;-)
Navin Israni 2013年

1
很好的解释。值得注意的另一点是.html,出于类似的原因,无论元标记如何,Firefox也将本地文件呈现为标记汤。对于XHTML文件,只有命名为,Firefox才会相应地呈现它们.xhtml
alecov 2015年

@ChrisMoschini。可能是,但是使用application/xhtml+xml,不是text/xml
TRiG

166

万一有人好奇,最终的原因是HTML最初是SGML的方言,SGML是XML的怪异哥哥。在SGML域中,可以在DTD中将元素指定为自动关闭(例如BR,HR,INPUT),隐式关闭(例如P,LI,TD)或显式关闭(例如TABLE,DIV,SCRIPT)。XML当然没有这个概念。

尽管现代的浏览器的解析模型不再是纯粹的SGML,但现代浏览器所使用的标记汤解析器却是从此继承而来的。当然,除非您使用XML mime类型发送它,否则您精心设计的XHTML将被视为编写不良的SGML风格的标记汤。这也是为什么

<p><div>hello</div></p>

...被浏览器解释为:

<p></p><div>hello</div><p></p>

...这是一个可爱的,难以理解的错误的秘诀,当您尝试对DOM进行编码时,该错误会使您陷入困境。


4
我很好奇。浏览器为什么选择以这种方式解释它?
艾哈迈德(Ahmed)Aeon Axan

32
@AhmedAeonAxan:P元素不能包含DIV元素(这是无效的HTML),因此浏览器会在开始标记之前隐式关闭P元素(定义为“隐式可关闭”)DIV。但是,浏览器在这方面的行为往往有所不同(因为它们可以处理任何无效的HTML)。
MrWhite

5
@ColeJohnson不,这不是吊牌汤;greim使有效和无效HTML之间的边界混乱了。当作者不在乎规则时,您会得到标签汤,因为浏览器使用错误校正。</p>另一方面,缺少的结束标记实际上是HTML定义的一部分!
李斯特先生,2015年

3
@MrLister-排序。“标记汤”描述了如何解析HTML,而不是其编写方式。它是一个术语,用于描述用于理解HTML的不同策略的浏览器,与严格的XML解析相反。XML解析仅适用于XML mime类型,但是由于这些类型从未得到广泛使用,因此浏览器会退回到各种“标签解决方案”方案,即使对于其他有效文档也是如此。
greim 2015年

8
HTML5实际上标准化了“标记汤”的解析,包括一种处理无效标记的一致方法。在此之前,浏览器不得不自己弄清楚如何处理无效的标记,从而导致不一致。当前浏览器中的HTML解析器是有史以来最先进的软件之一。速度飞快,可以处理大多数输入,产生一致的结果。
斯蒂恩·德·威特

161

其他人回答了“如何”并引用了规范。<script/>经过数小时的研究,他们找到了错误报告和邮件列表,这是“为什么不这样” 的真实故事。


HTML 4

HTML 4基于SGML

SGML有一些shorttags,如<BR//<B>text</><B/text/,或<OL<LI>item</LI</OL>。XML采用第一种形式,将结尾重新定义为“>”(SGML是灵活的),因此它变为<BR/>

但是,HTML没有重新定义,因此<SCRIPT/> 表示 <SCRIPT>>
(是的,“>”应的内容部分,并且所述标签仍然关闭。)

显然,这与XHTML不兼容,并且破坏许多站点(在浏览器足够成熟时可以解决 此问题),因此没有人实现短标记,并且规范不建议这样做

实际上,所有“有效的”自封尾标签都是技术上不合格的解析器上带有禁止的结束标签的标签,实际上是无效的。W3C 提出了此hack,以通过使其与HTML兼容来帮助过渡到XHTML 。

<script>的结束标记是不被禁止

“ Self-end”标记是HTML 4中的一种hack,没有意义。


HTML 5

HTML5具有五种类型的标记,并且仅允许“ void”和“ foreign”标记为自动关闭

因为<script>不是void(可能包含内容)并且不是外来对象(例如MathML或SVG),<script>所以无论您如何使用它都不能自动关闭。

但为什么?他们难道不能认为它是外国的,特例或其他东西吗?

HTML 5旨在与HTML 4和XHTML 1的实现向后兼容。它的语法主要涉及文档化和实现统一。(这就是为什么尽管无效的HTML4 等也有效的HTML 5的原因。)<br/> <hr/>

自关闭<script>是实现过去有所不同的标签之一。它用于在Chrome,Safari浏览器的工作和Opera ; 据我所知,它从来没有在Internet Explorer或Firefox中起作用。

起草HTML 5并遭到拒绝是因为HTML 5 破坏了 浏览器的 兼容性,对此进行了讨论。具有自关闭脚本标记的网页在旧浏览器中可能无法正确呈现(如果有的话)。还有其他建议,但它们也不能解决兼容性问题。

在草稿发布之后,WebKit更新了解析器以使其符合要求。

<script>由于与HTML 4和XHTML 1的向后兼容性,在HTML 5中不会发生自关闭。


XHTML 1 / XHTML 5

其他答案所述,当真正用作XHTML时,<script/>实际上是封闭的。

除了规范说,应该在作为HTML服务工作过:

XHTML文档...可以标记为Internet媒体类型“ text / html” [RFC2854],因为它们与大多数HTML浏览器兼容。

所以发生了什么事?

人们问的Mozilla让火狐解析符合文档作为XHTML不管指定的内容头(被称为内容嗅探)。这将允许自动关闭脚本,并且由于网络托管者还不够成熟,无法提供正确的标头,因此无论如何都需要进行内容嗅探。IE很擅长

如果第一次浏览器之战没有以IE 6结束,那么XHTML可能也已列入清单。但这确实结束了。IE 6的XHTML 有问题。实际上,IE 根本不支持正确的MIME类型,这迫使每个人都使用text/htmlXHTML,因为IE在整个十年中都占有主要的市场份额

而且内容嗅探可能 真的很糟,人们表示应该停止嗅探。

最终,事实证明W3C 并不意味着XHTML是可嗅探的:该文档既是 HTML和XHTML,又是Content-Type规则。可以说他们坚定地坚持“只是遵循我们的规范”,而忽略了实际的做法。这个错误一直持续到后来的XHTML版本。

无论如何,这个决定解决了 Firefox 的问题。Chrome 诞生已有7年了; 没有其他重要的浏览器。这样就决定了。

由于遵循以下规范,仅指定doctype不会触发XML解析。


1
@AndyE当您编写自动关闭的<script>时,当时的主要浏览器并不认为它已关闭,并且会将子序列html解析为javascript,从而导致有效的HTML5在这些旧的浏览器上中断。因此,该提案被拒绝。在链接的HTML5邮件列表中对此进行了说明。
羊皮的

2
@AndyE:您所描述的是向前兼容性-旧代码与新的编译器/解释器/解析器一起工作的能力。向后兼容性是新代码与旧的编译器/解释器/解析器一起使用的能力。因此,是的,因此存在向后兼容性的问题,因为考虑到新规范编写的页面将无法在旧的浏览器中运行(是的,这是Web编程的传统,尝试使新代码尽可能在旧的浏览器中运行)。
slebetman

3
@Dmitry现实是,禁止使用自封闭脚本是一条路。通过链接,自动关闭的<script>将破坏所有浏览器,用户将只看到空白页-游戏机,互联网电视,公司Win7 PC 上的IE 11 ,数百万个Java运行时或数十亿部智能手机。您可以在大多数设备上升级大多数语言的大多数WebView吗?如果HTML5试图像XHTML2这样失败。
羊皮的


2
一点点纠正:在HTML中看起来像是自动关闭的标签不是带有可选结束标签的标签,而是带有被禁止的结束标签(空标签或空标签)的标签。带有可选结束标签(例如<p>或)的标签<li>不能被“自封闭”,因为它们可以包含内容,因此<p/>,如果该元素中允许,则like这样的代码仅是(格式错误的)开始标签及其后面的内容。 ,最终将出现在其中。
伊利亚·斯特雷钦

44

Internet Explorer 8和更早版本不支持XHTML解析。即使您使用XML声明和/或XHTML文档类型,旧的IE仍会将文档解析为纯HTML。在纯HTML中,不支持自动关闭语法。尾部的斜杠只是被忽略,您必须使用一个显式的结束标记。

即使支持XHTML解析的浏览器(例如IE 9和更高版本)仍将文档解析为HTML,除非您使用XML内容类型提供文档。但是在那种情况下,旧的IE根本不会显示文档!


9
“ IE不支持XHTML解析。” 在撰写本文时,对于IE版本是正确的,但现在不再正确。
EricLaw 2013年

@EricLaw您能否阐明IE的哪个版本已解决此问题?(以及任何特定条件-例如,需要有效的文档类型)
scunliffe 2014年

2
@scunliffe IE9是第一个完全支持XHTML的版本。blogs.msdn.com/b/ie/archive/2010/11/01/...
EricLaw

28

上面的人已经很好地解释了这个问题,但是可能使事情变得清楚的一件事是,尽管人们<br/>一直在HTML文档中使用诸如此类的内容,但/基本上处于这种位置的任何内容都将被忽略,并且仅在试图使可以解析为XML和HTML的东西。尝试使用<p/>foo</p>,例如,您会得到一个普通的段落。


22

自动关闭脚本标记将不起作用,因为脚本标记可以包含内联代码,并且HTML不够灵巧,无法根据属性的存在打开或关闭该功能。

另一方面,HTML确实具有出色的标记,可以包含对外部资源的引用:<link>标记,它可以是自动关闭的。它已经包括样式表,RSS和Atom提要,规范URI以及各种其他功能。为什么不使用JavaScript?

如果您希望脚本标签是自封闭的,则不能像我所说的那样做,但是有一种替代方法,尽管不是明智的选择。您可以使用自行关闭链接标记,并通过给其提供文本/ javascript和rel作为脚本的类型来链接至JavaScript,如下所示:

<link type="text/javascript" rel ="script" href="/path/tp/javascript" />

4
我喜欢那样,为什么它不“聪明”?
Josh M.

5
因为有一个预定义的脚本标签,可以准确地执行加载脚本的工作。.为什么您还要用其他东西混淆事情呢?锤子钉在钉子里。用鞋子会不会很聪明?
戴夫·劳伦斯

8
@daveL-我们有<style>标签,但对外部CSS文件使用链接标签。链接标记的定义:“ <link>标记定义文档和外部资源之间的链接。” 似乎合理的逻辑是将链接标记用于外部CSS或JS ...这就是...在外部文件中进行链接。注意我不是在谈论spec / cross-browserness / etc,我只是在评论使用链接标记同时引入CSS和JS的逻辑性质...如果那样的话,这实际上是很有意义的。不确定鞋子是否合适。
Jimbo Jonny

20

与XML和XHTML不同,HTML不了解自动关闭语法。将XHTML解释为HTML的浏览器不知道该/字符表明该标签应该是自动关闭的。取而代之的是,他们将其解释为空属性,并且解析器仍然认为标记为“打开”。

正如<script defer>被视为<script defer="defer"><script />被视为<script /="/">


33
这种解释很优雅,但实际上是错误的。如果为true,则DOM中的script元素将具有“ /”属性。我已经检查了IE,Firefox和Opera,它们实际上都没有包含这样的属性。
Alohci

11
/不是有效的属性名称字符,因此将其丢弃。否则,这种解释非常清楚。
hallvors-恢复莫妮卡

1
实际上,某些HTML解析器(尤其是验证器)可能会将解释/为NET(空端标记)构造的一部分。
IllidanS4希望莫妮卡回到

18

Internet Explorer 8和更早版本不支持XHTML的正确MIME类型application/xhtml+xml。如果您以XHTML的形式提供服务text/html,而这些Internet Explorer的较早版本必须执行任何操作,则它将被解释为HTML 4.01。您只能对任何允许省略结束标记的元素使用短语法。请参阅HTML 4.01规范

XML“短格式”被解释为名为/的属性,该属性(因为没有等号)被解释为具有“ /”的隐式值。在HTML 4.01中,这是完全错误的-不允许使用未声明的属性-但浏览器将忽略它。

IE9和更高版本支持XHTML 5一起提供application/xhtml+xml


IE 9支持XHTML,而IE不再> 51%。你能更新你的答案吗?
Damian Yerrick

5

那是因为SCRIPT TAG不是无效元素。

HTML文档中 -VOID ELEMENTS 根本不需要“结束标记”!

xhtml中,所有内容都是通用的,因此都需要终止,例如“结束标记”;包括br的简单换行符as <br></br>或它的简写 <br />

但是,脚本元素决不能是void或参数化元素,因为在其他任何内容之前,脚本标签都是浏览器指令,而不是数据描述声明。

原则上,仅需要语义终止指令(例如“关闭标签”)来处理语义不能被后续标签终止的指令。例如:

<H1>语义不能被跟随符终止,<P>因为它没有足够的自身语义来覆盖并终止先前的H1指令集。尽管它能够将分成新的段落行,但是它不足以覆盖当前的字体大小和样式行高,使之流中倾泻而下,即从H1泄漏(因为P没有) )。

这就是发明“ /”(终止)信号的方式和原因。

一个通用的无描述终止标签,例如< />,对于遇到的级联中的任何单个下降都足够了,例如:<H1>Title< />但这并非总是如此,因为我们还希望能够“嵌套” Stream的多个中间标签:split变成洪流,然后包裹/掉落到另一个瀑布上。结果,诸如这样的通用终止符< />将无法确定要终止的属性的目标。例如:<b>粗体 <i>斜体 < /> 斜体 </>正常。无疑将无法正确理解我们的意图,并且极有可能将其解释为粗体,粗体,斜体,粗体

这就是包装器(即容器)这一概念的诞生。(这些概念是如此相似,以致于无法辨别,有时同一元素可能同时具有。<H1>包装器和容器同时位于。而<B>语义包装器只是一个)。我们需要一个没有语义的普通容器。当然,DIV元素的发明也随之而来。

DIV元素实际上是2BR容器。当然,CSS的出现使整个情况变得比以前更怪异,并造成了许多巨大后果的混乱-间接地!

因为使用CSS可以轻松地覆盖新发明的DIV的本地BR前后行为,所以通常将其称为“不执行任何操作的容器”。这是自然的错误!DIV是块元素,将在结束信令之前和之后自然中断流的行。不久,WEB开始遭受页面DIV感染。他们大多数还是。

CSS的到来,它具有完全覆盖和完全重新定义任何HTML Tag的本机行为的功能,从而以某种方式设法混淆和模糊了HTML存在的全部含义...

突然,所有HTML标记似乎都过时了,它们被污损了,剥夺了所有原始含义,身份和用途。您会以某种方式获得不再需要它们的印象。说:一个容器包装标签就足够了所有数据表示。只需添加所需的属性。为什么没有有意义的标签呢?随便发明标签名称,让CSS剩下的麻烦。

这就是xhtml的诞生方式,当然是巨大的挫折,它是由新来者付出了如此高昂的代价,并且对什么是什么以及这一切的可恶目的有一个错误的认识。W3C从万维网发展到哪里错了,同志们!

HTML的目的是有意义的数据流传输给人类接收者。

传递信息。

正式的部分只是为了帮助信息传递的清晰。xhtml对此信息没有丝毫考虑。-对此,信息绝对无关紧要。

此事中最重要的事情是要知道并能够理解xhtml不仅仅是某些扩展HTML的版本,xhtml是完全不同的野兽;地面 因此将它们分开是明智的。


3

这里已经很好地描述了 “真正的XHTML”,“伪XHTML”和HTML之间的区别以及服务器发送的MIME类型的重要性。如果您想立即尝试,这里是带有实时预览的简单可编辑代码段,其中包括适用于功能强大的浏览器的自封闭脚本标签:

div { display: flex; }
div + div {flex-direction: column; }
<div>Mime type: <label><input type="radio" onchange="t.onkeyup()" id="x" checked  name="mime"> application/xhtml+xml</label>
<label><input type="radio" onchange="t.onkeyup()" name="mime"> text/html</label></div>
<div><textarea id="t" rows="4" 
onkeyup="i.src='data:'+(x.checked?'application/xhtml+xml':'text/html')+','+encodeURIComponent(t.value)"
><?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
[<!ENTITY x "true XHTML">]>
<html xmlns="http://www.w3.org/1999/xhtml">
<body>
  <p>
    <span id="greet" swapto="Hello">Hell, NO :(</span> &x;.
    <script src="data:text/javascript,(g=document.getElementById('greet')).innerText=g.getAttribute('swapto')" />
    Nice to meet you!
    <!-- 
      Previous text node and all further content falls into SCRIPT element content in text/html mode, so is not rendered. Because no end script tag is found, no script runs in text/html
    -->
  </p>
</body>
</html></textarea>

<iframe id="i" height="80"></iframe>

<script>t.onkeyup()</script>
</div>

您应该Hello, true XHTML. Nice to meet you!在下面的文本区域中看到。

对于无法使用的浏览器,您可以复制文本区域的内容并将其另存为扩展名为(.xhtml.xht)的文件(感谢Alek的提示)。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.