AJAX基礎(四)——DOM與xml及xpath

Javascript中裝載XML文檔

裝載同域的XML文件 node

裝載一段表示XML的字符串 數據庫

裝載的js代碼 跨域

function loadXML(flag,xmldoc){

    if(window.ActiveXObject){

        //IE瀏覽器

            var activexName=["MSXML2.DOMDocument","Miscrosoft.XmlDom"];

        var xmlObj;

        for(var i=0;i<activexName.length;i++){

            try{

                xmlObj=new ActiveXObject(activexName[i]);

                break;

            }catch(e){

                

            }

        }

        if(xmlObj){

            //同步方式裝載XML數據

            xmlObj.async=false;

            if(flag){

                //裝載XML的文件

                xmlObj.load(xmldoc);

            }else{

                //裝載XML的字符串

                xmlObj.loadXML(xmldoc);

            }

            //返回根節點

            //return xmlObj;

            //返回根元素節點

            return xmlObj.documentElement;

        }else{

            alert("裝載XML文檔的對象建立失敗");

            return null;

        }

    }else if(document.implementation.createDocument){

        //針對Firefox類瀏覽器

        var xmlObj;

        if(flag){

            //得到XML文檔

            xmlObj=document.implementation.createDocument("","",null);

            if(xmlObj){

                //同步方法進行裝載

                xmlObj.async=false;

                  xmlObj.load(xmldoc);

                return xmlObj.documentElement;

            }else{

                alert("裝載XML文檔的對象建立失敗");

                return null;

            }

        }else{

            //裝載XML字符串

            xmlObj=new DOMParser();

            var docRoot=xmlObj.parseFromString(xmldoc,"text/xml");

            return docRoot.documentElement;
        }

    }

    alert("裝載文檔的對象建立失敗");

    return null;
}


調用裝載代碼:



function text(){

              var domxml1=loadXML(true,"test.xml");

                alert(domxml1);

                var domxml2=loadXML(false,"<xml>123</xml>")

            }


    IEFireFox類的瀏覽器對於這兩種狀況分別有各自的處理方式,所以咱們須要寫一個封裝方法,方便之後進行XML文檔的裝載操做。 數組

    注意和XMLHttpRequest對象同樣,跨域裝載XML文檔會被瀏覽器禁止。 瀏覽器

DOM 操做XML

和操做HTML文檔相同,能夠利用DOMAPI進行XML數據的獲取和修改 app

function test(){

                var rootElement=loadXML(true,"testBook.xml"); 

                var rootDocument=rootElement.parentNode;

                var bookElement=rootDocument.createElement("book");

                var textNode=rootDocument.createTextNode("AJAX Hello");

                bookElement.appendChild(textNode);

                rootElement.appendChild(bookElement);

                

                var bookElements=rootElement.getElementsByTagName("book");

                alert("");

            }


    須要注意document這個特殊的對象只對應於HTML的根節點。XML的根節點須要在得到XMLDOM對象後經過必定的方式獲取出來。 dom

解決瀏覽器處理空白信息的差別

    HTML文檔body的子孫節點或XML根節點的子孫節點中,若是兩個元素節點之間只有空格,縮進,回車這樣的不包含任何文字信息的內容,那麼這些信息就都是空白信息。 async

    IEDOM實如今解析文檔時會過濾掉空白信息,FireFoxDOM實如今解析文檔時會將空白信息當成是文本節點保留。 函數

    這一差別致使使用DOMAPI來遍歷文檔數據須要寫不一樣的代碼來適應不一樣的瀏覽器 oop

    移除全部空白信息,保證IEFireFox下的dom樹結構相同

    解決瀏覽器處理空白信息所用的js函數

function removeBlank(doc){

                if(doc.childNodes.length>1){}

                for(var loopIndex=0;loopIndex<doc.childNodes.length;loopIndex++){

                    var currentNode=doc.childNodes[loopIndex];

                    if(currentNode.nodeType==1){

                        removeBlank(currentNode);

                    }

                    if(((/^\s+$/.test(currentNode.nodeValue)))&&(currentNode.nodeType==3)){

                        doc.removeChild(doc.childNodes[loopIndex--]);

                    }

                }

            }


DOM對象序列化成XML字符串

IE的方法:DOM對象上有一個xml的屬性,能夠得到對象對應的XML的字符串

FireFox的方法:新建一個XMLSerializer對象,而後使用serializeToString方法將DOM對象轉換成XML字符串

function serializeDOM(xmldoc){

                if(xmldoc.xml){

                    //IE瀏覽器

                    return xmldoc.xml;

                    

                }else if(window.XMLSerializer){

                    var seria=new XMLSerializer();

                    return seria.serializeToString(xmldoc);

                }

                return null;

            }


XPATH技術

GetElementById方法在解析XML時是否合適?

    首先XML中每個元素節點不必定有id屬性。

    其次XML中的兩個元素節點可能有相同的id屬性,這樣getElementById這個方法就不能保證找到咱們須要的惟一節點了。

    所以這種方式並不合適XML的解析。

    getElementById的方式一次得到的節點太多,還須要再進行遍歷獲取數據,比較麻煩。

    XPATH即便——解決問題的良藥

XPATH是什麼「全稱是XML PathLanguage(XML路徑語言),適用於肯定XML文檔中某節點位置的語言。

咱們能夠把它當作相似於SQL同樣的查詢語言,經過給出XPATH路徑信息(就像SQL命令同樣)既能夠從XML中查找出符合條件的及誒單(就像從數據庫中返回須要的數據同樣)。

Java中的DOM4j開源包中有selectSingleNode和selectNodes這樣兩個方法能夠根據XPATH表達式來獲取一個或多個節點。

在IE6.0及其之後版本中咱們但是使用一樣的方式來方位呢任意深度的XML數據,這給XML數據的解析操做帶來了便利。

可是在FireFox等瀏覽器中,則是使用了w3c標準的XPATH處理方式,沒有IE這麼簡單的方式。

XPATH技術——咱們用一個實例來說解

首先,寫出獲取路徑的js函數:

function selectNodes(xmldoc,sXpath){

    if(window.ActiveXObject){

        //IE瀏覽器

        return xmldoc.selectSingleNode(sXpath);

    }else if(window.XPathEvaluator){

        //FireFox類瀏覽器

        var xpathObj=new XPathEvaluator();

        if(xpathObj){

            var result=xpathObj.evaluate(sXpath,xmldoc,null,XPathResult.ORDERED_NODE_ITEARTOR_TYPE,null);

            var nodes=new Array();

            var node;

            while((node = result.iterateNext())!=null) {

                nodes.push(node);

            }

           return nodes;

        }else{

            return null;

           

        }

    }else{

        return null;

    }

}


一個重要應用:當返回結果是節點列表時的後續操做

evaluate()方法最常返回的是一個節點列表,獲得節點列表後咱們還要想着怎麼來遍歷這個列表中的全部節點。

 

XPathResult對象提供了4種常量:

    UNORDERED_NODE_ITERATOR_TYPE:節點的無序集合,可經過重複調用iterateNext()直到返回null來訪問。訪問過程當中要保證文檔沒有被修改;

    ORDERED_NODE_ITERATOR_TYPE:節點的列表,按照文檔中節點的屬性排列。訪問方法同上;

    UNORDERED_NODE_SNAPSHOT_TYPE:隨機訪問的節點列表。snapshotLength屬性指定了列表長度,而且snapshotItem()方法返回指定下標的節點。節點可能和在文檔中的順序不同。既然這種結果是一個「快照」,所以即使文檔發生變化,它也有效;

    ORDERED_NODE_SNAPSHOT_TYPE:隨機訪問的節點列表,按照節點在文檔中的順序排列。

    

    若是evaluate()方法中的第4個參數resultType設置的是ANY_TYPE,且返回的是節點列表,則默認的是前兩個(實驗結果,我也不清楚究竟是第一個仍是第二個),而後使用iterateNext()方法來遍歷。

我的以爲第三個或第四個(快照)也不錯,相似數組的操做比較簡單。


在經過調用此函數來獲取不一樣參數的值:

function testxpath(){

                var rootElement=loadXML(true,"XPATH.xml");

                removeBlank(rootElement);

                //查找全部的author元素節點

                //關鍵就是如何表示元素在DOM 樹中的路徑

                //絕對路徑/books/book/author

                //相對路徑 book/author

                //全文檔搜索法//author  //book/author

                var author1=selectNodes(rootElement,"/books/book/author");

                var author2=selectNodes(rootElement,"book/author");

                var author3=selectNodes(rootElement,"//author");

                var author4=selectNodes(rootElement,"//book/author");

                 

                //查找屬性節點

                //關鍵是先找到包含屬性節點的元素節點

                var isdn1=selectNodes(rootElement,"/books/book/@isdn");

                var isdn2=selectNodes(rootElement,"book/@isdn");

                var isdn3=selectNodes(rootElement,"//book/@isdn");

                var isdn4=selectNodes(rootElement,"//books/book/@isdn");

                

                 

               //查找文本節點

               //關鍵是找到包含文本節點的那個元素節點

               var text1=selectNodes(rootElement,"/books/book/name/text()");

               var text2=selectNodes(rootElement,"book/name/text()");

               var text3=selectNodes(rootElement,"//book/name/text()");

               var text4=selectNodes(rootElement,"//name/text()");

              

              //有條件的查找元素節點

              //須要首先找到元素節點,而後再增長條件表達式

              var book1=selectNodes(rootElement,"/books/book[@isdn]");

              var book2=selectNodes(rootElement,"book[@isdn]");

              var book3=selectNodes(rootElement,"//book[@isdn]");

              

              //多個條件與關係的查詢元素節點

              //須要首先找到元素節點,而後每個查詢條件寫在一箇中括號中

              Var bookA1=selectNodes(rootElement,"/books/book[@isdn='0002'][price>35]");

              var bookA2=selectNodes(rootElement,"book[@isdn='0002'][price>35]");

              var bookA3=selectNodes(rootElement,"//book[@isdn='0002'][price>35]");

              

              //多個條件或關係的查找元素節點

              //須要首先找到元素節點,而後每個查詢條件寫在一個XPATH的表達式,這些表達式用|組合,表示或關係

              var book01=selectNodes(rootElement,"/books/book[@isdn='0002']| /books/book[price>35]");

              var book02=selectNodes(rootElement,"book[@isdn='0002']|/books/book[price>35]");

              var book03=selectNodes(rootElement,"//book[@isdn='0002']|/books/book[price>35]");

              alert("");

            }

    

    DOM 的語言無關性設計爲其帶來了很是普遍的可應用性並使其在大量的系統和平臺上得以實現。這樣作的代價是:使 DOM比爲每一個語言專門設計的 API更困難且更缺少直觀性。

    DOM 奠基了一個很是有效的基礎,遵循一些簡單的原則就可其上構建易於使用的系統。凝結了一大羣用戶智慧和經驗的 DOM將來版本正在設計之中,並且極有可能爲這裏討論的問題提供解決方案。如 JDOM這樣的項目正在修改該 API 以得到更天然 Java感受,並且如本文中所述的技術能夠幫助您使 XML的操縱更方便、更簡潔而且不易出錯。利用這些項目且遵循這些用法模式以容許 DOM成爲基於 XML項目的出色平臺。

相關文章
相關標籤/搜索