用jQuery 處理XML--瀏覽器中的XML與JavaScript
來自IBM Developer Works
jQuery與XML
快而強的遍歷系統,華麗麗的選擇器語法,這或許是jQuery 那么流行的原因。當然它還有詳盡的文檔。它主要是用來處理HTML的,但在這里妳會看到如何應用到XML。
使用jQuery進行DOM元素的操作和遍歷
首先確定妳在頁面引用的jQuery庫,才能使用它。然后簡單地使用jQuery()或者它的簡化形式$(), 傳遞一個選擇器作為它的第一個參數。選擇器通常是一個指定了一個或多個元素的字符串。清單20展示了一些基本的jQuery選擇器的使用。
Listing 20. Basic jQuery selectors
<script type="text/javascript"> var allImages = $("img"); // all IMG elements var allPhotos = $("img.photo"); // all IMG elements with class "photo" var curPhoto = $("img#currentPhoto"); // IMG element with id "currentPhoto" </script> |
需要記住的一點是jQuery方法返回的始終是一個jQuery對象。這種對象支持鏈式操作(見清單21)。這一特性在其他JavaScript框架中也是通用的。
Listing 21. Basic jQuery operation with chained method calls
<script type="text/javascript"> $("img").css({"padding":"1px", "border": "1px solid #333"}) .wrap("<div class='img-wrap'/>"); </script> |
上述代碼選中頁面中所有img元素並設置padding和border, 然后用一個帶img-wrap class 的div 來包裹所有這些img.
清單22則展示了jQuery 是如何將前面章節的一個例子進行簡化。
Listing 22. Creating and injecting a DOM node with jQuery
<script type="text/javascript"> alert($("h1:first").html()); // .text() also works and might be better suited here
$("#auth").text("Sign Out");
var $li = $("<li>List Item Text</li>"); // $ is used as var prefix to indicate jQuery object $("ul#nav").append($li); </script> |
使用jQuery 處理XML
之前有提到過傳遞給jQuery $()的第一個參數是一個字符串形式的選擇器。第二個不起眼的參數則允許你設置context,或者開始一個jQuery節點,抑或把當前選擇的元素當作一個根節點來使用。默認jQuery會把Document作為當前的Context, 但更好的做法是把context指定得更詳細更一些,具體到某個特定的元素身上。在進行XML處理時,需要把context設置為XML的根節點(見清單23)。
Listing 23. Retrieving values from an XML document with jQuery
<script type="text/javascript"> // get value of single node (with jQuery) var description = $("description", xmlData).text(); // xmlData was defined in previous section
// get values of nodes from a set (with jQuery) var relatedItems = $("related_item", xmlData); var relatedItemVals = []; $.each(relatedItems, function(i, curItem){ relatedItemVals.push(curItem.text()); }); </script> |
上述代碼使表示變得相當簡潔。通過向jQuery傳遞節點名稱和設置它的context為xmlData,可以很方便地獲取想要的節點。取得元素的值,剛需要一翻周折了。
因為innerHTML 對於非HTML元素不管用,所以就不能使用jQuery的html()方法來獲取節點的值。jQuery 雖然提供了一個跨瀏覽器的方法innerText 來獲取元素的值,但當用來處理XML時在瀏覽器間仍有些差異。比如IE會把包含空值(空格,Tab點位符,換行)的節點給忽略掉,而處理這樣的情況時,FireFox則會把這些節點當作正常節點。為了避免這點不一致性,可以創建一個函數來處理。這個函數里需要用到一些jQuery函數: contents(), filter() 和 trim()。
Listing 24. Cross-browser JavaScript functions for accurate text value retrieval of a node
<script type="text/javascript"> /** * Retrieves non-empty text nodes which are children of passed XML node. * Ignores child nodes and comments. Strings which contain only blank spaces * or only newline characters are ignored as well. * @param node {Object} XML DOM object * @return jQuery collection of text nodes */ function getTextNodes(node){ return $(node).contents().filter(function(){ return ( // text node, or CDATA node ((this.nodeName=="#text" && this.nodeType=="3") || this.nodeType=="4") && // and not empty ($.trim(this.nodeValue.replace("\n","")) !== "") ); }); }
/** * Retrieves (text) node value * @param node {Object} * @return {String} */ function getNodeValue(node){ var textNodes = getTextNodes(node); var textValue = (node && isNodeComment(node)) ? // isNodeComment is defined above node.nodeValue : (textNodes[0]) ? $.trim(textNodes[0].textContent) : ""; return textValue; } </script> |
現在來看看如何設置節點的值(見清單25)。示例代碼中有兩點需要注意:一是設置根結果的文本值會重寫所有子節點。另外就是如果一個節點之前是沒有值的,那么就用 node["textContent"]而不是node.textContent。因為在IE中空節點根本就沒有textContent屬性。
Listing 25. Cross-browser JavaScript function for accurate setting of the text value of a node
<script type="text/javascript"> function setNodeValue(node, value){ var textNodes = getTextNodes(node); if (textNodes.get(0)){ textNodes.get(0).nodeValue = value; } else { node["textContent"] = value; } } </script> |
DOM屬性與jQuery
在之前的一些例子中已經展示了即使用最原始的JavaScript來處理DOM中的屬性也是非常直觀明了的了。同樣地,jQuery也提供了相應的簡化方式。更重要的是,屬性可以用在選擇器中,非常的強大。
Listing 26. Getting and setting DOM element attributes with jQuery
<script type="text/javascript"> var item = $("item[content_id='1']", xmlData); // select item node with content_id attribute set to 1 var pubDate = item.attr("date_published"); // get value of date_published attribute item.attr("archive", "true"); // set new attribute called archive, with value set to true </script> |
從代碼中可以看出,jQuery的attr()方法即可以設置設置也可以返回屬性值。更強大的是jQuery允許在選擇器中提供屬性來返回特定的元素。下如上面的代碼所展示的那樣,我們獲取到了content_id為1的元素。
通過jQuery的Ajax來裝載XML
或許你已經有所了解,Ajax是用JavaScript來異步從服務器獲取XML的一種Web技術。Ajax本身是依賴XMLHttpRequest (XHR) 所提供的API來向服務器發送請求和從服務器獲取響應的。jQuery除了提供強大的用於遍歷和處理DOM元素的方法外,還提供了跨瀏覽器的Ajax支持。也就是說通過Ajax獲取XML簡單得就是調用Ajax的get方法。清單27展示了這樣的例子。
Listing 27. Loading an external XML file with jQuery's Ajax method
<script type="text/javascript"> $.ajax({ type : "GET", url : "/path/to/data.xml", dataType : "xml", success : function(xmlData){ var totalNodes = $('*',xmlData).length; // count XML nodes alert("This XML file has " + totalNodes); }, error : function(){ alert("Could not retrieve XML file."); } }); </script> |
$.ajax()方法有一系列豐富的選項設置,並且可以通過其他一些簡化的變形方式來調用,比如$.getScript()會導入JavaScript腳本並執行,$.getJSON()會獲取JSON數據然后可以在Success回調中使用。當裝載XML文件時,妳需要了解一下Ajax的基本語法。如上面代碼所示,我們設置類型為get,url設置為從"/path/to/data.xml"這個路徑獲取XML文件,然后還指明文件類型為XML。當從服務器獲取了數據后,success 或error中的一個方法會被觸發。本例中,裝載成功的話會彈出窗口顯示所有節點數目。jQuery的星號選擇器表示匹配所有元素。最重要的一點是在回調函數中,第一個參數用來接收從服務器返回的數據。這個參數的名字隨便起,接下來的Context就被設置成了這個返回的數據。
在處理Ajax相關的請求時需要注意跨域問題,出於安全性考慮一般不允許從不同的域獲取文件。所以上述例子中的代碼可能在妳實際的程序中有所不同。
像處理XML一樣處理外部的XHTML
因為XHTML是XML的一個子集,所以像XML一樣處理XHTML是完全沒有問題的。至於為什么妳有處理XHTML的需求是另一回事,但事實是妳確實可以這樣做。比如,導入一個XHTML頁面然后從中解析數據是可行的,雖然我會建議用另外更強健的方法來實現。
盡管之前講述了DOM元素的遍歷和處理,jQuery同時也可以用來處理XML,雖然需要先將XML文件破費周折地裝載進代碼中。本節的內容包含了不同的方法和基本的用於完成XML處理的例子。