IE中的XML DOM 與 Firefox中的XML DOM 比較

IE中的XML DOM

當微軟在IE 5.0中第一次加入對XML支持時,他們只是在MSXML ActiveX庫(最初是爲了在IE 4.0中解析Active Channels的組件)中實現XML的功能。最初的版本並無打算公開使用,然而隨着開發人員逐漸瞭解這個組件並嘗試使用時,微軟才意識到這個庫的重要性,很快就在IE 4.01中發佈了MSXML徹底升級版本。
MSXML最初還只是IE的一個組件。直到2001年,微軟發佈了MSXML 3.0,這是一個經過其公司網站獨立發佈的產品。在2001年晚些時候,微軟又發佈了MSXML 4.0,而且將其改名爲微軟XML核心服務組件。MSXML從最初一個基本的、無校驗功能的XML解析器,逐漸發展成一個功能強大的組件,可以校驗XML文檔,進行XSL轉化,支持命名空間、XML的簡單APISAX),以及W3C XPathXML Schema標準,而且每一個新版本都在性能上有必定的提高。
爲了在JavaScript中建立ActiveX對象,微軟實現一個新的ActiveXObject類,該類用來實例化ActiveX對象。ActiveXObject類的構造函數包含一個字符串參數,該參數表示要建立的ActiveX對象的版本,在此指的就是XML文檔的版本。第一個XML DOM ActiveX對象名爲Microsoft.XmlDom,其建立方法以下所示:
var oXmlDom = new ActiveXObject("Microsoft.XmlDom");
這個新建立的XML DOM對象與其餘DOM對象同樣,能夠用來遍歷DOM樹,操做DOM節點。
到本書截稿爲止,MSXML DOM文檔共有五個不一樣的版本,分別是:
q  Microsoft.XmlDom
q  MSXML2.DOMDocument
q  MSXML2.DOMDocument.3.0
q  MSXML2.DOMDocument.4.0
q  MSXML2.DOMDocument.5.0
MSXML是基於ActiveX的實現,所以只可以在Windows平臺上使用。在Mac平臺上的IE 5是不提供XML DOM支持的。
由於存在五個不一樣版本,而你老是會使用最新版,因此使用一個函數來判斷瀏覽器所使用的版本是至關有用的。這樣就能夠確保使用最新的XML支持,獲取最佳的性能。下面的函數createDocument()將使你可以建立正確的MSXML DOM文檔。
function createDocument() {
    var aVersions = [ "MSXML2.DOMDocument.5.0",
       "MSXML2.DOMDocument.4.0","MSXML2.DOMDocument.3.0",
       "MSXML2.DOMDocument","Microsoft.XmlDom"
    ];
 
      for (var i = 0; i < aVersions.length; i++) {
         try {
             var oXmlDom = new ActiveXObject(aVersions[i]);
             return oXmlDom;
         } catch (oError) {
               // 不作任何處理
      }
    }
    throw new Error("MSXML is not installed.");
}
該函數遍歷存放MSXML DOM文檔的版本號的aVersions數組,從最新版本MSXML2.DOMDocument.5.0開始嘗試建立DOM文檔。若是成功建立對象,那麼返回該對象且退出createDocument();不然try...catch語句將捕獲所拋出的異常,並繼續下一次循環,嘗試下一個版本。若是MSXML DOM文檔建立失敗,那麼拋出異常,說明MSXML未安裝。因爲該函數不是一個類,因此用法與其餘函數相似,都將返回一個值:
var oXmlDom = createDocument();
使用createDocument()函數將確保程序使用最新的DOM文檔。當建立了XML文檔後,下一步就是載入XML數據。
1. IE中載入XML數據
MSXML支持兩種載入XML的方法:load()loadXML()Load()方法從Web的指定位置載入一個XML文件。與XMLHttp同樣,load()方法能夠以同步或異步兩種模式載入數據。默認狀況下,load()方法採用異步模式;若是要採用同步模式,那麼必須將MSXML對象的async屬性設置爲false,代碼以下:
oXmlDom.async = false;
當採用異步模式時,MSXML對象公開了readyState屬性,該屬性和XMLHttpreadyState屬性同樣,包含五種狀態。
此外,DOM文檔支持onreadystatechange事件處理函數,能夠監控readyState屬性。由於異步模式是默認選項,所以將async屬性設置爲true是可選的:
oXmlDom.async = true;
 
oXmlDom.onreadystatechange = function () {
    if (oXmlDom.readyState == 4) {
       //document徹底載入後,進行某些操做
    }
};
 
oXmlDom.load("myxml.xml");
本示例中,將把虛構的、名爲myxml.xmlXML文檔載入到XML DOM 文檔中。當readyState值爲4時,說明文檔已經徹底載入,則執行if語句中的代碼。
第二種載入XML數據的方法是loadXML(),該方法與load()方法的主要區別在於從字符串載入XML,而不是根據指定的文件名載入XML。該字符串必須包含正確格式的XML,以下所示:
var sXml = "<root><person><name>Jeremy McPeak</name></person></root>";
 
oXmlDom.loadXML(sXml);
在此,oXmlDom文檔將載入sXml變量中包含的XML數據。loadXML()方法不須要像load()方法那樣檢查readyState屬性,也不須要設置async屬性,由於該方法並不涉及服務器請求。
2. IE中遍歷XML DOM文檔
XML DOM文檔的遍歷與HTML DOM的遍歷很是相似,由於它們都是節點層次的結構。節點樹的最頂部是documentElement屬性,包含文檔的根元素。使用表4-1中所列出的屬性,能夠訪問文檔中任何元素或屬性。
4-1 XML DOM屬性
   
   
attributes
包含當前節點屬性的數組
childNodes
包含子節點數組
firstChild
指向當前節點的第一個子節點
lastChild
指向當前節點的最後一個子節點
nextSibling
返回當前節點的下一個鄰居節點
nodeName
返回當前節點的名字
nodeType
指定當前節點的XML DOM節點類型
nodeValue
包含當前節點的文本
ownerDocument
返回文檔的根元素
parentNode
指向當前節點的父節點
previousSibling
返回當前節點的前一個鄰居節點
text
返回當前節點的內容或當前節點及其子節點的文本(只有IE才支持的屬性)
xml
以字符串返回當前節點及其子節點的XML(只有IE才支持的屬性)
遍歷DOM文檔並獲取數據,是一個很直觀的過程。讓咱們看看下面的XML文檔:
<?xml version="1.0" encoding="utf-8"?>
 
<books>
    <book isbn="0471777781">Professional Ajax</book>
    <book isbn="0764579088">Professional JavaScript for Web Developers</book>
    <book isbn="0764557599">Professional C#</book>
    <book isbn="1861002025">Professional Visual Basic 6 Databases</book>
</books>
這是一個簡單的XML文檔,包含一個根元素<books/>以及四個子元素<book/>。以該文檔爲例,咱們能夠研究DOM的細節。DOM樹是基於節點之間的關係構造的。一個節點可能包含其餘節點或者子節點。另外一個節點可能與其餘節點擁有相同的父節點,咱們稱之爲鄰居節點。
若是要獲取文檔中第一個<book/>元素,那麼只需簡單經過訪問firstChild屬性就能夠達到目的:
var oRoot = oXmlDom.documentElement;
 
var oFirstBook = oRoot.firstChild;
documentElement賦給變量oRoot,能夠節省程序空間和輸入的內容,儘管這並非必需的。使用firstChild屬性能夠引用根元素<books/>的第一個子元素<books/>的引用,並將其賦值給變量oFirstBook
使用childNodes集合也能夠達到相同的目的:
var oFirstBook2 = oRoot.childNodes[0];
選擇childNodes集合中的第一項將返回根節點的第一個子節點。由於childNodesJavaScript中的NodeList類型,因此使用length屬性能夠獲得子節點的數量,以下:
var iChildren = oRoot.childNodes.length;
本示例中,由於文檔元素有四個子節點,因此iChildren值爲4
正如前面所述,節點能夠有子節點,也就意味着它能夠有父節點。經過parentNode屬性能夠選擇當前節點的父節點:
var oParent = oFirstBook.parentNode;
在本小節前面已經提到變量oFirstBook,不過很快,它如今已是文檔中第一個<book/>元素,因此其parentNode屬性就是指DOMdocumentElement屬性,也就是<books/>元素。
若是當前節點是book元素,那麼如何選擇另外一個book元素呢?由於<book/>元素有共同的父節點,因此它們互爲鄰居關係。經過nextSiblingpreviousSibling屬性能夠選擇當前節點的臨近節點。nextSibling屬性指向下一個鄰居,而previousSibling屬性指向前一個鄰居:
var oSecondBook = oFirstBook.nextSibling;
 
oFirstBook2 = oSecondBook.previousSibling;
這段代碼引用第二個<book/>元素,並將其賦值給oSecondBook。經過oSecondBook鄰居節點對變量oFirstBook2從新賦值,oFirstBook2的值不變。若是節點沒有下一個鄰居節點,那麼nextSiblingnull。對於previousSibling也是一樣的,若是當前節點沒有前一個鄰居節點,那麼previousSibling也爲null
如今咱們知道了如何遍歷文檔結構,接下來要了解的是如何從樹的節點獲取數據。例如,使用text屬性能夠獲得包含第三個<book/>元素的文本,代碼以下:
var sText = oRoot.childNodes[2].text;
text屬性(微軟特有的屬性)能夠獲得該節點包含的全部文本節點,該屬性至關有用。若是沒有text屬性,訪問文本節點必須:
var sText = oRoot.childNodes[2].firstChild.nodeValue;
這段代碼與前面使用text屬性的代碼同樣獲得一樣的結果。相似上一個例子,使用childNodes集合引用第三個<book/>元素,而使用firstChild指向<book/>元素的文本節點,由於文本節點在DOM中還是一個節點。使用nodeValue屬性獲取當前節點的值,就能夠獲取文本。
這兩個示例所產生的結果是相同的,然而使用text屬性和使用文本節點的nodeValue屬性之間存在一個主要的區別。text屬性將獲得包含當前元素及其子節點的全部文本節點的值,而nodeValue屬性只能獲得當前節點的值。它雖然是個有用的屬性,但可能會返回比預期值更多的內容。例如,假設咱們將XML文檔修改爲:
<?xml version="1.0" encoding="utf-8"?>
 
<books>
 
    <book isbn="0471777781">
        <title>Professional Ajax</title>
        <author>Nicholas C. Zakas, Jeremy McPeak, Joe Fawcett</author>
    </book>
    <book isbn="0764579088">Professional JavaScript for Web Developers</book>
    <book isbn="0764557599">Professional C#</book>
    <book isbn="1861002025">Professional Visual Basic 6 Databases</book>
</books>
新的XML文檔在第一個<book/>元素中添加了兩個新的子節點:<title/>元素(書名),<author/>元素(做者)。咱們再一次使用text屬性:
alert(oFirstChild.text);
代碼中沒有其餘新的內容,咱們能夠看看圖4-1中所顯示的結果。
  4-1
請注意,這時咱們將得到<title/><author/>元素的文本節點,並將其鏈接在一塊兒。這就是textnodeValue的不一樣之處。nodeValue屬性只能獲得當前節點的值,而text屬性則將獲得包含當前節點及其子節點的全部文本節點。
MSXML還提供其餘一些獲取特定節點或數值的方法,最經常使用的方法是getAttribute()getElementsByTagName()
getAttribute()方法將接受一個包含屬性名稱的字符串型參數,並返回屬性值。若是指定的屬性不存在,那麼返回的值爲null。咱們還將使用本小節前面提到的那個XML文檔,請看下列代碼:
var sAttribute = oFirstChild.getAttribute("isbn");
 
alert(sAttribute);
這段代碼獲取第一個<book/>元素的isbn屬性值,並將其賦值給變量sAttribute而後使用Alert()方法顯示該值。
getElementsByTagName()方法根據其參數所指定的名字,返回子元素的NodeList。該方法只搜索給定的節點中的元素,因此返回的NodeList不包含任何外部元素。例如:
var cBooks = oRoot.getElementsByTagName("book");
 
alert(cBooks.length);
這段代碼獲取文檔中全部的<book/>元素,並將返回的NodeList賦值給變量cBooks。對於前面那個XML文檔例子而言,警告框將顯示找到的四個<book/>元素。若是要獲取全部子節點,那麼必須用「*」做爲getElementsByTagName()方法的參數,其代碼以下所示:
var cElements = oRoot.getElementsByTagName("*");
由於前面的XML文檔例子中只包含<book/>元素,因此這段代碼的結果與上一個示例相同。
3. IE中獲取XML數據
要獲取XML數據只需使用一個屬性,即xml。該屬性將對當前節點的XML數據進行序列化。序列化(serialization是將對象轉換成簡單的可存儲或可傳輸格式的過程。xml屬性將XML轉換成字符串形式,包括完整的標籤名稱、屬性和文本:
var sXml = oRoot.xml;
alert(sXml);
這段代碼從文檔元素開始序列化XML數據,並將其做爲參數傳遞給alert()方法。下面就是部分已序列化的XML
<books><book isbn="0471777781">Professional Ajax</book></books>
已序列化的數據能夠載入到另外一個XML DOM對象,發送到服務器,或者傳給另外一個頁面。經過xml屬性返回的已序列化XML數據,取決於當前節點。若是是在documentElement節點使用xml屬性,那麼將返回整個文檔的XML數據;若是隻是在<book/>元素上使用它,那麼將返回該<book/>元素所包含的XML數據。
xml屬性是隻讀屬性。若是但願往文檔中添加元素,那麼必須使用DOM方法來實現。
4. IE中操做DOM
如今爲止,咱們已經學習如何遍歷DOM,從DOM中提取信息,將XML轉換成字符串格式。接下來學習的是如何在DOM中添加、刪除和替換節點。
l   建立節點
使用DOM方法能夠建立多種不一樣的節點。第一種就是用createElement()方法建立的元素。向該方法傳入一個參數,指明要建立的元素標籤名稱,並返回一個對XMLDOMElement的引用:
var oNewBook = oXmlDom.createElement("book");
 
oXmlDom.documentElement.appendChild(oNewBook);
這段代碼建立一個新的<book/>元素,並經過appendChild()方法把它添加到documentElement中。appendChild()方法添加由其參數指定的新元素,而且將其做爲最後一個子節點。但在該例子中,添加到該文檔中的是一個空的<book/>元素,於是還須要爲該元素添加一些文本:
var oNewBook = oXmlDom.createElement("book");
 
 
var oNewBookText = oXmlDom.createTextNode("Professional .NET 2.0 Generics");
 
oNewBook.appendChild(oNewBookText);
 
oXmlDom.documentElement.appendChild(oNewBook);
這段代碼經過createTextNode()方法建立一個文本節點,並經過appendChild()方法把它添加到新建立的<book/>元素中。createTextNode()方法只有一個字符串參數,用來指定文本節點的值。
如今已經經過程序建立了新的<book/>元素,爲其提供了一個文本節點,並將它添加到文檔中。對於這個新元素而言,還須要像其餘鄰居節點同樣,爲其設置isbn屬性。這很簡單,只要經過setAttribute()方法就能夠建立屬性,該方法適用於全部元素節點。
var oNewBook = oXmlDom.createElement("book");
 
var oNewBookText = oXmlDom.createTextNode("Professional .NET 2.0 Generics");
oNewBook.appendChild(oNewBookText);
 
oNewBook.setAttribute("isbn","0764559885");
 
oXmlDom.documentElement.appendChild(oNewBook);
上面這段代碼中,新添加的一行是用來建立isbn屬性的,並將其值賦爲0764559885setAttribute()方法有兩個參數:第一個參數是屬性名,第二個參數則是賦給該屬性的值。對於向元素添加屬性,IE還提供其餘一些方法,不過它們實際上並不比setAttribute()更好用,並且還須要更多的編碼。
l   刪除、替換和插入節點
若是可以往文檔中添加節點,那麼一樣意味着能夠刪除節點。removeChild()方法正是用來實現該功能的。該方法包含一個參數:要刪除的節點。例如,要從文檔中刪除第一個<book/>元素,則可使用如下代碼:
var oRemovedChild = oRoot.removeChild(oRoot.firstChild);
removeChild()方法返回被刪除的子節點,於是oRemoveChild變量將指向已刪除的<book/>元素。當擁有對舊節點的引用時,就能夠將其放置在文檔的任何地方。
若是想用oRemovedChild指向的元素來替換第三個<book/>元素,那麼能夠經過replaceChild()方法來實現,該方法返回被替換的節點:
var oReplacedChild = oRoot.replaceChild(oRemovedChild, oRoot.childNodes[2]);
replaceChild()方法接受兩個參數:新添加的節點和將被替換的節點。在這段代碼中,將用oRemovedChild變量引用的節點替換第三個<book/>元素,而被替換節點的引用將存在oReplacedChild變量中。
因爲oReplaceChild變量是被替換節點的引用,於是能夠容易地將其插入到文檔中。使用appendChild()方法能夠該其添加到子節點列表的最後,也可使用insertBefore()方法將該節點插入到某個節點以前:
oRoot.insertBefore(oReplacedChild, oRoot.lastChild);
這段代碼將以前被替換的節點插入到最後一個<book/>元素的前面。lastChild屬性的用法與firstChild選擇第一個子節點很是類似,經過該屬性能夠獲取最後一個子節點。insertBefore()方法接受兩個參數:要插入的節點和表示插入點的節點(插入點在該節點以前)。該方法也將返回插入節點的值,但上述例子中並不須要。
如你所見,DOM是一個至關強大的接口,經過它能夠實現數據的獲取、刪除和添加等操做。
5. IE中處理錯誤
XML數據的載入過程當中,可能會因爲不一樣的緣由而拋出錯誤。例如,外部的XML文件找不到,或者XML的格式不正確。爲了處理這些狀況,MSXML提供了一個包含錯誤信息的parseError對象。對於每一個由MSXML建立的XML DOM文檔對象而言,該對象都是其所屬的屬性值之一。
咱們能夠經過parseError對象公開的與整數0進行比較的errorCode屬性來檢查錯誤。若是errorCode不等於0,則表示有錯誤發生。下面的例子故意設計出現一個錯誤。
var sXml = "<root><person><name>Jeremy McPeak</name></root>";
var oXmlDom = createDocument();
oXmlDom.loadXML(sXml);
 
if (oXmlDom.parseError.errorCode != 0) {
    alert("An Error Occurred: " + oXmlDom.parseError.reason);
} else {
    //XML載入成功後的操做
}
你們會注意到,在突出顯示的代碼行中,<person>元素是不完整的(沒有相應的</person>標籤)。因爲要載入的XML的格式不正確,所以將產生一個錯誤。而後errorCode0進行比較,若是不相等(在本例中就不相等),那麼將顯示發生錯誤的警告。要實現該功能,可使用parseError對象的reason屬性來獲取錯誤出現的緣由。
parseError對象提供瞭如下屬性,可以幫助你更好地瞭解錯誤:
q  errorCode:錯誤代碼(長整型);
q  filePos:在文件中發生錯誤的位置(長整型);
q  line:包含錯誤的代碼行的行號(長整型);
q  linePos:在特定行中發生錯誤的位置(長整型);
q  reason: 錯誤的緣由(字符串型);
q  srcText: 發生錯誤的代碼行內容(字符串型);
q  url: XML文檔的URL(字符串型)。
儘管這些屬性提供了每種錯誤的信息,可是應該使用哪一個屬性,則取決於你的須要。
errorCode屬性能夠是正數也能夠是負數,只有當errorCode0時才表示沒有錯誤發生。

 

Firefox中的XML DOM

如今咱們來看看Firefox中的XML DOM實現,Firefox的開發人員採用更爲標準的方法,將其做爲JavaScript實現的一部分。Mozilla確保全部基於Gecko的瀏覽器的全部平臺都支持XML DOM
Firefox中建立一個XML DOM,須要調用document.implementation對象的createDocument()方法。該方法接受三個參數:第一個參數是包含文檔所使用的命名空間URI的字符串;第二個參數是包含文檔根元素名稱的字符串;第三個參數是要建立的文檔類型(也稱爲doctype)。若是要建立空的DOM文檔,則代碼以下所示:
var oXmlDom = document.implementation.createDocument("", "", null);
前兩個參數是空字符串,第三個參數爲null,這樣能夠確保生成一個完全的空文檔。事實上,如今Firefox中並不提供針對文檔類型的JavaScript支持,因此第三個參數老是爲null。若是要建立包含文檔元素的XML DOM,那麼能夠在第二個參數中指定標籤名稱:
var oXmlDom = document.implementation.createDocument("", "books", null);
這段代碼建立了一個XML DOM,其documentElement<books/>。若是要建立包含指定命名空間的DOM,能夠在第一個參數中指定命名空間URI
var oXmlDom = document.implementation.createDocument("http://www.site1.com",
       "books", null);
當在createDocument()方法中指定命名空間時, Firefox會自動附上前綴a0以表示命名空間URI
<a0:books xmlns:a0="http://www.site1.com" />
接着,你能夠經過程序來填充XML文檔,不過在通常狀況下,還須要在空的XML DOM對象中載入現有的XML文檔。
1. Firefox中載入XML數據
Firefox中,將XML載入XML DOM的方法和微軟採用的方法大體相同,只存在一個顯著區別:Firefox只支持load()方法。所以,在這兩種瀏覽器中載入外部XML數據的代碼是相同的:
oXmlDom.load("books.xml");
與微軟的IE同樣,Firefox一樣實現了async屬性,該屬性的行爲也與其一致:將async設置爲false,表示以同步模式載入文檔;不然,以異步模式載入文檔。
FirefoxXML DOM實現和微軟的XML DOM實現還存在另外一個不一樣,即Firefox不支持readyState屬性及onreadystatechange事件處理函數。在Firefox中,支持load事件和onload事件處理函數。在文檔徹底載入後將觸發load事件:
oXmlDom.load("books.xml");
oXmlDom.onload = function () {
    //文檔徹底載入後的操做
};
正如前面所說,在FirefoxXML DOM實現中,並無loadXML()方法,不過經過Firefox中的DOMParser類能夠模擬loadXML()的行爲。該類有一個名爲parseFromString()的方法,用來載入字符串並解析成文檔:
var sXml = "<root><person><name>Jeremy McPeak</name></person></root>";
var oParser = new DOMParser();
var oXmlDom = oParser.parseFromString(sXml,"text/xml");
在這段代碼中,建立了一個XML字符串,並做爲參數傳遞給DOMParserparseFromString()方法。parseFromString()方法的兩個參數分別是XML字符串和數據的內容類型(通常設置爲text/xml)parseFromString()方法返回XML DOM對象,所以這裏獲得的oXmlDom與第一個例子相同。
2. Firefox中獲取XML數據
儘管存在這樣那樣的不一樣,但IEFirefox中用於獲取文檔中XML數據的大多數屬性和方法是一致的。正如在IE中,可使用documentElement屬性來獲取文檔的根元素,例如:
var oRoot = oXmlDom.documentElement;
Firefox一樣支持W3C標準屬性,包括childNodesfirstChildlastChildnextSiblingnodeNamenodeTypenodeValueownerDocumentparentNodepreviousSibling。不幸的是,對於微軟專有的textxml屬性,Firefox並不支持,不過能夠利用其餘方法來模擬該屬性的行爲。
你們應該還記得,text屬性返回了當前節點的內容,或者是當前節點及其子節點的內容。這不只僅返回當前節點的文本,還有全部子節點的文本,所以要模擬該功能實現是十分容易的。下面這個簡單的函數就可以完成該功能,該函數惟一的參數是一個節點:
function getText(oNode) {
    var sText = "";
    for (var i = 0; i < oNode.childNodes.length; i++) {
       if (oNode.childNodes[i].hasChildNodes()) {
           sText += getText(oNode.childNodes[i]);
       } else {
           sText += oNode.childNodes[i].nodeValue;
       }
    }
    return sText;
}
getText()函數中,sText變量用來保存獲取的全部文本。接着對oNode的子節點使用for循環進行遍歷,檢查每一個子節點是否包含子節點。若是有子節點,那麼就將其childNode傳給getText()函數,並進行一樣的處理;若是沒有子節點,那麼將當前節點的nodeValue加到字符串中(對文本節點而言,這只是文本字符串)。處理了全部子節點後,該函數返回變量sText
IE中的xml屬性將存放對當前節點包含的全部XML進行序列化的結果。在Firefox中,提供了一個名爲XMLSerializer對象來完成這一功能。該對象提供一個使用JavaScript可訪問的serializeToString()方法,使用該方法能夠對XML數據進行序列化。
function serializeXml(oNode) {
    var oSerializer = new XMLSerializer();
    return oSerializer.serializeToString(oNode);
}
serializeXml()函數以XML節點做爲參數,建立一個XMLSerializer對象,並將該節點傳給serializeToString()方法。該方法將向調用者返回XML數據的字符串表示。
對於節點操做的DOM方法,FirefoxIE大體相同。參見「在IE中操做DOM」小節。
3. Firefox中處理錯誤
FirefoxIE的錯誤處理並不同。當IE遇到錯誤時,它會填充parseError對象;而當Firefox遇到錯誤時,它會將包含錯誤信息的XML文檔載入到XML DOM文檔中。看下面的這個例子:
var sXml = "<root><person><name>Jeremy McPeak</name></root>";
var oParser = new DOMParser();
var oXmlDom = oParser.parseFromString(sXml,"text/xml");
 
if (oXmlDom.documentElement.tagName != "parsererror") {
    //沒有錯誤發生,進行所需操做
} else {
    alert("An Error Occurred");
}
在突出顯示的代碼行中,你會發現其中將產生一個錯誤:XML字符串格式不正確(由於<person>元素不完整,沒有相應的</person>元素)。當載入錯誤的XML時,XML DOM對象將會載入一個documentElement<parsererror/>的錯誤文檔。咱們能夠經過檢查documentElementtagName屬性來很容易地肯定是否發生錯誤。若是tagName屬性不是parsererror,就能夠肯定沒有發生任何錯誤。
在本例中,可能會生成以下所示的錯誤文檔:
<parsererror xmlns="http://www.mozilla.org/newlayout/xml/parsererror.xml">XML
Parsing Error: mismatched tag. Expected: </person>.
Location: [url]http://yoda/fooreader/test.htm[/url]
Line Number 1, Column 43:<sourcetext><root><person><name>Jeremy
McPeak</name></root>
------------------------------------------^</sourcetext></parsererror>
全部的錯誤信息都包含在錯誤文檔的文本中。若是要經過程序使用這些錯誤信息,那麼首先就要對其進行解析。最簡單的方法是使用一個稍長的正則表達式:
var reError = />([\s\S]*?)Location:([\s\S]*?)Line Number (\d+), Column
    (\d+):<sourcetext>([\s\S]*?)(?:\-*\^)/;
該正則表達式將錯誤文檔分爲五個部分:錯誤消息、發生錯誤的文件名、行號、該行中發生錯誤的位置,以及發生錯誤的源代碼。使用正則表達式對象的test()方法可使用這些信息:
if (oXmlDom.firstChild.tagName != "parsererror") {
    //沒有錯誤發生,進行所需操做
} else {
    var oXmlSerializer = new XMLSerializer();
    var sXmlError = oXmlSerializer.serializeToString(oXmlDom);
    var reError = />([\s\S]*?)Location:([\s\S]*?)Line Number (\d+), Column
       (\d+):<sourcetext>([\s\S]*?)(?:\-*\^)/;
    reError.test(sXmlError);
正則表達式捕獲到的第一部分數據是錯誤消息,第二部分是文件名,第三部分是行號,第四部分是行內位置,第五部分是源碼。你可使用這些解析後的信息來建立自定義的錯誤消息:
var str = "An error occurred!!\n" +
    "Description: " + RegExp.$1 + "\n" +
    "File: " + RegExp.$2 + "\n" +
    "Line: " + RegExp.$3 + "\n" +
    "Line Position: " + RegExp.$4 + "\n" +
    "Source Code: " + RegExp.$5;
 
alert(str);
若是發生錯誤,那麼alert()方法會以易於閱讀的格式在警告框中來顯示相關的錯誤信息。
相關文章
相關標籤/搜索