2014年1月22日 星期三

xPath 在 IE10 IE11 無法作用 (SelectNodes / SelectSingleNode)

最近在做公司的系統後台,關於跨瀏覽器相容的部分
本來後台有指定瀏覽器 -> 最新版本的 chrome
本前端工程師感到非常欣慰



但最近大老闆指示下來,要支援 IE11
(本來是要求支援 IE 但是被我力爭成目前最新版本的 IE11)
由於系統已經使用非常非常的久了
架構龐大且複雜
只好一個一個 bug 的來看

後來發現
其中很多的 bug 都牽涉到同一個來源
就是 IE10 之後, xPath 就不支援了
其實原因很簡單
在過去所有的 xml 都自動被 IE 包裝成 MSXML 格式
但是到了 IE10 之後這個動作被拿掉了!!
因此 xPath 就突然失效了

經過不斷的 google ,網路上有幾個解法
1. 在獲取 xml 的同時,將他封裝成 MSXML
try{
  xhr.responseType = "msxml-document";
}catch(e){}

2. 在使用 xPath 的地方將 xml 變更成 MSXML
var doc;
try{
  doc = new ActiveXObject('Microsoft.XMLDOM');
  doc.loadXML(stringVarWithXml);
  var node = doc.selectSingleNode('//foo');
}catch(e){
  //deal with case that ActiveXObject is not supported
}


3. 使用模擬 xPath 的套件取代 xPath 行為
https://code.google.com/p/wicked-good-xpath/

雖然其實最後這三個解法都無法解決我的問題
我另外又試了另一個可能可以的方法
使用 getElementsByTagName() 函式來取代 SelectNodes (SelectSingleNode)
但是在程式中又都是只尋找下一層的子節點
而且原本的 xml 竟然一大堆同名的節點下方還有同名的節點
真是被打敗

於是花了很多時間,把原本的程式邏輯搞清楚
發現其實根本不需要用到 xPath 因為所有的搜尋行為都只找下一層而已
因此我自己寫了一個 getChildByName function 來取代掉原本的方法
getChildByName = function(xmlDoc, tagName){
  var tmpXML = xmlDoc.cloneNode(true);
  var childNodes = tmpXML.childNodes;
  for(var i = childNodes.length-1 ; i >= 0 ; i--){
    if(childNodes[i].tagName != tagName){
      tmpXML.removeChild(childNodes[i]);
    }
  }
  childNodes = tmpXML.childNodes;
  return childNodes;
}

其實確實是還有改進的空間
但是以目前來說,可以確實解決問題就好了

沒有留言:

張貼留言