新版瀏覽器

做網路的人請注意一下,IEFirefox 這個星期都會推出最新的版本。

FirefoxFirefox 2.0 沒有意外的話明天會正式發行。感覺 Firefox 的哲學慢慢的轉變成提供一個裝了就有所有功能的完整瀏覽器,而不是原來 1.0 ~ 1.5 這樣弄成要去找擴充套件用起來才順手這樣。在亞洲市場或許是個利多。

Internet Explorer
Internet Explorer 7 英文版前幾天已經公布下載了,中文版不知道台灣微軟什麼什麼時候要弄出來。IE 在 2001 年之後就一直沒有出過新版,有效的讓一般人忘記瀏覽器跟所有軟體一樣需要出新版。這五年以來許多好人(?)也前仆後繼的做了一堆增強 IE 功能但是網頁顯示核心卻都一樣糟的瀏覽器。

從網頁設計的觀點,Firefox 因為是標準瀏覽器,出了新版大概不會讓網頁看起來不一樣。IE 的話,不知道 IE6 正常的網頁到 IE7 會不會壞掉 (或是說,IE6 上壞掉的東西到 IE7 會不會正常?(笑) ;也可以說這些考慮是多餘的啦,畢竟裝 IE7 需要通過 Windows 正版檢查 —— 台灣一半以上的電腦都不會通過(爆);這些電腦會繼續使用 IE6 與呼叫 IE6 來顯示網頁的 KKMAN & PCMan 直到 … 誰知道到什麼時候?某個病毒把盜版 Windows 搞的不堪用的那天吧。

XML parsing on different browsers

瀏覽器解析 XML 的不同行為

一個 XML 文件長這個樣子:一個文件類型宣告 (<?xml ?>)、一個根目錄 element 包含其他的 element。所以當 XMLHttpRequest 物件抓遠端的 XML 回來解析的時候,obj.responseXML 這個 XMLDocument Object 的 .childNodes.length 應該是 1 —— .firstChild 就是 root element 。

問題來啦:以上看似合理的 XML parsing 只發生在 Mozilla 上面。在 IE 裡面 childNodes.length 是 2,firstChild.nodeName 會傳回 … ?xml !這是怎樣?

那改用 .lastChild 去拿 root element 好了,這總不會出錯了吧。嘿嘿,不行 —— Operaobj.responseXML 更有趣:childNodes.length = 2 ,第一個 childNode 是 ?xml、第二個是 root、第三個是 … #text,nodeValue是長度 0 空字串。我檢查過,這絕對不是 Server 端的問題,因為那邊是用 PHP DOM 在生 well-formed XML 的。

最後我的解法還是用 obj.responseXML.lastChild 拿 root,不過在之前先經過一個判斷式:如果 .lastChild.nodeName == ‘#text’ 就做 removeChild 的動作。

這個解析 XML 的差異是因為各家瀏覽器 XMLHttpRequest 物件行為的不同,與 prototype.js 無關。prototype.js 只做 warpper 而已,裡面搞成這樣它應該是不知道。

還有另外一種解法是不要做 AJAX —— 做 AJAteXt,叫伺服器傳文字進來,再從 obj.responseText 抓出來處理。不是很正統而且還需要而額外寫解析函式的方法,但 GMail 好像就是這樣在抓信件內文的。

XMLHttpRequest on different browsers parses XML in different ways. An XMLDocument Object contains a <?xml ?> doctype declaration and a root element. Anything else should be child nodes under the root. Thus, when the XML file is fetched, obj.responseXML.childNodes.length should return 1, and firstChild should return the root element.

Sounds right? Not quite. What described above only occurs in Mozilla. In poor-designed IE6, childNodes.length returns 2 — firstChild.nodeName returns ?xml. Opera behaviors even weirder; childNodes.length returns 3, first two are same as IE, and the their one is a #text with zero-length string nodeValue.

I ended up using lastChild to retrive the root element after checking its nodeName; if lastChild.nodeName == ‘#test’ { removeChiid(); } .

The other solution is to abandon AJAX – use AJAteXt instead. By parse responseText on your own code, you could avoid these kind of inconsistent behaviors. Kind of non-standard method, but AFAIK, Gmail does use AJAteXt to retrieve mail text.