同事報案,某套裝軟體網站無法檢視特定網頁。比對後發現,問題網頁的共同特徵是內含 Unicode 罕用字,而問題只發生在 IE,改用 Chrome 或 Edge 則一切正常。

這裡先簡單解釋所謂的「Unicode 罕用字」,學名其實是 Surrogate Pairs。Windows 通常用 UTF-16 編碼(2 Bytes) 表示 Unicode 字元,但這樣最多只能表示 65,536 個字元,Unicode 4.1 標準則包含超過 97,000 個字元(其中單單中文就超過 7 萬個,Wow!),因此在 Basic Multilingual Plane (BMP) 之外,Unicode 標準又定義了額外 16 個 Plane,共可容納 110 萬個字元,但目前只用到 U+0000 - U+10FFFF 區段。當需要表示 BMP 以外的補充字元,得改用兩個 UTF-16 編碼組成一個 Surrogates Pair (共四個 Bytes)表示。總之,我們只需要知道,BMP 以外的罕用字元區,每個 Unicode 字元需要四個 Bytes 才能表示,在編碼及字型處理上,與一般 Unicode 字元不同。為了方便溝通,我習慣叫這種字元 - 「Unicode 罕用字」。

回到茶包上。(跳一下)

從出錯網頁找到嫌疑字元 -「𥴰」(靖字加上竹字頭),因為 IE 無法顯示,用 Chrome 檢查,發現它在 HTML 共出現兩次,一次直接寫輸「𥴰」,另一次則是以 NCR 表示,寫成 𥴰

寫了一個簡單網頁包含這個字元的兩種表示法進行測試,但用 IE 檢視很正常:

花了點時間分析網路傳輸跟 JavaScript 程式,發覺該網頁的顯示方式較特殊,是透過 AJAX 呼叫取回內含網頁 HTML 的 XML,再從中取出 HTML 動態顯示網頁。因此,我改用 XML 夾帶 Unicode 罕用字做測試:

<?xml version='1.0' encoding='utf-8' ?>
<root>
	<div>𥴰</div>
	<div>&#x25D30;</div>
</root>

起初用 IE11 開啟倒也沒什麼問題,但老司機馬上想到要測其他 IE 相容模式:

果然,一旦切換 IE8 以下的 IE 相容模式就會出錯!

至此可推論 - 「IE8- 無法正常處理內含 Unicode 罕用字的 XML」! 依此結論回頭檢查問題網站,網頁果真被設成 IE8 相容,這樣就有了合理解釋。但試著以 F12 強制改為 IE11 模式,問題並沒有解決。進一步追查,發現該套裝軟體在 HTML 裡加了 X-UA-Compatible 指定 IE=8 強制指定 IE8 相容,由於是套裝軟體,如何修改調整是另一種挑戰,此處按下不表。

可能年代太久遠了,我沒找到 IE8- XML 不支援 Unicode 罕用字的文獻,但實測結果夠明確,加上行將就木的瀏覽器不值得深究,就此打住。

A case of XML containing Unicode surrogate pairs char causing IE8 failed to display web page.


Comments

# by Huang

國人使用的中文字數還在持續成長中,至少10萬字以上了XD,國人愛造字

# by ByTIM

還有異體字,遇到都很傻眼。

Post a comment