天天看點

兩個小function實作XML和string互相轉化

//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對象。

兩個小function實作XML和string互相轉化

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>​

​ 标簽。

兩個小function實作XML和string互相轉化

但是,如果我們設定的mimeType類型是 ​

​text/xml​

​ 的話,則又是傳回是另外模樣的文檔樹結構:

var domParser = new DOMParser();
console.dir(domParser.parseFromString('<p>内容</p>', 'text/xml'));      

控制台輸出結果如下圖:

兩個小function實作XML和string互相轉化

相容性

DOMParser方法IE9+均支援。

二、了解XMLSerializer方法

XMLSerializer方法的作用和DOMParser相似,XMLSerializer可以讓DOM樹對象序列化為字元串。

文法

var xmlSerializer = new      

此時 ​

​xmlSerializer​

​ 就是一個XMLSerializer對象。

兩個小function實作XML和string互相轉化

XMLSerializer對象有一個名為 ​

​serializeToString()​

​ 的方法,可以傳回序列化的xml字元串。

文法如下:

var      

傳回值是DOMString類型。

參數

rootNode

必須。用來轉換成字元串的DOM樹根節點。

例如:

var xmlSerializer = new XMLSerializer();
console.log(xmlSerializer.serializeToString(document.querySelector('.link')));      

我在本文對應的控制台運作上面JS代碼,結果如下圖:

兩個小function實作XML和string互相轉化

和outerHTML屬性差別

​serializeToString()​

​​ 方法和 ​

​outerHTML​

​ 有些類似,但還是有所差別,主要有有下面兩個:

  1. outerHTML隻能作用在Element元素上,但是不能是其他節點類型,例如文本節點,注釋節點之類。但是​

    ​serializeToString()​

    ​ 方法适用于任意節點類型。包括:
節點類型 釋義
DocumentType 文檔類型
Document 文檔
DocumentFragment 文檔片段
Element 元素
Comment 注釋節點
Text 文本節點
ProcessingInstruction 處理指令
Attr 屬性節點
  1. ​serializeToString()​

    ​方法會給根元素自動增加xmlns命名空間,例如對比下面兩種代碼輸出結果:
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浏覽器截圖如下:

兩個小function實作XML和string互相轉化

可以看到,HTML字元串中注釋相關的,以及換行空格都被移除了,使用DOMParser方法的好處是比正規表達式替換更容易了解與上手,由于使用浏覽器内置的解析,是以HTML字元容錯性更強,使用正規表達式可能無法面面俱到。不足就是代碼量相對多一點。

四、結語

今天整理與研究這篇文章時候發現自己還有很多原生的DOM API不是很了解,例如NodeIterator和TreeWalker,都是IE9+浏覽器都支援的原生API,以後有機會可以介紹下,雖然現在圈子裡關心這類原生DOM API的開發人員占比很低,我們日常使用機率也不高,不過以後如果想要成為creater,優秀的架構創造者,這樣的學習是必不可少的。

參考文檔:

  1. ​​MDN-DOMParser​​
  2. ​​MDN-XMLSerializer​​