从 HTML 到 HTML(通过 HTML)
当你使用如 Thymeleaf 这样的软件时,了解 HTML 系列网络标准的内部机制是非常重要的。至少如果你想理解自己正在做什么的话。
问题是很多人了解他们用于创建网页的技术,但并不真正知道这些技术的来源。自从第一个网页接口诞生以来已经过了很长时间,而自那以后每一项新技术都在不断改变我们的网页开发方式,淘汰了大量我们的工作内容,尤其是我们的知识。
如今,随着 HTML5 的出现,事情变得更加复杂。它到底是什么? 为什么是 HTML 而不是 XHTML? 曾经人们不认为 HTML 的标签混合写法是有害的吗?
所以,让我们退一步,看看我们是如何走到今天这一步的,以及为什么会这样。
回到上世纪 90 年代,出现了 HTML...
...并且 HTML 是一个标准(或者更准确地说,是一个推荐标准),由万维网联盟(简称 W3C)维护。HTML 延伸自一种叫做 SGML 的语言,它定义了一种基于标签的标记语言,用来编写丰富的超文本文档,并且高度依赖于在网络上提供这些文档及其相关资源所使用的协议:超文本传输协议(HTTP)。
HTTP 使用文本来头部定义向客户端提供的内容及方式,其中有一个头特别重要:Content-Type
Content-Type 头部MIME(多用途互联网邮件扩展)。用于发送 HTML 文档的 MIME 类型是text/html
:
Content-Type: text/html
HTML 还定义了检查文档是否有效的方法。所谓有效基本上意味着文档是按照 HTML 规则编写的,这些规则规定了一个标签可以有哪些属性,这个标签可以在文档中的什么地方出现等等。
这些有效性规则是使用一种称为文档类型定义(DTD)的语言来定义的,该语言用于指定 SGML 文档的结构。每个版本的 HTML 都会创建一个标准 DTD,并且 HTML 文档必须通过出现在文件最开头的一个子句来声明它们符合哪一个 DTD(也就是哪个版本的 HTML),这就是文档类型声明或DOCTYPE
子句:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
文档对象模型与标签混杂
HTML 最初是为了在浏览器中显示文档设计的,在 90 年代末期,浏览器是由激烈竞争的公司开发的,这些公司希望为用户提供尽可能多的新奇功能。由于 HTML 仅定义了文档格式化的规则,许多其他功能都留给了浏览器开发者去想象。
在浏览器中出现的一个非常有趣的想法是客户端交互性。这种交互性是通过在浏览器内执行脚本——比如用 JavaScript 编写的脚本——实现的,并赋予这些脚本能处理、修改甚至触发文档中部分元素的事件的能力。为此,浏览器必须将 HTML 文档建模为内存中的对象树,每一个对象都有状态和事件,因此文档对象模型(DOM)诞生了。
问题在于 HTML 对良好格式的要求相当宽松,而 DOM 树则是严格层次结构的。这意味着对 HTML 标签位置和顺序的不同解释可能导致不同浏览器生成不同的 DOM 对象树。此外,这些不同的浏览器还以不同的方式来建模 DOM 节点的 API(命名、事件等),这就让你明白了当时要实现跨浏览器的交互性有多困难。
更糟的是,在这一切发生的同时,浏览器对 HTML 开发者变得越来越宽容,允许他们编写格式不良的 HTML 文档(标签混杂),并自动纠正他们的错误。这导致 HTML 开发者制作出更差格式的文档,而浏览器又允许越来越多的格式错误,从而形成了一个极具破坏性的循环。你猜怎么着:每款浏览器都是以不同的方式来纠正这些错误的。太棒了。
W3C 最终标准化了 DOM API 和一门用于在浏览器中进行脚本编程的语言:JavaScript(尽管由于一些复杂的原因,他们坚持称其为 ECMAScript)。但由于标签混杂的世界再加上浏览器厂商对这些标准的全面采纳速度缓慢(很多情况下担心影响向后兼容性),所产生的影响至今仍在影响我们构建 Web 应用的方式。
XML 出现了
在 HTML 成为一种广泛传播的语言之后一段时间,W3C 开发了一项新的规范,称为 XML(可扩展标记语言),目的是以分层标记文本的形式表示通用数据(不仅仅是网页)。
XML 是可扩展的,因为它允许定义特定用途的语言(标签及其属性),以满足特定场景的需求。但从 XML 的角度来看,HTML 文档并不是良好格式的,事实上,XML 和 HTML 仍然是互不兼容的语言。无法将 HTML 表达为一种 XML应用程序.
XML 文档严格采用层级结构并消除了 HTML 的结构歧义,这使得它能够更直接地转换为标准化的 DOM 树(这个过程被称为XML 解析)。另外,由于 XML 是一种基于文本的语言,而文本是一种与技术无关的格式(与二进制相对),因此 XML 特别适合用于在互联网上跨平台交换数据。事实上,这也催生了如今无处不在的Web Services(网络服务)技术。
HTML + XML = XHTML
在某一阶段,受到 XML 明显实用性以及其可以让网页文档更具扩展性和互操作性(比如,在浏览器中生成可预测的 DOM)的推动下,W3C 决定将 HTML 重新定义为一种 XML 方言(或应用程序),而不是一种 SGML 方言,于是 XHTML 诞生了。
XHTML 要求网页作者以格式良好的 XML 来编写文档,这引入了一些以前 HTML 中没有的格式规则:标签必须始终关闭,属性必须始终进行转义并用引号包围等。
将 XHTML 引入网页文档,并将其转化为格式良好的 XML,普遍被认为是向前迈进的一大步,因为它可以实现浏览器之间更高程度的标准化,减少因作者错误而需要特定于浏览器来修正的空间,并使网页更容易被解析和自动处理。
作为其中的一部分,XHTML 引入了一个直接来自 XML 的、颇具争议的概念,即严厉错误处理(Draconian Error Handling),这意味着任何 XML 解释器——现在也包括浏览器——只要在处理 XML 文档时发现任何形式错误,都应该立即失败。实际上,这意味着 XHTML 的作者必须创建完全格式正确的文档,否则就必须接受这样一个事实:浏览器根本无法(实际上是不被允许)显示它们。
在验证方面,XHTML 1.0 规范定义了一组可以在DOCTYPE
声明子句中使用的 DTD:XHTML 1.0 Strict
, XHTML 1.0 Transitional
和XHTML 1.0 Frameset
第一个用于纯粹的XHTML 文档,即不使用任何 HTML 中废弃的标签;第二个用于仍使用废弃标签和属性的过渡型文档;第三个则用于框架页。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
但 XHTML 最重要的特性之一是它还引入了一个新的 MIME 类型,这是每个网页服务器用来发送 XHTML 的类型,从而使浏览器知道它们必须使用 XHTML 解析器和引擎,而不是它们的 HTML 对应组件。这就是application/xhtml+xml
:
Content-Type: application/xhtml+xml
回归(XHTML 的)现实
就在 XHTML 推出之后,一切看起来都很光明。我们开发者只需要等待浏览器全面实现它,网页开发的世界就会突然变得美好得多……
问题是,这一切从未发生。
实际情况是,某一款特定的浏览器拒绝支持application/xhtml+xml
内容类型。你猜是哪一款?没错,就是那一款:Internet Explorer(IE)。
IE 11 之前的版本在尝试访问使用 XHTML 自有内容类型发送的文档时会弹出下载对话框,这显然意味着如果你希望你的网站能展示给 IE 用户看,你就无法使用该内容类型。等到这个问题最终被解决时,已经太晚了。
幸运地——或者可以说是不幸地——XHTML 1.0 规范包含一个附录,指出 XHTML 1.0 内容也可以使用 HTML 时代的旧text/html
内容类型来发送,以便于过渡。而这就是过去几年里大多数人的做法:创建 XHTML 1.0 内容,然后以text/html
HTML 形式提供。过渡持续了很长时间。
但事实是,当你以 HTML 而不是 XHTML 格式提供内容时,浏览器将使用其 HTML 引擎而非 XHTML 引擎来渲染内容。尽管这些 HTML 引擎具备处理 XHTML 的能力,但它们仍需向后兼容旧的 HTML 4 代码——这使得它们成为非常复杂的软件组件,更重要的是,它们缺少 XHTML 中某些最典型的 XML 特性,首先是……严厉错误处理。
如果你没有严厉错误处理机制,那么浏览器就会变得宽容,允许你发送格式不良的文档,并自动帮你纠正错误。如果你知道浏览器会(按自己方式)纠正你的错误,那你可能永远不会去修正自己的文档……于是 HTML 的噩梦仍在继续。
了解这一点后,请想想你可能从未真正创建过一个真正的 XHTML 网站。你所做的不过是使用(可能格式错误)的 XHTML 文档,但却作为传统的 HTML 提供并显示出来。对此你怎么看?
但事情变得更糟,因为在 2002 年,XHTML 1.1
移除了使用 HTML 内容类型的可能,因此只能使用application/xhtml+xml
XHTML 内容类型。问题在于,这本应该迫使 Internet Explorer 支持application/xhtml+xml
XHTML 内容类型,但实际并没有实现。这一限制的结果只是让 XHTML 1.1 变得像尼斯湖水怪一样虚无缥缈。几乎没有人真正使用过它。
2009年,W3C再次允许使用text/html
XHTML 1.1,但又一次为时已晚。
走向HTML5:一个分道扬镳的故事
在某个时候(确切地说是2004年),一些浏览器制造商意识到现有的XHTML规范发展得太慢,无法应对网络日益增长的需求(视频、音频、更丰富的应用程序接口等),并且W3C正越来越多地推动他们创建对文档的更严格解释,这最终可能导致大量现有(格式不良的)代码变得无用。
他们希望增强Web应用的功能,例如视频、音频、本地存储或高级表单处理,实际上他们可以通过以特定浏览器的方式添加这些功能来做到这一点,但他们不想再次走上互操作性差的老路。他们需要标准能够演进并包含这些新功能。
然而,当时现有的标准(即XHTML)在演进方面存在一个问题:仍有大量的网站和应用程序仍然依赖遗留的HTML代码,如果这些酷炫的新功能通过走XHTML极端严格的路线被标准化,除非这些应用被完全重写,否则它们将永远无法使用这些新功能。每个人都想要一个更具互操作性和标准化的网络,但不是以抛弃数百万网页作者多年来的工作为代价。
因此,这些厂商(以及其他个人)向W3C提出了一个想法,即以一种使所有(或大部分)现有HTML和XHTML代码仍然有效的新HTML方式演进HTML,同时为Web应用提供强大的新功能,并且重要的是,明确地定义错误处理应如何进行。
后者意味着浏览器不会在遇到第一个错误时就停止运行,而是根据规范按照规范定义的方式了解如何自动修正网页作者造成的错误,因此会以完全相同的方式响应这些错误,从而使得HTML代码(无论是否符合XML格式)都可以跨浏览器运行。你仍然会被建议为新网站编写符合XML格式的代码,但如果你不愿意这样做,或者仍保留有大量旧的HTML代码(而且大多数情况下你确实有),你仍然可以加入这场变革。看到那边那个老HTML网站了吗?我们给它加点视频吧!这一切听起来相当合理。
但在2004年的时候,W3C并没有觉得这一切如此合理,他们拒绝了这个提议,并决定坚定地沿着XHTML方向前进。对他们来说,HTML已经死亡,没有理由复活它,而XHTML 2.0
才是未来的方向。
这导致了分裂。这一HTML新理念的支持者,包括来自Opera Software、Mozilla基金会和Apple的个人,退出了W3C并成立了Web超文本应用技术工作组(WHATWG)目的是定义我们现在所知的HTML5。
最终,在2007年,W3C成立了一个下一代HTML的工作组,后来该工作组接受与WHATWG合作,有效地采纳HTML5作为其工作规范和未来发布物。W3C和WHATWG现在联合致力于HTML5的开发,并于2009年,W3C直接终止了XHTML 2.0小组的工作,让它自然消亡。
HTML5现在成为仅仅是的网络标准未来。
那么,HTML5到底是什么?
HTML5是一组仍在持续开发中的标准——截至2011年仍在完善中,从当前的HTML 4和XHTML规范演进而来的目标包括:
- 添加先进的新功能到HTML中,这些功能有效地将Web开发从面向文档的理念稍微转向更面向应用的方向。这些功能被称为HTML5特性并且在某些情况下由独立于HTML5核心标准之外的标准定义。HTML5特性包括但不限于:视频、音频、绘图画布、地理位置、本地存储、离线支持以及高级表单相关功能。
- 提供一条轻松迁移至HTML5的道路,这样只需很少甚至无需重写任何代码即可采用HTML5。
- 提供一种标准化的代码错误处理方式,使得格式不良的HTML5代码将在所有浏览器中以可预测的方式运行。
从实际角度来看,这意味着(可能全部)你现在使用的HTML和XHTML代码只需更改你的DOCTYPE
(重复)至HTML5版本即可被视为有效的HTML5:
<!DOCTYPE html>
并使用内容类型text/html
:
Content-Type: text/html
来提供你的内容。DOCTYPE
为什么HTML5不指定任何DTD呢?因为根本不存在。HTML5没有DTD,因为定义文档是否为有效HTML5的规则是在规范本身中以人类可读文本的形式定义的,而无法用DTD语言表达出来。
但这并不意味着HTML5解析器和/或引擎不能进行验证。它可以。只是它必须是一个专门用于HTML5解析的软件组件,其中必须编写特定代码来执行涉及验证HTML5的相关规则(而不是从DTD文件中读取这些规则)。即使现在的规范已经相当灵活,它仍然是一个规范,你必须遵循它。
但如果不存在 DTD,那为什么还要有 DOCTYPE 子句呢?因为需要 DOCTYPE 子句才能让浏览器以标准模式(而不是怪异模式)显示文档。这个子句<!DOCTYPE html>
是最小有效的 DOCTYPE 声明,这已经完全满足我们的需求了。它只是充当了一个开关。
我现在可以使用 HTML5 吗?
大多数情况下是可以的。虽然(截至2016年)没有任何一款浏览器完全实现了整个 HTML5 的功能集,但大多数主流浏览器确实实现了其中很大部分的功能。因此,只要你的用户没有使用已淘汰的非常旧版本的 Internet Explorer,那么在大多场景下都没有问题。
另外,请注意浏览器的支持情况实际上会随着时间推移而变化,不仅是因为浏览器快速更新新版本的速度,还因为该规范本身仍在不断完善中。
关于 HTML5 特性以及对应浏览器支持情况的列表,请查看Can I use…网站。特别推荐查看 HTML5 所有特性的分类列表:http://caniuse.com/#cats=HTML5
那 XHTML5 呢?是否存在?
理论上是存在的。XHTML5 就是以如下方式提供的 HTML5:
Content-Type: application/xhtml+xml
但请注意 IE 直到第 11 版才支持这种方式(Microsoft Edge 支持)。所以再次考虑一下你的用户的浏览器能力吧。
同时请注意 HTML5 和 XHTML5 之间的区别仅在于内容类型和仅仅是内容类型,因为一份格式良好的 XML 式 HTML5 文档事实上就是一份完全合法的 HTML5 文档。这与 HTML4 与 XHTML 1.0/1.1 的关系大不相同,后者是互不兼容的语言。