W3C最近宣布将于今年年底解散XTHML2工作组。一石激起千层浪,很多误解和谣言四起,江湖一片血雨腥风,搞得网页设计师人人自危,好像世界末日即将到来。其实,这只是个误解,看完下面的这幅漫画,大家就了解了。完全可以放心,然后回家洗洗睡了。
非原创,来源网络:英文版源文地址:漫画英文版源文地址,这里是英文原版漫画
感谢我的同事Kevin Jaw的翻译。他的博客地址是:Kevin Jaw的博客
W3C最近宣布将于今年年底解散XTHML2工作组。一石激起千层浪,很多误解和谣言四起,江湖一片血雨腥风,搞得网页设计师人人自危,好像世界末日即将到来。其实,这只是个误解,看完下面的这幅漫画,大家就了解了。完全可以放心,然后回家洗洗睡了。
非原创,来源网络:英文版源文地址:漫画英文版源文地址,这里是英文原版漫画
感谢我的同事Kevin Jaw的翻译。他的博客地址是:Kevin Jaw的博客
根据RFC标准所产生的IETF,Xhtml网页文件格式兼容可作为任何以下三个MIME类型:
text/xml
application/xml
application/xhtml+xml
然而,虽然所有这三个MIME类型在技术上是正确的,使用text/xml or application/xml可能会产生意想不到的,不一致,不受欢迎的结果。因此,application/xhtml+xml是XHTML文件建议 的MIME类型。这些文件必须遵守的XML格式规范。一般而言,格式良好的XML包括:
*正确嵌套元素
*适当关闭部分
*适当引用属性
*标记性状的小写
当交付application/xhtml+xml良构的XHTML文件任何用户代理是正确处理的。不幸的是,虽然大多数的浏览器了解 application/xhtml+xml MIME type,而Internet Explorer不是显示这些文件的内容,IE浏览器显示空白页,并下载提示。为了防止这种现象,许多开发商和设计师发送他们的XHTML文件使用不正确 的MIME类型:text/html.
当送达此MIME类型的XHTML文件当做HTML处理。这可能会绕过IE的的MIME不足,甚至便利不符合规定的标记。,但它在技术上是不正确的,将引起警告后试图验证。此外, W3C的指导方针提出意见对MIME类型为text/html的XHTML 1.1。
新闻来源:W3C
W3C 近日发布两项标准,XHTML Basic 1.1 及移动 Web 最佳实践 1.0。这两项标准均针对移动 Web,其中,XHTML Basic 1.1 是 W3C 建议的移动 Web 置标语言。W3C 从移动 Web 最佳实践中总结了 10 条最基本的规则:
XHTML Basic 1.1
移动置表语言有众多分支,XHTML Basic 1.1 的发布,为移动置标语言提供了一个标准, XHTML Basic 1.1 包含以下新功能:
你可以到 mobileOK checker 对你的移动 Web 进行验证,以测试其是否对移动设备友好。
转自http://www.junchenwu.com/2006/01/buttoninput.html
一句话概括主题:<button>
具有<input type="button" ... >
相同的作用但是在可操控性方面更加强大。
HTML 4.01规范的Forms部分指名表单有以下几种控制类型:buttons, checkboxes, radio buttons, menus, text input, file select, hidden controls, object controls. 其中除了buttons/menus/object controls之外,都是由<input>
完成。
我这里说的是<button>
和<input>
。
<button>
和<input>
规范中指名:可以用<button>
和<input>
来做表单按扭。不同的按钮类型请参考这些元素的详细定义。要注意的是<button>
比<input>
支持更丰富的表现功能。
大家都知道<input>
可以这样用(实际上是一定要这样用):<input type="submit" value="OK" />
,一定要这样闭合。而不是:<input type="submit" value="OK" ></input>
。因为起始标签为必须,而关闭标签是禁止的。
<button>
比<input>
更厉害的地方就在于它可以包含内容。它的值并不是写在value
属性里,而是包含在标签中。如:<button>OK</button>
。<button>
的起始标签和关闭标签都是必须的。这样你便获得了样式化的主导权。
你可以这样写:<button><strong>OK</strong>, I do.</button>
,甚至是插入图片:<button><img src="button.gif" alt="" />, it's great.</button>
。有点类似于<input type="image">
,但是显然强大多了。
最后要注意的是,被<button>
包含的图片,不能使用热点地图,即不能<img src="foo.gif" usemap="..." />
,这是不合法的。当然也不能再包含诸如input
, select
, textarea
, label
, button
, form
, fieldset
, iframe
,和isindex
(不推荐使用)元素了。
下面是一份在 HTML 4 Strict 和 XHTML 1.0 Strict 下必须遵守的标签嵌套规则,比如你不能在 <a>
里面再嵌入一个 <a>
这样的约定。
说明:
<html>
而不应是 <HTML>
)ä
和 ä
)注1. 以上内容基于 [HTML 4.01 Specification] 的 Strict DTD。JunChen 翻译自 Allowed nesting of elements in HTML 4 Strict (and XHTML 1.0 Strict)
注2. 对于 XHTML 1.0,基本上一致,不同点如下:
<script>
和 <style>
的内容,在 HTML 4 里是 CDATA
而在 XHTML 里是 #PCDATA
<table>
标签后可以紧跟一个 <tr>
,而在 HTML 4.01 里,不允许这样,不过 <tbody>
标签又是可以省略的。意思就是说,如果代码中的 <table>
后紧跟 <tr>
,对于 HTML 4.01,会隐性的生成一个 <tbody>
标签,而在 XHTML 里面就没有。这会影响到样式表使用 tbody
作为选择器。推广Web Standards的人经常说XHTML
比HTML
更加严格,当然从某种意义上说是的,比如它要求所有的标签关闭并且所有的属性都用引号。但其实XHTML 1.0
还分两种(加上Frameset DOCTYPE的话算三种,本文不讨论),Transitional(过渡型)和Strict(严格)DOCTYPEs。并且HTML 4.01
也有同样的文档声明。
从字面上就可以看出来意思:Transitional DOCTYPEs只是为了实现从旧时代到新时代的过渡,而且Strict DOCTYPEs是默认的文档声明, 对构造HTML 4.01
和XHTML 1.0
都适用。
使用Transitional DOCTYPE
一般是由于代码中含有过多陈旧的写法,并且一下子很难完全转换到Strict DOCTYPE
来。但是Strict DOCTYPE
才应该是你的目标。它鼓励甚至有时是强迫你把结构与表现区分开来,把表现层的代码都写在CSS里。HTML 4 Document Type Definition: –
本HTML 4.01 Strict DTD不包括表现层属性和标签,W3C将逐渐淘汰这些属性和标签,您完全可以使用样式表来实现。您应该使用Strict DTD,如需获得表现层属性和标签的支持,请使用Transitional DTD。
用Strict DOCTYPE
还有一个好处,即可以让浏览器使用它们最严格、(一定程度上)最符合标准的模式来渲染页面。
Tommy Olsson在Web Standards Group的Ten questions for Tommy Olsson一文中很好的阐述了使用Strict的好处:
我觉得,使用Strict DTD,无论是
HTML 4.01 Strict
还是XHTML 1.0 Strict
,远比讨论是用HTML
还是XHTML
重要的多。它代表了未来互联网的质量。它将结构和表现分开,使得维护一个站点非常容易。
对于刚开始接触web standards和正确的、语义化的结构的人,认清Transitional和Strict DOCTYPEs的区别非常重要。更多详细列表请参考:XHTML: Differences between Strict & Transitional、Comparison of Strict and Transitional XHTML和XHTML1.0 Element Attributes by DTD。
对于准备向Strict进发的人来说,两者的有些区别很可能会使开发者犯错误,接下来我将会谈到。
Strict DOCTYPEs
下不支持的标签center
font
iframe
srike
u
Strict DOCTYPEs
下不支持的属性align
(表格相关的支持:col
, colgroup
, tbody
, td
, tfoot
, th
, thead
, and tr
)language
background
bgcolor
border
(table
支持)height
(img
和object
支持)hspace
name
(在HTML 4.01 Strict中支持,XHTML 1.0 Strict中的form
和img
不支持)noshade
nowrap
target
text
, link
, vlink
, 和alink
vspace
width
(img
, object
, table
, col
, 和 colgroup
都支持)元素类型的内容模型描述了什么样的元素类型实例可以被包含。这一点上,两种文档声明的最大区别在于blockquote, body, 和form元素仅能够包含块级元素,如:
body
中,必须被p
或者div
等块级元素包含input
元素不能直接是form
元素的下一层blockquote
元素内的文本,必须被p
或者div
等块级元素包含在向Strict DOCTYPEs
过渡的过程中,了解每个元素是做什么的比知道每个元素长啥样有效的多。
首先考虑结构和语义,然后再担心表现。
原文:http://www.456bereastreet.com/archive/200501/the_perils_of_using_xhtml_properly/
翻译:Neo (http://www.omemo.net/neo)
修正:JunChen
JunChen注:omemo.net网站似乎已经挂掉,链接都失效了。文章写得非常不错,一直是Best of 456 Berea Street。在这里发布的时候我进行了少量代码上和翻译上的修改,以忠实原著。
我使用XHTML有些年了,但直至去年夏天我才着眼于如何正确使用,那就是说,以application/xhtml+xml
的MIME类型来伺服(server)它。虽然我遇到了这些问题,但我知道问题远非如此。就如你即将发现的一样,当你开始使用真正的XHTML,你会遭遇很多似乎细小但让人困惑的问题。
请注意这不是一篇讨论支持或反对使用XHTML的文章。我只是写下我所知道的潜在的易犯错误,并且让你自己来决定自己的选择:HTML 4.01,为所有浏览器伺服为text/html
的XHTML 1.0或者为能够处理其的浏览器伺服为application/xhtml+xml
而其他浏览器则伺服为text/html
的XHTML 1.0。否则有些东西会完全不一样。
只有在问题发生的时候,我才有机会去了解和认识这些东西。有些情况下我必须花很多时间来查找问题和求助于其他人,来寻求一个解决方案。但我在其中学到不少东西,我会把我已经使用XHTML后应该知道的都告诉你。
注意我这里提及的问题只会发生在能正确处理application/xhtml+xml
MIME类型的用户代理中,而因此XHTML被作为XML。这也可能是这里不提及XHTML的早期使用的原因——很少有人使用这样的浏览器,所以几乎不会有人因只伺服为text/html
的XHTML所烦忧。
今天,实际上把XHTML伺服为application/xhtml+xml
正慢慢变得平常。我所知道的理由有两个:
text/html
的时候。如果你参与了任何一次讨论,你知道我在说什么。假如你,像我,决定实现某些类型的content negotiation和在传送XHTML的时候使用正确的媒体类型,你需要知道什么能(和将)在你发布的文档中发生,并且知道怎样避免问题的发生。对于对content negotiation同进行content negotiation的脚本例子有兴趣的读者,我推荐你阅读Content Negotiation和Serving up XHTML with the correct MIME type。还有很多这种类型的文章,但这是我读到的最精彩的两篇。
每一个基本的教程都有一些HTML和XHTML的明显区别:元素和属性名字使用小写,属性值总要用引号。不要使用简化属性,确保所有的元素都有结束标签和没有不正确的嵌套等等。但是,当XHTML伺服为application/xhtml+xml
时还需要知道更多东西。
良好的结构是必须的
文档必须是良好的结构(well-formed)的XML(跟合法的(valid)XHTML不必然相同)。就是必须,不是可能。
如果文档结构不好,符合标准的浏览器(当前我知道Mozilla,Firefox,Netscape,Camino,Opera,Safari和OmniWeb——相当多的浏览器除了IE)将会显示错误信息并且以某种方式中止处理文档。
此外,这还意味着不再使用未编码的”&”号。
XML声明可能是必须的
如果要使用UTF-8或者UTF-16以外的变法,必须要XML声明,除非HTTP头已经提供编码。
在HTTP头中是否要指定字符编码有些模糊,Architecture of the World Wide Web, Volume One: Media Types for XML这样写的:总体上,不应该在协议头为XML数据指定字符编码,因为数据本身已描述。
另一方面,XHTML 1.0, Second Edition: Character Encoding写到:
为了让文档使用指定的字符编码,最好的办法是保证web服务器发送正确的头。
就是说,在XML声明中指定字符编码是好的习惯:
<?xml version="1.0" encoding="iso-8859-1"?>
只有五个实体是安全的
只有五个预定义的实体(<
, >
, &
, "
, 和'
)的支持是有保证的。其他的可能完全被忽略或者直接输出。比如,如果XHTML文档包含如
或者”
的实体,Safari会直接地输出。Opera反而选择忽略未知的实体,同时Mozila家族会认得这些实体并且就像HTML中“如果文档引用公共的映射浏览器伪DTD目录中的标识符并且没有单独声明的文档”
来处理。
使用UTF-8字符编码是最受推荐的,让你(几乎)可以使用你需要键入文档的任意字符,不需要实体或者字符编号。如果你不能或不愿使用UTF-8,数字式的字符编号是可以支持和安全使用的。
SGML式注释的内容可能会被忽略
SGML注释(HTML风格注释, <!-- 注释 -->
)可能会(并且会)被浏览器当作注释,就算是在script
或者style
元素内部使用。
在HTML中,普遍地把script
和style
的内容装入注释中,为的是在不认识script
或style
元素的浏览器中隐藏他们,并且在页面上把其内容生成平白文本。
在XHTML中,这样做会引起浏览器忽略掉注释里的任何内容。
在老的浏览器中隐藏script
和style
的习惯可以追溯到1990年代中期。我的经验是,有如此表现的浏览器是十分罕见的,所以你可以安全地忽略它们,并且停止在脚本和样式中装入SGML式注释,就算你使用的是HTML。
脚本和样式元素的内容也被当作XML
样式和脚本元素是PCDATA(parsed character data,解析字符数据)块,不是CDATA(character data,字符数据)块。因此,在其内看起来像XML的任何东西都会被当作XML来解析,并且会引发错误除非是良构的。
为了在script
或style
块中使用<、&或者–,你需要用CDATA :
<script type="text/javascript">
<![CDATA[
...
]]>
</script>
在CDATA里,你可以任何顺序的字符,它们不会被当作XML来解析(除了结束CDATA部分]]>)。
需要以text/html
发送的文档中,CDATA部分的起始和结束标签需要注释掉,以便在不能处理CDATA部分的浏览器中隐藏:
<script type="text/javascript">
// <![CDATA[
...
// ]]>
</script>
<style type="text/css">
/* <![CDATA[ */
...
/* ]]> */
</style>
如果要确保很老的浏览器隐藏CDATA部分,需要使用更为复杂的方法,像在Ian Hickson的Sending XHTML as text/html Considered Harmful中描述的那样:
<script type="text/javascript">
<!--//--><![CDATA[//><!--
...
//--><!]]>
</script>
<style type="text/css">
<!--/*--><![CDATA[/*><!--*/
...
/*]]>*/-->
</style>
一个更好的办法可能是在发送text/html
的文档前使用content negotiation脚本来删除任何CDATA部分。
当然,最聪明和安全的途径是把所有的CSS和JavaScript都移动到外部文件中,但不总是现实的做法。
没有会自动补全的元素
在HTML中,假如表格的tbody
元素漏写的话浏览器会自动补全,而XHTML不会。如果你没有清楚地添加tbody,它就不会出现。在编写CSS选择器和JavaScript的时候请铭记在心。
用document.write编写的脚本不再工作
在XHTML中使用JavaScript,document.write
不会工作。Ian Hickson在Why document.write() doesn’t work in XML解释了原因。你需要使用document.createElementNS()
代替。关于更多可以在Experts Exchange中的论坛主题中找到。
这也是Google AdSense不在XHTML中工作的原因之一。那些希望以application/xhtml+xml伺服XHTML并且使用Google广告的人,这儿有一个解决办法:Simon Jessey的Making AdSense work with XHTML。尽管有点麻烦,但还是工作了(我在这里也使用了),同时被Google所认可。
引入样式元素
在XHTML中,为了兼容定义CSS规则的XML方法,你应该使用XML样式表声明(访问 XHTML 1.0, Second Edition: Referencing Style Elements when serving as XML的XML样式表声明和Associating Style Sheets with XML documents的xml-stylesheet处理说明)。要载入外部CSS文件,我们需要使用style
元素,同时应该使用XML样式表声明来引入样式元素。为此,使用id属性给style
元素一个分解的标识符,然后在XML样式表声明中引入该标识符:
lang=”en”>
我不知道在实际中究竟有多必要,并且不使用XML样式表声明的话会有什么问题。或许有人会指点我的。
CSS的应用规则有些不一样
CSS应用到body
的性质(property)并不应用到XHTML的整个文档。最值得注意的是应用背景颜色或者图片。在HTML中,应用到body
元素的背景将会覆盖整个页面。在XHTML中,你必须同时样式化html。在Juicy Studio的CSS body Element Test中有这个行为的演示。
在XHTML中作为CSS规则的元素和属性名字是大小写敏感的(而且必须是小写的)。避免问题最简单的办法是,不管在HTML,XHTML还是CSS中所有东西都保持小写。
有挑战,但不是不可能
当我开始为兼容的浏览器伺服XHTML为application/xhtml+xml
时,在作出决定前假如我能读到想这篇一样的文章,或许我的头痛可以减轻不少。我甚至考虑使用HTML 4.01 Strict
。虽然如此,我还是从经验中学到不少,而学习总是一个好东西。
正确地使用真正的XHTML,十分希望这篇文章能为你提供一些更有用的信息,并且可以为是否需要走这条路提供更多有根据的决定。
HTML和XHTML可能比我在这里提到的还有更多地不同,所以在这里把你在使用application/xhtml+xml
的XHTML时遇到的问题提出来,如果你知道任何的错误或者忽略,务必告诉我。
在你每一个页面的顶端,你需要文档声明。是的,必须。
如果不指定文档类型,你的HTML不是合法的HTML,并且大部分浏览器会用“怪癖模式 (quirks mode)”来处理页面,这意味着浏览器认为你自己也不知道究竟做什么,并且按浏览器自己的方式来处理你的代码。你可以是一个HTML大师,在地球上打遍 天下无敌手,或者你的HTML可以无瑕疵,CSS可以很完美,但如果没有文档声明,或者错误的文档声明,你的网页与一个短视的,独眼的长臂猿婴儿十分艰难 地堆砌起来的没两样。
XHTML 1.0 Strict(严格)的文档声明是这样的:
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Strict//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd“>
下面的是XHTML 1.1的文档声明,作为XHTML的最新版本,看起来更完美,但还是有一些问题,随后我们会稍微讲解……
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.1//EN” “http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd“>
如果你不愿放弃HTML 4或者你还有Netscape 4死忠用户,你可以使用XHTML 1.0 Transitional(过渡型):
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd“>
你使用这的唯一理由是你还要兼容老版本的,少用的浏览器。过渡型XHTML 1.0允许HTML 4的表现元素,其也可能在如Netscape 4的浏览器中表现更好。但使用这些元素将对你网页的效率和可用性有害。
最后,如果你是使用框架的怪人之一,可以使用像下面一样的XHTML 1.0 Frameset(框架)文档类型声明:
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Frameset//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd“>
注意DOCTYPE标签必须大写和前置一个英文半角感叹号!。它是唯一一个打破规则的标签,它不需要关闭。
语言声明
即使HTTP头或者在html起始标签内设置了xml:lang属性,你也必须为文档指定一个主 要语言。尽管处理一个合法的XHTML文档这不是必须的,但也是一个易用性的考虑。值是缩写的,比如en(English,英语),fr(French, 法语),de(German,德语)或者mg(Malagasy,这是什么语?译者也不知道,呵呵。——译者注)。
声明一个主要用英语内容的文档,例子是这样的:
<html xmlns=”http://www.w3.org/1999/xhtml” xml:lang=”en”>
在声明主要语言之后,假如还需要使用其他语言,你还可以在内联中使用xml:lang属性(比如<span xml:lang=”de”>HTML Hund</span>)。
内容类型
HTML文档的媒体类型和字体集也许要指定,可以使用HTTP头来完成,比如:
Content-Type: text/html; charset=UTF-8
HTTP头部的第一部分(如text/html)是文件MIME类型,让浏览器知道文件的媒体类型因此可以知道怎么处理。所有的文件都有MIME类型。JPEG图像是image/jpeg,CSS文件是text/csss和HTML一般使用text/html。
HTTP头部的第二部分(如UTF-8部分)是字符集。
也许设置HTTP头的最简易方法是在HTML中使用“HTTP同义(HTTP-equivalent)”的头标签,像这样:
<meta http-equiv=”Content-Type” content=”text/html; charset=UTF-8″ />
些微复杂当更好的方法是使用服务器端脚本语言来发送头。用PHP的话,你可以这样做:
<? header(“Content-Type: text/html; charset= UTF-8”); ?>
如果你不愿意(或不能)使用服务器端脚本语言,你也许可以直接给服务器设置一个 “.htaccess”文件。大部分服务器(Apache兼容)可以在根目录使用一个“.htaccess”的小文本文件,写入下面的内容,你就可以把所 有的“html”后缀文件都与MIME类型和字符集关联:
AddType text/html;charset=UTF-8 html
字符集包括大部分西方基于拉丁文语言的“ISO-8859-1”,日语的 “SHIFT_JIS”,中文的“GB18030”和UTF-8,一个 Unicode Transformation Format版本,提供大范围的多种语言的单个字符。基本上,你应该使用一个你知道的,能为你用户清楚认知的字符集。除非你使用基于拉丁语的语言(包括英 语)(ISO-8859-1被普遍接受的),你应该使用UTF-8因为它可以显示大多数语言的大多数字符,使用它也是安全的,因为它可以在大部的计算机上 使用。
注意
XHTML应该当作application/xhtml+xml的MIME类型来使用,再清楚不 过,这是XML程序。不幸的是,大部分浏览器没有对这没有第一线索。所以,一般认为使用text/html的MIME类型是不错的。根据W3C的建议和网 页标准工程的未来亮点,调味的XHTML 1.0也许可以作text/html使用,但XHTML 1.1不应该,这就是这个网站以XHTML 1.0 Strict(严格)作为例子,假定text/html的MIME类型。但是你仍然可以(或许不应该)为它们设置正确的MIME类型给浏览器,轻微的调用 一下服务器端即可。
这个网站使用PHP为XHTML 1.1设置application/xhtml+xml的MIME类型给那些能够理解和处理这个类型的浏览器(如Mozilla),为XHTML 1.0 Strict设置text/html给其他浏览器(如IE)。为每一个页面的顶部加入如下代码:
<? if(stristr($_SERVER[“HTTP_ACCEPT”],”application/xhtml+xml”)){ header(“Content-Type: application/xhtml+xml; charset=UTF-8”); echo(‘<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.1//EN” “http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd”>’); } else { header(“Content-Type: text/html; charset=UTF-8”); echo (‘<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Strict//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd”>’); } ?>
这些检查核实浏览器是否接受application/xhtml+xml的MIME类型,如果接 受,就发送这个MIME类型并把XHTML 1.1文类类型写到HTML中。如果这个MIME类型不被接受,就发送text/html的MIME类型并把XHTML 1.0 Strict(严格)的文档类型写入HTML。
除了你知道你正在做着正确的事情和为自己准备将来的路的平和想法外,最直接的益处就是,使用这个 方法,Mozilla浏览器把你的文件当作XML程序对待并且如果你的XHTML还没有抓痒,就是说不合式的,Mozilla就不会工作。然后你就可以排 错了,而不需要用校验器来运行你的文档了。
2007 年 6 月 18 日
http://www.ibm.com/developerworks/cn/xml/x-tipapachexhtml/
本文将向您展示:如何配置 Apache 以便为支持可扩展超文本标记语言(Extensible Hypertext Markup Language,XHTML)的浏览器标记文档的媒体类型为 application/xhtml+xml,同时仍然向不支持该语言的浏览器(如 Microsoft® Internet Explorer®)发送 text/html。
当 Web 服务器向浏览器发送文档时,它会给文档加上一个响应报头作为前缀,如 清单 1 所示。此报头包含了用于告诉浏览器如何解释文档的元数据。元数据的一个最重要的部分是最后一行中的 Content-Type
。它将告诉浏览器如何呈现内容。例如,浏览器用于显示 JPEG 和 GIF 的代码是不同的。最重要的是,很多浏览器用于显示 XHTML 和超文本标记语言(Hypertext Markup Language,HTML)的代码也是不同的。
HTTP/1.1 200 OK Date: Thu, 04 Jan 2007 19:39:13 GMT Server: Apache/2 Last-Modified: Wed, 06 Sep 2006 11:19:37 GMT ETag: "4dfce0-c4aa-26828440" Accept-Ranges: bytes Content-Length: 50346 Content-Style-Type: text/css Content-Type: application/xhtml+xml |
Web 服务器应该给 XHTML 文档加上媒体类型标记 application/xhtml+xml。识别此媒体类型的 Web 浏览器就会相应地将其以 strict 模式而不是 tag soup 模式运行。这使浏览器能更可靠地进行显示,对于级联样式表(Cascading Style Sheets,CSS)布局和基于文档的对象模型的 JavaScript ™ 程序,这一点尤为重要。事实上,在一些情况下同一文档能以两种不同的方式显示,取决于其处理模式是 tag soup 还是 strict。如果想要生成格式良好甚或是有效的 XHTML,则 strict 模式将会是您计划使用并希望使用的模式。
不支持 XHTML 的浏览器也能以 tag soup 模式处理格式良好的文档。结果并不完美,但可以满足一小部分使用很老的浏览器的用户需要。对于大部分使用不符合标准的 Internet Explorer 的用户来说,结果也还可以接受。但是,当前版本的 Internet Explorer(包括 6 和 7)无法识别 application/xhtml+xml 媒体类型。如果向 Internet Explorer 发送 application/xhtml+xml 文档,它将会反过来要求您保存文件,如 图 1 所示。
图 1. Internet Explorer 不知道如何处理 application/xhtml+xml
因此,处理 XHTML 时,要获得最大的兼容性,就需要向 Firefox、Safari、Opera 和其他符合标准的浏览器发送 application/xhtml+xml,而向 Internet Explorer 发送 text/html。在这两种情况下发送的是同一个文件。您只需在超文本传输协议(Hypertext Transfer Protocol,HTTP)的报头中更改文件的媒体类型标记即可。使用 Apache Web 服务器时,可在服务器配置文件或个人目录中的 .htaccess 文件中做此更改。
根据默认,Apache 通过检查文件的扩展名来决定与每个文件一起发送的媒体类型。扩展名类型映射存储于 httpd/conf 目录(通常是类似 /usr/httpd/conf 或 /etc/httpd/conf 的目录)下的 mime.types 文件中。比如,清单 2 显示了 Apache 2.0 的 mime.types 文件的部分内容。
# This file controls what Internet media types are sent to the client for # given file extension(s). Sending the correct media type to the client # is important so they know how to handle the content of the file. # Extra types can either be added here or by using an AddType directive # in your config files. For more information about Internet media types, # please read RFC 2045, 2046, 2047, 2048, and 2077. The Internet media type # registry is at <http://www.iana.org/assignments/media-types/>. # MIME type Extensions application/atom+xml atom application/mathematica application/mathml+xml mathml application/msword doc application/octet-stream bin dms lha lzh exe class so dll dmg application/postscript ai eps ps application/rdf+xml rdf application/reginfo+xml application/xhtml+xml xhtml xht application/xslt+xml xslt application/xml xml xsl application/xml-dtd dtd application/xml-external-parsed-entity application/zip zip audio/mpeg mpga mp2 mp3 image/jpeg jpeg jpg jpe image/naplps image/png png image/svg+xml svg image/tiff tiff tif text/html html htm text/plain asc txt text/sgml sgml sgm text/xml text/xml-external-parsed-entity video/mpeg mpeg mpg mpe |
一些更老的版本没有根据默认安装所有这些映射,并且可能事实上使用了一些十分有害的映射。尤其应该注意,对于原始 XML 文件使用 text/xml 而不是 application/xml 是一个常见的问题。
具有了这些默认的映射后,您所需要做的全部工作就是为 XHTML 文件加上 .xhtml 或 .xht 后缀,而不是 .html 后缀,之后,所有这类文件都将被作为 application/xhtml+xml 处理。这对于 Firefox、Opera 和 Safari 效果很好,但对于 Internet Explorer 却并非如此。您所需要的是一种方法,通过它可向 Internet Explorer 发送一种媒体类型而向所有其他浏览器发送另一种媒体类型。
2007 年,可以放心假设所有非 Internet Explorer 的浏览器都能识别 application/xhtml+xml。(如果您确实希望支持很老的浏览器,则破解我下面提出的规则也很容易。)因此您就需要识别 Internet Explorer 的所有版本并将媒体类型更改为 text/html。幸运的是,Internet Explorer 在发送 HTTP 请求时可告知服务器浏览器的类型,如 清单 3 所示。
清单 3. Internet Explorer 的 HTTP 请求报头
GET /test/a.xhtml HTTP/1.1 Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/msword, application/vnd.ms-powerpoint, */* Accept-Language: en-us Accept-Encoding: gzip, deflate User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.1.4322) Host: www.xom.nu Connection: Keep-Alive |
关键在于 User-Agent
字段。虽然由于传统原因 Internet Explorer 在开始时感觉像是 Netscape,但 MSIE
字符串可将其识别为 Internet Explorer。所有版本的 Internet Explorer 在 User-Agent
字段中都包含了此字符串,而所有其他现代的浏览器都不具备此特征。
您需要配置服务器以便查看报头中的 User-Agent
字段,并向 Internet Explorer 发送 text/html,向所有其他浏览器发送 application/xhtml+xml。mod-rewrite 模块并不局限于重写 URL。它还能根据 User-Agent
更改 HTTP 响应报头。清单 4 展示了配置文件中需要放入的代码。
清单 4. 向 Internet Explorer 发送 text.html
RewriteEngine on RewriteCond %{HTTP_USER_AGENT} .*MSIE.* RewriteCond %{REQUEST_URI} \.xhtml$ RewriteRule .* - [T=text/html] |
第一行会打开重写引擎。
第二行的第一个重写条件表明:下面的规则仅适用于 HTTP 请求报头中的 user-agent 字符串包含子字符串 MSIE
的情形。正则表达式 .*MSIE.*
实现了此功能。
第三行的第二个重写条件表明:下面的规则仅适用于浏览器请求的文件具有 .xhtml 扩展名的情形。常规的 .html 文件被作为普通的 text/html 提供给所有浏览器。
最后一行是实际的重写规则。此规则有点不太常见,因为重写并未真正更改 URL 中的任何东西。接下来,匹配整个 URL (.*
) 但接着将其替换成它自己 (-
)。然而,最后的 [T=text/html]
字段会把 Content-Type
报头更改为 text/html。如果同时匹配上述两个条件,则使用此规则。反之则不然。
根据服务器设置的不同,此代码可能位于以下几个位置之一:
这些指导说明在 Apache 1.3 和 2.0 中应该都有效。如果您在 .htaccess 文件中使用这些规则,则似乎没什么作用,这时,确保对目录做出了如下设置以允许在主 httpd.conf 文件中进行覆盖:
<Directory /var/www/foo> AllowOverride FileInfo </Directory> |
如果可以的话,您应该多支持一个不能识别 application/xhtml+xml 的浏览器:Lynx。Lynx 是一种文本模式浏览器,主要由自动化脚本和处理 shell 的 UNIX® 爱好者使用。它的市场份额很小,但是其独特的功能使它具有了足够的重要性,颇值得我们关注,但前提是不给其他用户造成不便。
幸运的是,所有 Lynx 的 user-agent 字符串都以词 “Lynx” 开头,而其他的 user-agent 字符串都不包含该词。因此,为支持 Lynx,您所要做的全部工作就是将该字符串添加到重写条件正则表达式中,如 清单 5 所示:
RewriteEngine on RewriteCond %{HTTP_USER_AGENT} ((.*MSIE.*)|(Lynx.*)) RewriteCond %{REQUEST_URI} \.xhtml$ RewriteRule .* - [T=text/html] |
第二行中的新正则表达式匹配任何包含 MSIE
或以 Lynx
开头的字符串。如果发现另一个浏览器不能很好地处理 application/xhtml+xml,则可向其 user-agent 字符串中做类似的添加。
一些更老版本的 Opera 和 Safari 通过在其 user-agent 字符串中包含 MSIE
将自己伪装成 Internet Explorer。但是您无需为此忧虑,原因如下:
要了解更精确的目标信息,请参阅 参考资料 中到 user-agent 字符串完整列表的链接和可供您参考的 application/xhtml+xml 浏览器支持。
XHTML 是 Web 的未来。但是,像很多其他重要的技术一样,它的采用由于得不到 Microsoft 浏览器的有力支持而受到阻碍。如本文所展示的那样,没有理由等待 Microsoft。您可以轻松地向非 Microsoft 的浏览器提供 XHTML,同时仍然告诉 Internet Explorer 将它作为 tag soup 处理。现代浏览器的访客和页面作者将完全受益于 XHTML,而受 Internet Explorer 牵制的访客则仍然可获得大部分内容。适当地设置 Multipurpose Internet Mail Extensions(MIME)媒体类型并不是向旧的浏览器提供 XHTML 所能采用的惟一途径,但它却是往正确方向上迈出的一大步。
学习