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

问题描述 投票:1236回答:11

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

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

只有这一点得到承认:

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

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

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

javascript html internet-explorer xhtml
11个回答
457
投票

XHTML 1规范说:

С.3. Element Minimization and Empty Element Content

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

XHTML DTD将脚本元素指定为:

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

5
投票

那是因为SCRIPT TAG不是一个VOID ELEMENT。

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

在xhtml中,一切都是通用的,因此它们都需要终止,例如一个“结束标签”;包括br,一个简单的换行符,如<br></br>或其简写<br />

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

原则上,语义终止指令(例如,“结束标签”)仅用于处理指令,其语义不能被后续标签终止。例如:

<H1>语义不能被后面的<P>终止,因为它没有足够的自己的语义来覆盖并因此终止先前的H1指令集。虽然它能够将流分解为一个新的段落行,但它不够“强大”来覆盖当前的字体大小和样式行高,即从H1泄漏(因为P没有它) )。

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

< />一样的通用无描述终止标签,对于遇到的级联的任何单一下降都是足够的,例如:<H1>Title< />但情况并非总是如此,因为我们还希望能够“嵌套”,流的多个中间标记:在包裹/落入另一个级联之前分裂成种子。因此,诸如< />之类的通用终结符将无法确定要终止的属性的目标。例如:<b>bold <i>bold-italic < /> italic </>normal。毫无疑问,我们的意图无法正确,并且很可能将其解释为大胆的粗体大胆的正常。

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

DIV元素实际上是2BR-Container。当然,CSS的出现使得整个情况比其他情况更糟糕,并且造成了许多重大后果的巨大混乱 - 间接!

因为使用CSS,您可以轻松覆盖新发明的DIV的原生前后行为,它通常被称为“无所事事的容器”。哪个,自然是错的! DIV是块元素,并且在结束信令之前和之后将原生地断开流的线。不久,WEB开始遭受DIV-itis页面的困扰。他们中的大多数仍然是。

CSS的出现使其能够完全覆盖并完全重新定义任何HTML标记的本机行为,以某种方式设法混淆和模糊HTML存在的整个含义......

突然间,所有的HTML标签看起来都像是过时的,它们被污损,剥夺了它们原有的意义,身份和目的。不知怎的,你会得到他们不再需要的印象。说:单个容器包装标签足以满足所有数据的呈现。只需添加所需的属性即可。为什么不使用有意义的标签;随时创建标记名称,让CSS打扰其余部分。

这就是xhtml诞生的方式,当然也是一种直率的,被新来者付出的沉重代价以及对什么是什么的扭曲的看法,以及这一切的目的是什么。 W3C从万维网走到了什么错了,同志们?!!

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

提供信息。

正式部分仅用于帮助清晰地传递信息。 xhtml没有对信息做出丝毫考虑。 - 对它而言,信息绝对无关紧要。

在这个问题上最重要的是知道并且能够理解xhtml不仅仅是某些扩展HTML的版本,xhtml是一个完全不同的野兽;理由;因此将它们分开是明智的。


2
投票

“真正的XHTML”,“虚假XHTML”和HTML之间的区别以及服务器发送的MIME类型的重要性是already described here well。如果你想立即试用,这里有一个简单的可编辑片段,带有实时预览,包括适用于浏览器的自闭脚本标签:

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>

你应该在textarea下面看到Hello, true XHTML. Nice to meet you!

对于无法使用的浏览器,您可以复制textarea的内容并将其保存为带有.xhtml(或.xht)扩展名(thanks Alek for this hint)的文件。


227
投票

为了补充Brad和squadette所说的,自动关闭XML语法<script />实际上是正确的XML,但是为了在实践中工作,您的Web服务器还需要将文档作为正确形成的XML发送,其中包含XML模仿类型application/xhtml+xml in HTTP Content-Type标头(而不是text/html)。

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

来自w3

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

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

如果您的服务器在其HTTP标头中发送text/html类型,即使使用其他正确形成的XHTML文档,FF3 +也将使用其HTML呈现模式,这意味着<script />将无法工作(这是一个更改,Firefox以前不那么严格)。

无论是否在文档中使用http-equiv元素,XML prolog或doctype,都会发生这种情况 - 一旦获得text/html标头,Firefox就会分支,这决定了HTML或XML解析器是否在文档内部查看,而HTML解析器不会了解<script />


152
投票

如果有人好奇,最终的原因是HTML最初是SGML的方言,这是XML的奇怪的哥哥。在SGML-land中,可以在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>

...这是一个可爱的晦涩bug的秘诀,当你尝试对DOM进行编码时,它会让你陷入困境。


140
投票

其他人已回答“如何”和引用规范。这是真正的故事“为什么没有<script/>”,经过几个小时挖掘bug报告和邮件列表。


HTML 4

HTML 4基于SGML

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

然而,HTML没有redfine,所以<SCRIPT/> should mean <SCRIPT>>。 (是的,'>'应该是内容的一部分,标签仍未关闭。)

显然,这与XHTML不兼容,并将打破许多网站(当浏览器足够成熟时to care about this),所以nobody implemented shorttags和规范advises against them

实际上,所有“工作”自结束标签都是带有可选结束标签的标签,这些标签位于技术上不符合的解析器上,实际上是无效的。它是W3C,came up with this hack通过制作HTML-compatible来帮助过渡到XHTML。

<script>的结束标记是not optional

“自我结束”标签是HTML 4中的一个黑客,并且毫无意义。


HTML 5

HTML5有five types of tags,只有'void'和'foreign'标签是allowed to be self-closing

因为<script>不是空的(它可能有内容)并且不是外来的(如MathML或SVG),所以<script>不能自动关闭,无论你如何使用它。

但为什么?难道他们不能把它视为外国人,特殊情况或其他什么?

HTML 5旨在成为具有HTML 4和XHTML 1实现的backward-compatible。它不基于SGML或XML;它的语法主要涉及记录和统一实现。 (这就是为什么<br/> <hr/>等是valid HTML 5尽管HTML4无效。)

自闭式<script>是实现过去不同的标签之一。它used to work in Chrome, Safariand Opera;据我所知,它从未在Internet Explorer或Firefox中运行。

This was discussed当HTML 5被起草并被拒绝因为它breaks browser compatibility。自动关闭脚本标记的网页可能无法在旧浏览器中正确呈现(如果有的话)。有other proposals,但它们也无法解决兼容性问题。

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

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


XHTML 1 / XHTML 5

当真正充当XHTML时,<script/>真正关闭,正如other answers所说。

除了the spec says它应该在作为HTML服务时起作用:

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

所以发生了什么事?

人们asked Mozillalet Firefox parse符合文件XHTML,无论指定的内容标题(称为content sniffing)。这将允许自动关闭脚本和内容嗅探was necessary无论如何因为网络主机不够成熟,无法提供正确的标题; IE是good at it

如果first browser war没有以IE 6结尾,那么XHTML也可能在列表中。但它确实结束了。和IE 6 has a problem与XHTML。事实上,IE did not support正确的MIME类型at all,迫使每个人使用text/html for XHTML因为IE had major market share整整十年。

而且内容嗅探can be really bad和人们说it should be stopped

最后,事实证明,W3C didn't mean XHTML to be sniffable:文档是HTML和XHTML,以及Content-Type规则。可以说他们坚持“只要遵循我们的规范”和ignoring what was practicalcontinued在以后的XHTML版本中的错误。

无论如何,这个决定settled the matter为Firefox。这是在Chrome was born之前的7年;没有其他重要的浏览器。因此决定了。

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


44
投票

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

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


27
投票

上面的人已经解释了这个问题,但有一件事可能会清楚地表明,尽管人们在HTML文档中一直使用<br/>,但是这样一个位置上的任何/基本上都被忽略了,只有在尝试时才会使用制作可解析为XML和HTML的东西。例如,尝试<p/>foo</p>,你会得到一个常规段落。


22
投票

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

另一方面,HTML确实有一个很好的标签,用于包含对外部资源的引用:<link>标记,它可以自动关闭。它已经被用于包括样式表,RSS和Atom提要,规范URI以及各种其他好东西。为什么不用JavaScript?

如果你想让脚本标签自我封闭你不能像我说的那样做,但有一个替代方案,虽然不是一个聪明的方法。您可以使用自闭链接标记并通过为其提供一种text / javascript和rel作为脚本链接到您的JavaScript,如下所示:

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

20
投票

与XML和XHTML不同,HTML不了解自动关闭语法。将XHTML解释为HTML的浏览器不知道/字符表示标签应该是自动关闭的;相反,他们将其解释为空属性,解析器仍然认为标签是“开放的”。

就像<script defer>被视为<script defer="defer">一样,<script />被视为<script /="/">


18
投票

Internet Explorer 8及更早版本不支持XHTML,application/xhtml+xml的正确MIME类型。如果您将XHTML作为text/html提供,您必须为这些旧版本的Internet Explorer执行任何操作,它将被解释为HTML 4.01。您只能将短语法与允许省略结束标记的任何元素一起使用。见HTML 4.01 Specification

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

IE9和后来的support XHTML 5application/xhtml+xml一起服务。

© www.soinside.com 2019 - 2024. All rights reserved.