有一段時(shí)間,在 web 上出現(xiàn)了有關(guān)標(biāo)記未來發(fā)展的競爭,即 W3C 的 XHTML 2 和 HTML5 之間的競爭,這是主要瀏覽器廠商在其各自組織下進(jìn)行的競爭。首先,W3C 接管了 HTML5,并且它最近宣布了 XHTML 2 的衰退。這就使 web 上的 XML 的未來產(chǎn)生了巨大差異,此外, HTML5 現(xiàn)已成為每個(gè) XML 開發(fā)人員都會(huì)使用的一種技術(shù)。
但是,XML 愛好者不必失望:HTML5 支持恰當(dāng)?shù)?XML 序列化。了解 XML 形式的 HTML5 包括與舊式 XHTML 規(guī)則的一些主要差別,以及如何在現(xiàn)代 web 瀏覽器中實(shí)際應(yīng)用此詞匯。
HTML 的歷史一直存有爭議。即使是 web 架構(gòu)師盡了最大努力,網(wǎng)頁始終是一個(gè)難以駕馭的領(lǐng)域,它具有混亂的、令人費(fèi)解的,甚至是有時(shí)非常惱人的破碎標(biāo)記(別名為標(biāo)簽雜燴)。 XML 的一個(gè)目標(biāo)始終是幫助解決這種混亂問題,因此 XML 被定義為 “web 的 SGML”(SGML 是一種原語言,而 HTML 只是其中的一種)。XML 一問世就立刻引起了軒然大波。W3C 期望 XML 在瀏覽器中獲得成功,并將 XHTML 作為比 HTML 更連貫的最自然的發(fā)展。不幸的是,總是出現(xiàn)意想不到的問題破壞這一目標(biāo)。看似簡單的概念(比如命名空間和鏈接)成為技術(shù)政治的夢魘。由此產(chǎn)生的爭議和延遲已足以使瀏覽器開發(fā)人員確信,XML 可幫助解決現(xiàn)有問題,但是它又提出了更多新的、未知的問題。
即使沒有越來越多的證據(jù)表明 XML 并非靈丹妙藥,對于使用標(biāo)記雜燴的大量舊式網(wǎng)頁來說,當(dāng)瀏覽器開發(fā)人員試圖遷移到嚴(yán)格的基于 XML 的路徑時(shí),總是會(huì)遇到問題。此外,請考慮 Postel's Law(Postel 法則),這一法則根據(jù)著名的計(jì)算機(jī)科學(xué)家 John Postel 命名。該法則規(guī)定:
像保守派那樣去做,像自由派那樣去接受其他的。
XML 的限制與此法則在服務(wù)器或數(shù)據(jù)庫端是一致的,管理人員在策略方面是保守的。這也是 XML 茁壯成長的原因。web 瀏覽器可能是從其他人那里接收信息的最終示例,所以這也是 XML 和 Postel 法則最關(guān)注的地方。
XHTML 的發(fā)展
在過去幾年里形勢已非常嚴(yán)峻。瀏覽器廠商在很大程度上一直忽略了 W3C,并且成立了一個(gè) Web 超文本應(yīng)用技術(shù)工作組(Web Hypertext Application Technology Working Group,WHAT WG)發(fā)展 HTML,創(chuàng)建了 HTML5。但是對 W3C XHTML 的支持卻停滯了。通過提供場所來繼續(xù) HTML5 工作,W3C 第一次認(rèn)清了現(xiàn)實(shí),并且它在 2009 年停止了 XHTML 工作,接受了失敗這一事實(shí)。沒有一種方法來衡量這是否是 XHTML 在實(shí)踐中的結(jié)束。當(dāng)然 HTML5 并非是有意設(shè)計(jì)為 XML 友好的,但它至少以 HTML 的 XML 序列化形式(在本文中是 XHTML5)提供了口惠。然而,事情還遠(yuǎn)沒有解決,正如 HTML5 FAQ 中的一個(gè)問題所述:
如果我在 HTML 文檔中小心地使用語法,是否可以使用 XML 解析器處理它?不可以。HTML 和 XML 有著顯著的差別,尤其是在解析需求方面,并且您無法使用針對一方設(shè)計(jì)的工具去處理另一方的問題。但是,由于 HTML5 是根據(jù) DOM 定義的,所以在大多數(shù)情況下,可使用 HTML 或 XHTML 序列化來表示同一文檔。但是,稍后將介紹一些差異,這些差異使 XHTML 無法準(zhǔn)確表示一些 HTML 文檔,反之亦然。
對于對 web 上的 XML 的未來感興趣的任何開發(fā)人員來說,這種情況會(huì)讓他們感到非常困惑。本文將提供一個(gè)實(shí)用指南,闡述在 HTML 5 中使用 XML 的情況。本文是為那些被我稱為終極網(wǎng)絡(luò)黑客 的人而編寫的,他們不是 W3C 標(biāo)準(zhǔn)大師,但要么對在 web 上生成 XHTML 5 感興趣,要么對以簡單的方式使用它感興趣(也就是使用信息而不是擔(dān)心龐大復(fù)雜的呈現(xiàn))。我承認(rèn),做出其中一些建議對我來說是痛苦的,因?yàn)檎_處理 XML 已有一個(gè)長期主張。記住,HTML5 仍然是 W3C 的工作草案,在它成為一個(gè)完整的建議之前可能還需要一段時(shí)間。盡管其中一些特性很穩(wěn)定且能在 web 上很好地實(shí)現(xiàn)。
將文檔作為 XHTML5 提供
不幸的是,我有更多的壞消息。您可能無法像官方定義的那樣使用 XHTML5。這是因?yàn)橐恍┓ㄒ?guī)規(guī)定:為了將文檔轉(zhuǎn)換為 XHTML5,它必須使用 application/xhtml+xml 或 application/xml MIME 類型提供。但是如果您這樣做,所有發(fā)行的 Microsoft? Internet Explorer? 版本都將無法顯示它(但使用其他主流的現(xiàn)代瀏覽器則沒有問題)。惟一實(shí)用的解決方法是使用 text/html MIME 類型提供語法 XHTML5。從技術(shù)上講,這可能違反了一些版本的 HTML5 規(guī)范,但是除非您可以不支持 Internet Explorer,否則就沒有更多的選擇。說到增加混亂,這在相關(guān)的工作組中是一個(gè)非常有爭議的話題,并且至少這種語言已緩和了一些草案。 Internet Explorer 9 測試版(也稱為 “平臺預(yù)覽”)完全支持使用 XML MIME 類型提供的 XHTML,所以一旦用戶可普遍使用此版本時(shí),此問題就不存在了。同時(shí),如果您需要支持 Internet Explorer 6 或更早的版本,則本文中介紹的解決方法就不夠用了。您就只能使用 HTML 4.x 了。
對終極 web 黑客的建議:使用 text/html MIME 類型提供語法 XHTML5。
DOCTYPE 的樂趣
從終極 web 黑客的角度來說,一個(gè)好消息是,XHTML5 使文檔類型聲明(DTDecl)問題變得更少。XHTML 1.x 和 2 需要臭名昭著的構(gòu)造,比如 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">。這樣做的最大問題是新型的處理器很可能加載此 DTD URL,而這可能是一種不必要的網(wǎng)絡(luò)操作。此外,一個(gè) URL 包括許多其他 URL,并且您通常不需要從 W3C 站點(diǎn)下載多個(gè)文件。有時(shí) W3C 上放置的文件甚至?xí)幸恍﹩栴},這會(huì)導(dǎo)致一些很難調(diào)試的問題。
在 XHTML5 中,文件的 XML 性質(zhì)完全由 MIME 類型決定,并且實(shí)際上任何 DTDecl 都會(huì)被忽略,所以您可以忽略它。但是 HTML5 提供了最小化的 DTDecl <!DOCTYPE html>。如果您使用此 DTDecl,那么幾乎所有瀏覽器都會(huì)切換到 “標(biāo)準(zhǔn)” 模式,即使是完整的 HTML5,這通常更一致且更可預(yù)測。注意,HTML5 DTDecl 不會(huì)引用任何單個(gè)文件,所以可避免早期的一些 XHTML 問題。
對終極 web 黑客的建議:在 XHTML5 中使用 HTML 最小化的文檔類型聲明 <!DOCTYPE html> 。
由于您不使用任何外部 DTD 組件,因此您無法使用常見的 HTML 實(shí)體,比如 或 ©。這些都是在那些您未聲明的 XHTML DTD 中定義的。如果您想使用它們,XML 處理器將失敗并出現(xiàn)一個(gè) undefined entity 錯(cuò)誤。惟一安全的命名字符實(shí)體是:<、>、&、" 和 '。使用數(shù)值等效代替。例如,使用   而不是 ;使用 © 而不是 ©。
對終極 web 黑客的建議:不要使用任何命名字符實(shí)體,以下實(shí)體除外:<、>、&、" 和 '
從技術(shù)上講,如果您將文檔作為 text/html 提供,根據(jù)第一個(gè)建議,使用 HTML 命名字符實(shí)體,在大多數(shù)瀏覽器上都不會(huì)出錯(cuò),但是依靠這一意外是非常脆弱的。此外,記住,瀏覽器并不是 XML 的惟一使用者。其他 XML 處理器被此類文檔弄得不知如何是好。
命名空間的樂趣
認(rèn)識 XML 格式的復(fù)雜機(jī)制的最后一層是命名空間,前兩個(gè)是 MIME 類型和 DTDecl。可能您過去經(jīng)常使用類似下列行的內(nèi)容開始 XHTML 文檔。
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" >
黑體部分(xmlns="http://www.w3.org/1999/xhtml")是命名空間。在 XHTML5 中,此命名空間仍然是必需的。如果您包含了其他 XML 詞匯,比如可縮放的向量圖形(Scalable Vector Graphics,SVG),則將他們放置在其各自的必需命名空間中。
對終極 web 黑客的建議:在 XHTML5 文檔的頂部始終包含默認(rèn)的命名空間,并為其他嵌入的 XML 格式使用相應(yīng)的命名空間。
如果您包含了其他詞匯,則他們的命名空間聲明必須在嵌入部分最外面的開始標(biāo)記中。如果您在 html 元素中聲明了它們,則會(huì)遇到一個(gè) text/html 文檔一致性錯(cuò)誤。
處理 XHTML5 內(nèi)容
XHTML5 支持您使用以下方式指定介質(zhì)類型:用協(xié)議頭,比如 HTTP Content-Type 頭;使用名為 “字節(jié)順序標(biāo)記 (BOM)” 的特殊字符標(biāo)記,或者是使用 XML 聲明。只要不互相沖突,您可以隨意組合使用這些方法,但避免問題的最好方式是在選擇組合方法時(shí)要謹(jǐn)慎。不幸的是,使用 XML 聲明存在潛在問題,因?yàn)樗鼤?huì)使 Internet Explorer 8 及更早版本都切換到怪異模式,這會(huì)導(dǎo)致臭名昭著的顯示異常,也正是因?yàn)檫@種情況才使瀏覽器聞名于世。
對終極 web 黑客的建議:對 XHTML5 文檔僅使用 Unicode 編碼。在文檔的開頭部分,省略 XML 聲明,并使用 UTF-8 編碼,或者使用 UTF-16 Unicode 字節(jié)順序標(biāo)記(Byte Order Mark,BOM)。如果可以,可在提供文檔時(shí)使用 Content-Type HTTP 頭。
下面是此類 HTTP 頭的一個(gè)示例:
Content-Type: "text/html; charset=UTF-8"
新的語義標(biāo)記元素
HTML5 引入了一些新元素,提供語義更明確的內(nèi)容結(jié)構(gòu),比如 section 和 article。這些元素是 HTML5 的一部分,可能會(huì)發(fā)生變化,但是變化不會(huì)太大,并且這些新元素提供的改進(jìn)表達(dá)式也降低了風(fēng)險(xiǎn)。一個(gè)問題是 Internet Explorer 不是在 DOM 中構(gòu)造這些元素,所以如果使用 JavaScript,您就需要采用另一個(gè)解決方法。Remy Sharp 通過在文檔頭包含下列代碼段來維護(hù) JavaScript 修復(fù)。
<!--[if IE]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
您還可能需要定義元素的 CSS 規(guī)則,以免任何瀏覽器以 HTML 4 形式顯示文檔,HTML 4 形式以內(nèi)聯(lián)呈現(xiàn)方式顯示未知元素。下列 CSS 應(yīng)該有效。
header, footer, nav, section, article, figure, aside {
display:block;
}
對終極 web 黑客的建議: 使用新 HTML5 元素,但是請包含 HTML5 shiv JavaScript 和默認(rèn) CSS 規(guī)則以支持它們。
將它們組合起來
我已經(jīng)給出了許多單獨(dú)的建議,我將把它們組合起來形成一個(gè)完整的示例。清單 1 是滿足這些建議的 XHTML5。通過 HTTP 提供它時(shí),除非您可以不支持 Internet Explorer,否則請使用頭 Content-Type: "text/html; charset=UTF-8";當(dāng)不支持 Internet Explorer 時(shí),請使用頭 Content-Type: "application/xhtml+xml; charset=UTF-8"。
清單 1. 完整的 XHTML5 示例
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>A micro blog, in XHTML5</title>
<style>
<!-- Provide a fall-back for browsers that don't understand the new elements -->
header, footer, nav, section, article, figure, aside {
display:block;
} </style>
<script type="application/javascript">
<!-- Hack support for the new elements in JavaScript under Internet Explorer -->
<!--[if IE]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
</script>
<script type="application/javascript">
<!-- ... Other JavaScript goes here ... -->
</script>
</head>
<body>
<header>A micro blog</header>
<article>
<section>
<p>
There is something important I want to say:
</p>
<blockquote>
A stitch in time saves nine.
</blockquote>
</section>
<section><p>By the way, are you as excited about the World Cup as I am?</p>
</section>
</article>
<article>
<section>
<p>
Welcome to my new XHTML5 weblog <img src="/images/logo.png"/>
</p>
</section>
</article>
<aside>
<header>Archives</header>
<ul>
<li><a href="/2010/04">April 2010</a></li>
<li><a href="/2010/05">May 2010</a></li>
<li><a href="/2010/06">June 2010</a></li>
</ul>
</aside>
<footer>© 2010 by Uche Ogbuji</footer>
<nav>
<ul>
<li><a href="/">Home</a></li>
<li><a href="/about">About</a></li>
<li><a href="/2010/06">Home</a></li>
</ul>
</nav>
</body>
</html>
清單 1 使用 HTML5 DTDecl,并在頂部聲明默認(rèn)命名空間。本例中的 style 和 script 元素僅提供實(shí)際瀏覽器問題的解決方法。只有在使用其他 JavaScript 時(shí)才需要 script 元素。該文檔使用了大量新 HTML5 元素,我不會(huì)詳細(xì)介紹這些元素,因?yàn)樗鼈儾皇?XML 特有的。注意,img 元素使用的是 “自閉合” 語法(換句話說,它以 /> 結(jié)束),版權(quán)符號使用的是數(shù)值實(shí)體形式 ©。
可參閱 表 1 了解上述示例在不同瀏覽器中的行為概述。
表 1. 滿足本文建議的 XHTML5 的瀏覽器支持
瀏覽器 行為
舊版瀏覽器(例如,Internet Explorer 6.x 或更早版本、 Netscape、Firefox 1.x) 呈現(xiàn)將是不可預(yù)測的。例如,“自閉合” 元素的結(jié)束標(biāo)記可能是錯(cuò)誤的。如果您使用 HTML 命名實(shí)體則不會(huì)出現(xiàn)任何錯(cuò)誤。
Internet Explorer 7 或 8 由于使用的是 text/html MIME 類型,因此呈現(xiàn)將是常規(guī)的 “標(biāo)記雜燴”,但是任何 DTDecl 都將觸發(fā) “標(biāo)準(zhǔn)模式”,比如 Internet Explorer 提供它。HTML 命名實(shí)體不會(huì)出現(xiàn)任何錯(cuò)誤報(bào)告。
現(xiàn)代的、支持 HTML5 的瀏覽器,比如 Firefox 3.x、Safari 4 或最新的 Opera 或 Google Chrome 由于使用的是 MIME 類型,因此呈現(xiàn)將是 HTML5(而不是 XHTML5),但是會(huì)是在 “標(biāo)準(zhǔn)模式” 下。HTML 命名實(shí)體不會(huì)出現(xiàn)任何錯(cuò)誤報(bào)告。
任何標(biāo)準(zhǔn)的 XML 1.x 處理器 將不會(huì)考慮 MIME 類型。解析器將會(huì)在 XHTML 命名空間看到所有元素。如果使用任何假的 HTML 命名實(shí)體,都會(huì)收到錯(cuò)誤信息。
結(jié)束語
最近的一個(gè)重要情況是 W3C HTML 工作組發(fā)布了第一份公共工作草案 "Polyglot Markup: HTML-Compatible XHTML Documents",目的是提供有關(guān) XHTML5 的更全面、準(zhǔn)確和最新的消息。
此外,對我來說,做出本文中的一些建議來說很痛苦。這些解決方法來自長期的痛苦體驗(yàn),并且在將 XML 混合進(jìn)現(xiàn)實(shí) HTML 世界時(shí),這是避免難以重現(xiàn)的 bug 和奇怪的不兼容性的惟一方法。這當(dāng)然不是說我已經(jīng)停止了提倡仔細(xì)的 XML 設(shè)計(jì)和最佳實(shí)踐。最好將連接瀏覽器的最外面的組件保存為 XHTML5。所有類型的 XHTML 都能更好地呈現(xiàn)語言而不是攜帶信息的語言。您應(yīng)該以其他 XML 格式傳輸大多數(shù)系統(tǒng)的主要信息。然后在最后將其轉(zhuǎn)換為 XHTML5。您可能會(huì)好奇在最后時(shí)刻創(chuàng)建 XHTML5 的意義,但是請記住 Postel 法則,它建議嚴(yán)格執(zhí)行生成的內(nèi)容。通過為瀏覽器生成 XHTML5,其他人會(huì)很容易從您的網(wǎng)站和應(yīng)用程序中提取信息。在這個(gè)混搭、web API 和數(shù)據(jù)項(xiàng)目時(shí)代,這是一個(gè)重要特性。