昨天提到如何改寫 IE Only 網頁的 XML Data Island/MSXML 操作,我用一組元素、Attribute 的新增修改刪除動作對照 XML Data Island/MSXML 與現代瀏覽器的做法差異,算是做完基本功課。但後來熊熊想到,我幹嘛放著 jQuery 不用啦?

用 jQuery 重寫了昨天的範例,目標是支援 IE11/Edge/Chrome/Firefox。IE10 已在去年 EOS,理論上只需管 IE11 就好,但實測降到 IE9 相容模式都還能正常運作(註:IE9 開始支援 DOMParser)。

摘要重點:

  1. IE10+ 及其他瀏覽器雖已不支援 XML Data Island,但 <xml id='x'><root>...</root></xml> 仍被視為一般 HTML 元素處理,若 <xml> 內容是由 ASP.NET 在伺服器產生 XML 內容嵌入,可透過 $('#x').html() 讀取跟修改。但有一點要注意,<xml>...</xml> 在 IE10+ 及各家瀏覽器會顯示純文字部分,實務上可加一行樣式將其隱藏:(本文範例未加,以突顯此行為)
<style>xml { display: none; }</style>
  1. jQuery 1.5+ 支援 $.parseXML('<root>...</root>') 能將 XML 字串直接轉成 XMLDocument 物件,再包一層 $($.parseXML(xmlString)) 即可套用 .find()、children()、.attr()、.text()、.html()... 等好用 jQuery 方法。 參考:神奇的jQuery XML查詢魔法
  2. 如需直接存取 jQuery 物件封裝的 XMLDocument,可寫成 jqXmlObject[0].documentElement。
  3. 要取回完整 XML 需費點功夫,可用 jqXmlObject[0].documentElement.outerHTML (註:jqXmlObject.html() 包不到最外層),但 IE 未實做 XMLDocument documentElement.outerHTML,需借用 XMLSerializer,寫成 new XMLSerializer().serializeToString(jqXmlObject[0].documentElement));

程式範例:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<meta http-equiv="X-UA-Compatible" content="IE=Edge"> 
		<title>jQuery XML 操作範例</title>
	</head>
	<body>
		<div id=m></div>
		<xml id=x></xml>
		<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
		<script>
			function showMsg(m, c) {
				$('<div></div>').text(m)
					.css('color', c || '#444')
					.appendTo('#m');
			}
			
			var srcXml = '<data>\
  <text data-change="OLD" data-del="DEL">text節點</text>\
  <options>\
    <option>A</option>\
    <option>B</option>\
    <option>C</option>\
  </options>\
</data>';
			var ieChk = /MSIE ([0-9]+)/.exec(window.navigator.userAgent);
			showMsg(ieChk && ieChk[0] || 'Moder Browsers', 'purple');
			
			//將XML字串設進XML元素
			$('#x').html(srcXml);
			//從XML元素中取出XML字串
			var xmlStr = $('#x').html();
			
			//$.parseXML()可建立XMLDocument
			//$(XMLDocument)轉成jQuery物件方便操作
			var jqXml = $($.parseXML(xmlStr));
			
			showMsg('selectSingleNode 測試', 'green');
			//取得節點文字
			var n = jqXml.find('text');
			showMsg(n.text());
			//置換節點文字
			n.text('更新文字');
			showMsg('Attribute 增刪改', 'green');
			//增、刪、改 Attribute
			n.attr('data-add', 'ADD');
			n.attr('data-change', 'NEW');
			n.removeAttr('data-del');
			showMsg('selectNodes 測試', 'green');
			//列舉所有option
			jqXml.find('option').each(function(i, n) {
				showMsg('node-' + i + ' = ' + $(n).text());
			});
			//新增new節點
			jqXml.children().append('<new>新增節點</new>');
			//移除第三個option
			jqXml.find('options > option:eq(2)').remove();
			showMsg('輸出XML','brown');
			//取得結果 XML,在 IE 需借助 XMLSerializer
			showMsg(jqXml[0].outerHTML || 
				new XMLSerializer().serializeToString(jqXml[0].documentElement));
		</script>
	</body>
</html>

實測結果,IE11 分別開 IE11、IE10、IE9 相模容式:

Chrome、Edge 及 Firefox:

儘管有人鄙視 jQuery,但今天又是個靠 jQuery 省力解決的案例,它仍會是我前端工具箱最輕巧順手的一把利器。

Example of using jQuery to parse XML, add/modify/remove nodes or attributes.


Comments

# by suadiaaa

請接下我的膝蓋,思古之幽情,黑暗大還有啥古蹟你要修的!?

Post a comment