在開始使用 DOM 之前,了解它實(shí)際表示什么是值得的。DOM Document 是以層次結(jié)構(gòu)組織起來的節(jié)點(diǎn),或信息片段,的集合。這種層次結(jié)構(gòu)允許開發(fā) 者瀏覽樹來查找特定信息。通常,分析結(jié)構(gòu)需要在完成任何工作之前裝入整個(gè) 文檔并且裝入層次結(jié)構(gòu)。
DOM基礎(chǔ)
在開始使用 DOM 之前,了解它實(shí)際表示什么是值得的。DOM Document 是以層次結(jié)構(gòu)組織起來的節(jié)點(diǎn),或信息片段,的集合。這種層次結(jié)構(gòu)允許開發(fā)者瀏覽樹來查找特定信息。通常,分析結(jié)構(gòu)需要在完成任何工作之前裝入整個(gè)文檔并且裝入層次結(jié)構(gòu)。
由于 DOM 是基于信息的層次結(jié)構(gòu),因此它被稱為是基于樹的。
對(duì)于極其大的文檔,裝入整個(gè)文檔并對(duì)該文檔進(jìn)行解析會(huì)很慢且占用大量資源,所以要用其它方式來處理數(shù)據(jù)。一些基于事件的模型,如 Simple API for XML(SAX),是工作在數(shù)據(jù)流之上,在數(shù)據(jù)流經(jīng)過時(shí)對(duì)其進(jìn)行處理?;谑录?API 消除了在內(nèi)存中構(gòu)建數(shù)據(jù)樹的需要,但它不允許開發(fā)者實(shí)際更改原始文檔中的數(shù)據(jù)。
另一方面,DOM 還提供了一個(gè) API,該 API 允許開發(fā)者為創(chuàng)建應(yīng)用程序而在樹的任何地方添加、編輯、移動(dòng)或除去節(jié)點(diǎn)。
DOM 基本的節(jié)點(diǎn)類型
XML 中最常見的節(jié)點(diǎn)類型:
- Node: DOM 基本的數(shù)據(jù)類型。
- Element: 您將最主要處理的對(duì)象是 Element。
- Attr: 代表一個(gè)元素的屬性。
- Text: 一個(gè) Element 或 Attr 的實(shí)際內(nèi)容。
- Document: 代表整個(gè) XML 文檔。一個(gè) Document 對(duì)象通常也被稱為一棵 DOM 樹。
較不常見的節(jié)點(diǎn)類型:CData、注釋、處理指令和文檔片段:
- CData:“字符數(shù)據(jù)”的縮寫
- 注釋:注釋包含有關(guān)數(shù)據(jù)的信息,通常應(yīng)用程序會(huì)忽略它們。
- 處理指令:PI 是專門針對(duì)應(yīng)用程序的信息。
- 文檔片段:為了形成良好的格式,文檔只能有一個(gè)根元素。有時(shí),必須臨時(shí)創(chuàng)建幾組元素,這些元素不是滿足需求所必要的。
文檔片段類似于這樣:
<item instock="Y" itemid="SA15"> <name>Silver Show Saddle, 16 inch</name> <price>825.00</price> <qty>1</qty> </item> <item instock="N" itemid="C49"> <name>Premium Cinch</name> <price>49.00</price> <qty>1</qty> </item>
|
解析文檔的三步過程
為了使用 XML 文件中的信息,必須解析該文件以創(chuàng)建 Document 對(duì)象。
Document 對(duì)象是一個(gè)接口,所以不能直接實(shí)例化;相反,應(yīng)用程序一般使用 factory。確切的過程隨實(shí)現(xiàn)的不同而不同,但想法是相同的。在示例 JAXP 環(huán)境中,解析文件是一個(gè)三步過程:
- 創(chuàng)建 DocumentBuilderFactory。該對(duì)象將創(chuàng)建 DocumentBuilder。
- 創(chuàng)建 DocumentBuilder。 DocumentBuilder 將實(shí)際進(jìn)行解析以創(chuàng)建 Document 對(duì)象。
- 解析該文件以創(chuàng)建 Document 對(duì)象。
如果需要,在不必更改代碼的情況下,JAXP 允許插進(jìn)不同的解析器。讓我們繼續(xù),開始構(gòu)建應(yīng)用程序。
基本的應(yīng)用程序
從創(chuàng)建基本的應(yīng)用程序,名為 OrderProcessor 的類開始。
import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import java.io.File; import org.w3c.dom.Document; public class OrderProcessor { public static void main (String args[]) { File docFile = new File("orders.xml"); Document doc = null; try { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = dbf.newDocumentBuilder(); doc = db.parse(docFile); } catch (Exception e) { System.out.print("Problem parsing the file."); } } }
|
首先,Java 導(dǎo)入必要的類,然后創(chuàng)建 OrderProcessor 應(yīng)用程序。在本教程中的這個(gè)示例將只處理一個(gè)文件,所以為簡(jiǎn)短起見,該應(yīng)用程序包含對(duì)它的直接引用。
應(yīng)用程序在 try-catch 塊外部定義了 Document 對(duì)象,以便在后面使用該對(duì)象。try-catch 使您能執(zhí)行可能會(huì)拋出異常的一些操作,這樣不會(huì)危及整個(gè)應(yīng)用程序。如果異常拋出,則應(yīng)用程序簡(jiǎn)單地執(zhí)行相應(yīng)的 catch 代碼。
在 try-catch 塊內(nèi)部,應(yīng)用程序創(chuàng)建 DocumentBuilderFactory,然后使用它來創(chuàng)建 DocumentBuilder。最后,DocumentBuilder 解析該文件以創(chuàng)建 Document。
DOM 常用方法
- Document.getDocumentElement()
返回文檔的根(root)元素。 - Node.getFirstChild() and Node.getLastChild()
返回給定 Node 的第一個(gè)子女。 - Node.getNextSibling() and Node.getPreviousSibling()
這些方法返回下一個(gè)或前一個(gè)給定 Node 的同胞。 - Node.getAttribute(attrName)
對(duì)給定的 Node,返回給定名稱的屬性。例如,如果您要獲得名為 id 屬性的對(duì)象,可調(diào)用 getAttribute("id")。
編輯文檔
- 更改節(jié)點(diǎn)數(shù)據(jù)
Node.setNodeValue(elemValue);
|
- 添加節(jié)點(diǎn)
String totalString = new Double(total).toString(); Node totalNode = doc.createTextNode(totalString); //Document 對(duì)象創(chuàng)建新的文本節(jié)點(diǎn),該節(jié)點(diǎn)帶有作為值的 totalString Element totalElement = doc.createElement("total"); //創(chuàng)建新元素 total totalElement.appendChild(totalNode); // 將節(jié)點(diǎn)添加到新的 total 元素。 thisOrder.insertBefore(totalElement, thisOrder.getFirstChild()); //將新元素添加到 Document,指定新的 Node,然后指定新 Node 在 Node 之前
|
- 除去節(jié)點(diǎn)
Node deadNode = thisOrderItem.getParentNode().removeChild(thisOrderItem);
|
- 替換節(jié)點(diǎn)
Element backElement = doc.createElement("backordered"); //創(chuàng)建新元素 backordered Node deadNode = thisOrderItem.getParentNode().replaceChild(backElement,thisOrderItem);
|
- 創(chuàng)建和設(shè)置屬性
Element backElement = doc.createElement("backordered"); //創(chuàng)建新元素 backordered backElement.setAttributeNode(doc.createAttribute("itemid")); //創(chuàng)建新屬性 itemid String itemIdString = thisOrderItem.getAttributeNode("itemid").getNodeValue(); //取得thisOrderItem的屬性itemid的值 backElement.setAttribute("itemid", itemIdString); //設(shè)置backElement的屬性item的值,可以省略createAttribute Node deadNode = thisOrderItem.getParentNode().replaceChild(backElement,thisOrderItem);
|
- 除去屬性
Element thisOrder = (Element)orders.item(orderNum); Element customer = (Element)thisOrder.getElementsByTagName("cusomertid").item(0); customer.removeAttribute("limit"); //去除屬性limit
|
本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)
點(diǎn)擊舉報(bào)。