古蹟維護 - IE Only 網頁之 XML Data Island/MSXML 移植
4 |
IE 大限揭曉一文提到,野生 IE11 將會在 2022/6/15 滅絕,企業人工飼養的 IE 估計還至少可用到 2029 (嗚... 好像沒法再戰十年了),企業內部的 IE Only 網頁還可再撐段時間沒問題,但早點動手升級永遠比拖到最後一刻好,現在就該研究怎麼翻修升級。
今天先從一個超冷門的上古兵器開始講起 - XML Data Island。
它的概念是在 HTML 硬生生插入一段 XML 原生資料結構,類似這樣:
簡單來說是種「把 XML 資料內嵌在 HTML 使用」的概念。
現役專案有一批 ASP 時代作品充斥大量 VBScript + XML Data Island,在當年算是很先進的技術,加上系統做得頗成功,導致後來進入 ASP.NET 時代,VBScript 被 JavaScript 取代,但 XML Data Island 倒是被留下來搬進 WebForm。聽起很蠢?不會好嗎? 那可是 IE 市佔破 90% 的年代,所謂跨瀏覽器是指跨 IE6 跟 IE7 (笑),複製成功做法省時省力,在當時可是睿智選擇。
十年後,JSON 逐漸取代 XML 成為網頁資料交換的王道,IE10 起不再支援 XML Data Island,但用 X-UA-COMPATIBLE 指定 IE 相容模式,就算 IE11 仍可開心使用 XML Data Island,老 IE 網頁還是快快樂樂繼續用下去,直到 IE 就被消滅的這一天,終於要面對了。
IE 在背後是用 MSXML ActiveX 元件處理 XML Data Island,所以今天討論的議題也適用 AJAX MSXML 操作,現代瀏覽器本身對 XML 操作的支援也很完整,要取代 MSXML 完全沒問題,要改寫也不難,基本上就是用 XMLDocument、DOMParser 搞定,我整理了一個簡單範例,在 IE 7/8/9 用 XML Data Island/MSXML,在 IE10+ 跟其他瀏覽器則用 XMLDocument,示範基本的節點讀取/更新/刪除、集合巡覽、Attribute 操作等基本動作,留給未來的我參考。
廢話不多說,直接上 Code:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=9">
<title>XML Island Migration</title>
</head>
<body>
<ul id=m></ul>
<xml id=x></xml>
<script>
var ieChk = /MSIE ([0-9])/.exec(window.navigator.userAgent);
function showMsg(m) {
var li = document.createElement('li');
li.innerText = m;
document.getElementById('m').appendChild(li);
}
var xmlString = '<data>\
<text data-change="OLD" data-del="DEL">text節點</text>\
<options>\
<option>A</option>\
<option>B</option>\
<option>C</option>\
</options>\
</data>';
function xmlAppendChildTextElement(x, xParent, elemName, elemText) {
var xt, xe;
xe = x.createElement(elemName);
xt = x.createTextNode(elemText);
xe.appendChild(xt);
xParent.appendChild(xe);
}
if (ieChk && parseInt(ieChk[1])<10)
{
showMsg('IE7/8/9');
var xd = document.getElementById('x');
xd.loadXML(xmlString);
showMsg('selectSingleNode 測試');
//取得text節點文字
var n = xd.documentElement.selectSingleNode('text');
showMsg(n.text);
//置換text節點文字
n.text = '更新文字';
//增、刪、改 Attribute
n.setAttribute('data-add', 'ADD');
n.setAttribute('data-change', 'NEW');
n.removeAttribute('data-del');
showMsg('selectNodes 測試');
//列舉所有option
var nodeList = xd.documentElement.selectNodes('//option');
for (var i = 0; i < nodeList.length; i++) {
showMsg('node-' + i + ' = ' + nodeList[i].text);
}
//新增new節點
xmlAppendChildTextElement(x, x.documentElement, 'new', '新增節點');
//移除第三個option
var n = xd.documentElement.selectSingleNode('options/option[2]');
n.parentNode.removeChild(n);
showMsg(xd.xml);
}
else {
showMsg("IE10+ or Modern Browsers");
var xd = new DOMParser().parseFromString(xmlString, "text/xml");
showMsg('selectSingleNode 測試');
//取得text節點文字
var n = xd.documentElement.getElementsByTagName('text')[0];
showMsg(n.childNodes[0].nodeValue);
//置換text節點文字
n.childNodes[0].nodeValue = '更新文字';
//增、刪、改 Attribute
n.setAttribute('data-add', 'ADD');
n.setAttribute('data-change', 'NEW');
n.removeAttribute('data-del');
showMsg('selectNodes 測試');
//列舉所有option
var nodeList = xd.documentElement.getElementsByTagName('option');
for (var i = 0; i < nodeList.length; i++) {
showMsg('node-' + i + ' = ' + nodeList[i].childNodes[0].nodeValue);
}
//新增new節點
xmlAppendChildTextElement(xd, xd.documentElement, 'new', '新增節點');
//移除第三個option
var nodeToRemove = xd.documentElement.querySelector('options > option:nth-child(3)');
nodeToRemove.parentNode.removeChild(nodeToRemove);
showMsg(xd.documentElement.outerHTML || new XMLSerializer().serializeToString(xd.documentElement));
}
</script>
</body>
</html>
不囉嗦,馬上看結果:
Tips of migrating IE XML data island/MSXML operation to modern browsers.
Comments
# by Jackson2774
一言不"合"
# by Jeffrey
to Jackson2774, 謝謝,已修正。
# by Huang
XML不知道還要多久才會被消失
# by HarryHung
好懷念啊,這好像是古人我二十年前留下的餘孳 XD 不好意思,辛苦大家了。