1.注释标签常用语法1.1注释的注意事项1.2出错条件1.3注释中多个地方出错时1.4两个出错的注释标签,其间的内容被视为注释的一部分1.5解决方案2.浏览器的字符编码2.1问题描述各浏览器对于字符编码别名支持的宽泛程度有差异,当指定了浏览器无法识别的字符编码别名时,浏览器会以确定编码的优先级顺序采用设置的更低优先级的字符编码,以此类推。
而 Chrome Safari Opera 中对字符编码别名有着比其他浏览器更宽泛的支持。
2.2文档的字符编码顺序针对如何确定一个文档的字符编码,用户代码必须遵守下面的优先级顺序(优先级由高至低):(1)HTTP "Content-Type" 字段中的 "charset" 参数。
(2)META 声明中 "http-equiv" 为 "Content-Type" 对应的值中的 "charset" 的值。
(3)元素的 charset 属性。
2.3实例1上面是一段 PHP 代码,HTTP "Content-Type" 头字段设置了字符编码为 BIG5,页面中的 META 元素设置了字符编码为 UTF-8,页面本身的编码类型为 GB2312。
页面执行时,通过脚本输出了当前浏览器所采用的字符编码类型。
这个动态页面在各浏览器中运行时均显示出了 BIG5,可见此时所有浏览器均遵照HTML4.01 规范所述,以更高优先级的 HTTP "Content-Type" 头字段的 "charset" 参数的值作为字符编码类型。
2.4各浏览器默认编码格式上面页面中没有设定任何的字符编码信息,则各浏览器对于这个页面将使用各自的默认编码。
页面自身的编码为 GB2312。
各浏览器中运行效果如下:2.5实例2上面的动态页面自身的编码为 BIG5,HTTP "Content-Type" 头字段设置了字符编码为 maccyrillic,页面中的 META 元素设置了字符编码为 b.i.g+5。
各浏览器中运行效果如下:在 IE6 IE7 IE8 Firefox 中,浏览器无法识别 maccyrillic 这种字符编码别名,所以寻找更低优先级的 META 元素声明的字符编码,但发现也无法识别 b.i.g+5 这种字符编码别名,继而采用了当前语言版本的默认编码 GB2312,与页面自身的字符编码 BIG5 不相符,导致页面中的文字显示异常。
在 Chrome Safari 中,浏览器将 maccyrillic 识别为合法的 X-MAC-CYRILLIC,则不再理会更低优先级的编码设置,页面采用 X-MAC-CYRILLIC 作为字符的编码,与页面自身的 BIG5 编码不符,导致页面中的文字显示异常。
在 Opera 中,浏览器无法识别 maccyrillic 这种字符编码别名,所以寻找更低优先级的 META 元素声明的字符编码,将 b.i.g+5 这种字符编码别名识别为 BIG5,刚好与页面自身的 BIG5 字符编码相符,所以页面中的文字显示正常。
出现上述现象的原因主要有三点:(1)各浏览器的字符编码别名表不尽相同,对同一种编码下的各种别名支持的宽泛程度不一样。
像 maccyrillic 这种别名在 Chrome Safari 可以识别为通用的X-MAC-CYRILLIC,但其他浏览器则会将其视作错误的字符编码信息处理。
(2)各浏览器在匹配页面的字符编码与别名表中的字符编码时,匹配的方式不同。
Chrome Safari Opera 会将编码类型的字符串做一个转换,过滤了除英文大小写字符、数字字符之外的字符(isASCIIAlphanumeric)。
如 ISO8859_5 会以转换后的 ISO88595 与别名表中的 ISO-8859-5 转换后的 ISO88595 做比较,b.i.g+5 也会转换为 big5 与别名表中的做比较,所以浏览器可以正确识别这些设置的字符编码为浏览器内部的别名。
(3)各浏览器的默认字符编码不同。
注1:各浏览器均可以识别X-MAC-CYRILLIC 这种通用的字符编码别名2.6解决方案首先,对于动态页面必须确保 HTTP "Content-Type" 头字段的 "charset" 参数与页面自身编码相符,且务必在页面的 META 元素中也声明相符的字符编码信息。
对于静态页面,必须保证页面中 META 元素声明中 "http-equiv" 为 "Content-Type" 对应的值中的 "charset" 的值与页面自身编码相符。
其次,在设置字符编码别名时,最好使用最通用的、各浏览器均可识别的编码别名。
下面列出了部分的字符编码及其推荐的通用的别名在各浏览器中的支持情况:3. URI 中非ASCII 字符的处理3.1规范根据 HTML 4.01 规范中的描述,URI 中不应该包含非 ASCII 字符。
如以下 href 属性的值是不合法的:<A href="/Håkon">...</A>规范中建议,用户端在这种情况下应采取以下方式处理非 ASCII 字符:(1)将每个字符转换为 UTF-8 编码的相同字符,每个字符将有一或多个字节。
(2)用 URI 编码机制对这些字节进行编码。
如:每个字节转换为 %HH,其中的 HH 为这些字节的值的十六进制表示。
这种方式称为“百分号编码”。
3.2问题分析下面测试各种情况下各浏览器对于 URI 中非 ASCII 字符的编码方式。
在应用中经常使用的编码是 GB2312 和 UTF-8,一个汉字在 GB2312 编码下占 2 个字节,在 UTF-8 编码下占 3 个字节,因此通过对比这两种编码更容易看出区别。
下面的例子中将分别使用这两种编码测试。
●测试使用的非 ASCII 字符均为中文字符“汉”,“汉”在 GB2312 编码中的字节码为“BA BA”,在 UTF-8 编码中的字节码为“E6 B1 89”。
●测试结果的截图中,所有字符均为 ASCII 编码,GB2312 编码的“汉”以 ASCII 编码显示时,为“ºº”,UTF-8 编码的“汉”以 ASCII 编码显示时,为“æ±ᄆ”(第三个字节在 ASCII 字符集中无对应字符,因此显示为“ᄆ”)。
●测试的访问地址均为:http://local.test/BrowserName/汉?汉=汉为了便于区分各浏览器的表现,BrowserName 将在测试中替换为各浏览器名。
●另外,当声明一段测试代码是 GB2312 编码时,其含义为该 HTML 文件的编码为GB2312,并且在该文件中声明了:<meta http-equiv="Content-Type" content="text/html; charset=gb2312"/>同样,当声明一段测试代码是 UTF-8 编码时,其含义为该 HTML 文件的编码为UTF-8,并且在该文件中声明了:<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>注:1. 此处的“汉”字,在不同测试中,实际的编码也不相同。
3.2.1在浏览器的地址栏直接输入包含非ASCII 字符的URI在各浏览器的地址栏中,直接输入“http://local.test/BrowserName/汉?汉=汉”,结果如下:可见,对于 URI 中的非 ASCII 字符:●在 path 部分,所有浏览器都使用了 UTF-8 并做了百分比编码。
●在 query 部分,IE 使用了 GB2312,未做百分比编码;Firefox 和 Opera 使用了GB2312,做了百分比编码;Chrome 和 Safari 则仍使用 UTF-8 并做了百分比编码。
注:1. 因各浏览器的地址栏使用的编码未能确定,本测试仅强调URI 中非ASCII 字符最终使用的字符集。
3.2.2链接跳转或使用脚本跳转到包含非ASCII 字符的URI在不同的编码下,测试以下两段代码:点击按钮或链接后,各浏览器实际发送的 URI 如下:可见,对于 URI 中的非 ASCII 字符:●在 path 部分,所有浏览器都转换为 UTF-8,做了百分比编码。
●在 query 部分,IE 使用当前编码,未做百分比编码;其他浏览器则使用当前编码做百分比编码。
3.2.3使用Ajax请求包含非ASCII 字符的URI(get)在不同的编码下,测试以下代码:点击按钮后,各浏览器实际发送的 URI 如下:可见:(1)IE 无视页面编码设置,将任意编码的字符转换为 GB2312 发送请求,并且对于URI 中的非 ASCII 字符处理如下:●在 path 部分,IE6 并未处理;IE7 IE8 则做百分比编码。
●在 query 部分,IE 并未对其处理。
(2)其他浏览器对于 URI 中的非 ASCII 字符处理如下:●在 path 部分,均转换为 UTF-8 并做百分比编码。
●在 query 部分,Firefox Opera 转换为 UTF-8 并做百分比编码,ChromeSafari 则使用当前编码做百分比编码。
注:1. 这段代码仅为测试编码用,因此并未设置Ajax 请求的回调函数及后续处理,并且对于IE7 IE8,使用XMLHttpRequest 创建的xhr 对象和使用ActiveXObject 创建的xhr 对象的测试结果没有区别。
2. 假设这段代码所在域为local.test,即不会有跨域的问题。
3.3差异总结3.3.1地址栏直接输入:3.3.2点击链接跳转或使用脚本跳转:3.3.3使用Ajax 的get 方法请求:3.4解决方案当 URI 中含有非 ASCII 字符时,不要依赖浏览器对 URI 的编码方式,以避免产生差异。
建议:▪在使用此 URI 之前,先对其进行处理,如使用 JS 的 encodeURI 或encodeURIComponent 方法(JS 的这两个方法会将字符串转换为 UTF-8 并做百分比编码)。
▪在使用 XHR 对象发送 Ajax 请求时,如果仅在 query 部分含有非 ASCII 字符,请使用 post 方法发送,并在 send 之前使用xhrObject.setRequestHeader("Content-Type","application/x-www-form-urlenco ded")。