//convert string to xml object
function String2XML(xmlString) {
// for IE
if (window.ActiveXObject) {
var xmlobject = new ActiveXObject("Microsoft.XMLDOM");
xmlobject.async = "false";
xmlobject.loadXML(xmlstring);
return xmlobject;
}
// for other browsers
else {
var parser = new DOMParser();
var xmlobject = parser.parseFromString(xmlstring, "text/xml");
return xmlobject;
}
}
//convert xml object to string
function XML2String(xmlObject) {
// for IE
if (window.ActiveXObject) {
return xmlobject.xml;
}
// for other browsers
else {
return (new XMLSerializer()).serializeToString(xmlobject);
}
}
一、了解DOMParser方法
DOMParser可以讓 HTML 字元串解析為DOM樹,格式類型包括 XML 文檔,或者HTML文檔。
文法
var domParser = new
此時
domParser
就是一個DOMParser對象。
DOMParser對象包含一個名為parseFromString的方法。
該方法文法如下:
var
這個方法根據mimeType參數值的不同傳回HTML文檔或者XML文檔。
具體參數如下:
string
必需。字元串。表示被用來解析的DOM字元串(DOMString)。必需包括HTML, xml, xhtml+xml或是svg文檔内容,否則可能解析錯誤。
mimeType
必需。字元串。表示解析的文檔類型,支援下表這些參數值:
mimeType值 | 傳回文檔類型 |
text/html | Document |
text/xml | XMLDocument |
application/xml | XMLDocument |
application/xhtml+xml | XMLDocument |
image/svg+xml | XMLDocument |
其中Document文檔類型是會自動包含
<html>
和
<body>
标簽的,而XMLDocument文檔類型則不會主動添加
<html>
和
<body>
等标簽,且根據我的測試很多普通的HTML标簽有時候會parseerror解析錯誤。
舉個例子:
var domParser = new DOMParser();
console.dir(domParser.parseFromString('<p>内容</p>', 'text/html'));
此時傳回的文檔DOM樹結構如下截圖,出現了DOM字元串參數中沒有的
<html>
和
<body>
标簽。
但是,如果我們設定的mimeType類型是
text/xml
的話,則又是傳回是另外模樣的文檔樹結構:
var domParser = new DOMParser();
console.dir(domParser.parseFromString('<p>内容</p>', 'text/xml'));
控制台輸出結果如下圖:
相容性
DOMParser方法IE9+均支援。
二、了解XMLSerializer方法
XMLSerializer方法的作用和DOMParser相似,XMLSerializer可以讓DOM樹對象序列化為字元串。
文法
var xmlSerializer = new
此時
xmlSerializer
就是一個XMLSerializer對象。
XMLSerializer對象有一個名為
serializeToString()
的方法,可以傳回序列化的xml字元串。
文法如下:
var
傳回值是DOMString類型。
參數
rootNode
必須。用來轉換成字元串的DOM樹根節點。
例如:
var xmlSerializer = new XMLSerializer();
console.log(xmlSerializer.serializeToString(document.querySelector('.link')));
我在本文對應的控制台運作上面JS代碼,結果如下圖:
和outerHTML屬性差別
serializeToString()
方法和
outerHTML
有些類似,但還是有所差別,主要有有下面兩個:
- outerHTML隻能作用在Element元素上,但是不能是其他節點類型,例如文本節點,注釋節點之類。但是
方法适用于任意節點類型。包括:serializeToString()
節點類型 | 釋義 |
DocumentType | 文檔類型 |
Document | 文檔 |
DocumentFragment | 文檔片段 |
Element | 元素 |
Comment | 注釋節點 |
Text | 文本節點 |
ProcessingInstruction | 處理指令 |
Attr | 屬性節點 |
-
方法會給根元素自動增加xmlns命名空間,例如對比下面兩種代碼輸出結果:serializeToString()
div = document.createElement('div');
// 1.
console.log(div.outerHTML);
// 2.
var xmlSerializer = new XMLSerializer();
console.log(xmlSerializer.serializeToString(div));
輸出結果如下圖:
相容性
DOMParser方法IE9+均支援。
三、應用舉例
1. 去除HTML字元串的換行和注釋
首先測試HTML如下,放在一個自定義的script模闆中:
<script id="tpl" type="text/template">
<!-- 這是注釋1 -->
<p>這是文本。</p>
<!-- 這是注釋2 -->
<ol>
<li>清單</li>
<li>清單</li>
<li>清單</li>
</ol>
</script>
我們平常為了便于閱讀,同時維護友善,HTML模闆是包含縮進和注釋的,但是實際解析和這些是不需要的,需要删除,處理字元串正則替換這種方法以外,還可以試試使用浏覽器原生的一些DOM API方法,例如DOMParse,JavaScript代碼如下:
var htmlTpl = tpl.innerHTML;
// 字元串轉換成文檔類型
var domParser = new DOMParser();
var doc = domParser.parseFromString(htmlTpl, 'text/html');
// 使用原生的TreeWalker進行周遊
var treeWalker = document.createTreeWalker(doc);
var arrNodeRemove = [];
// 周遊注釋節點和換行文本節點
while(treeWalker.nextNode()) {
var node = treeWalker.currentNode;
if (node.nodeType == Node.COMMENT_NODE || (node.nodeType == Node.TEXT_NODE && node.nodeValue.trim() == '')) {
arrNodeRemove.push(node);
}
}
// 節點移除
arrNodeRemove.forEach(function (node) {
node.parentNode.removeChild(node);
});
// 字元串還原
console.log(doc.body.innerHTML);
// 輸出結果是:
// <p>這是文本。</p><ol><li>清單</li><li>清單</li><li>清單</li></ol>
Chrome浏覽器截圖如下:
可以看到,HTML字元串中注釋相關的,以及換行空格都被移除了,使用DOMParser方法的好處是比正規表達式替換更容易了解與上手,由于使用浏覽器内置的解析,是以HTML字元容錯性更強,使用正規表達式可能無法面面俱到。不足就是代碼量相對多一點。
四、結語
今天整理與研究這篇文章時候發現自己還有很多原生的DOM API不是很了解,例如NodeIterator和TreeWalker,都是IE9+浏覽器都支援的原生API,以後有機會可以介紹下,雖然現在圈子裡關心這類原生DOM API的開發人員占比很低,我們日常使用機率也不高,不過以後如果想要成為creater,優秀的架構創造者,這樣的學習是必不可少的。
參考文檔:
- MDN-DOMParser
- MDN-XMLSerializer