轉載于:http://hi.baidu.com/leexper/blog/item/1c47f1112c1d3676ca80c4a9.html
一.引言
本文的程序是用java編寫的,使用Jaxp包來解釋XML文檔。本文的適用對象是理解 XML 基本概念并開始準備用DOM編寫應用程序來操縱 XML文檔 的開發者。
一.引言
XML 是eXtensible Markup Language的縮寫,它是一種可擴展性標識語言, 能夠讓你自己創造標識,標識你所表示的內容。DOM全稱是Document Object Model(文檔對象模型),定義了一組與平臺和語言無關的接口,以便程序和腳本能夠動態訪問和修改XML文檔內容、結構及樣式。XML創建了標識,而 DOM的作用就是告訴程序如何操作和顯示這些標識。 |
二.DOM樹結構 |
實際上XML將數據組織成為一棵樹,DOM通過解析XML文檔,為XML文檔在邏輯上建立一個樹模型,樹的節點是一個個的對象。這樣通過操作這棵樹和這些對象就可以完成對XML文檔的操作,為處理文檔的所有方面提供了一個完美的概念性框架。 |
如下XML文檔: |
<line id=”1”> the <bold>First</bold>line</line> |
DOM的結構表示如下: |
|
由于DOM“一切都是節點(everything-is-a-node)”,XML樹的每個 Document、Element、Text 、Attr和Comment都是 DOM Node。 |
由 上面例子可知, DOM 實質上是一些節點的集合。由于文檔中可能包含有不同類型的信息,所以定義了幾種不同類型的節點,如:Document、Element、Text、 Attr 、CDATASection、ProcessingInstruction、Notation 、EntityReference、Entity、DocumentType、DocumentFragment等。 |
在創建XML文件時,如定義如下的XML文檔: |
<?xml version="1.0" encoding="UTF-8"?> |
<students> |
<!--this is an example--> |
<student> |
<name> |
<first-name>Mike</first-name> |
<last-name>Silver</last-name> |
</name> |
<sex>male</sex> |
<class studentid="15">98211</class> |
<birthday> |
<day>3</day> |
<month>3</month> |
<year>1979</year> |
</birthday> |
</student> |
<student> |
<name> |
<first-name>Ben</first-name> |
<last-name>Silver</last-name> |
</name> |
<sex>male</sex> |
<class studentid="16">98211</class> |
<birthday> |
<day>3</day> |
<month>3</month> |
<year>1980</year> |
</birthday> |
</student> |
</students> |
我們很自然想象到能得到如下圖的結構,但是這只是數據的描述,而不是DOM樹的結構。 |
|
我們可以通過以下的代碼得到上面的XML文檔的根結點和根結點下孩子節點的數目。 |
import javax.xml.parsers.*; |
import org.w3c.dom.*; |
import java.io.File; |
import xmlwriter.XMLProperties; |
public class Xml |
{ |
public static void main(String args[]) |
{ try |
{ File file=new File("links.xml"); |
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); |
DocumentBuilder builder=factory.newDocumentBuilder(); |
Document doc=builder.parse(file); |
doc.normalize(); |
Element theRoot = doc.getDocumentElement(); |
NodeList theList=theRoot.getChildNodes(); |
System.out.println("the students root has "+theList.getLength()+" children"); |
} |
} |
} |
結果顯示為: |
![]() |
但 是從上面XML文檔可以看出,students一共只有3個孩子節點(包括注釋),但程序得到的結果確實有7個孩子結點。為什么呢?因為在DOM中節點 和元素不是等價的,它的7個節點包括:兩個student元素、注釋及它們周圍的文本節點。這些文本節點有可能是回車換行、空格或者退格,假如把這些回車 換行、空格和退格都刪除,那么DOM解釋的時候就沒有這些文本節點,孩子節點就真的只有3個了。下圖是DOM樹的精確描述: |
|
|
三.常見的基本節點類型:文檔、元素、屬性、文本和注釋 |
XML 中共有12種節點類型,其中最常見的節點類型有5種: |
元素:元素是 XML 的基本組成單元。,描述XML的基本信息。 |
屬性:屬性節點包含關于元素節點的信息,通常包含在元素里面,描述元素的屬性。 |
文本:包含許多文本信息或者只是空白。 |
文檔:文檔節點是整個文檔中所有其它節點的父節點。 |
注釋:注釋是對相關的信息進行描述、注釋。 |
四.常見的基本方法: |
通過Jaxp包來解釋XML文檔后,對DOM的節點對象的基本操作有: |
appendChild(Node newChild):在本節點上增加一個新的孩子到孩子列表的后面。 |
getAttributes():得到本節點的屬性列表,返回類型為NamedNodeMap。 |
getChildNodes():得到本節點的孩子列表,返回類型為NodeList。 |
getFirstChild()、getLastChild():得到第一個和最后一個孩子節點。 |
getNextSibling()、getPreviousSibling():得到本節點的下一個和前一個兄弟節點。 |
getNodeName()、getNodeType()、getNodeValue():得到本節點的名稱、類型和值。 |
getParentNode():得到本節點的父親節點。 |
insertBefore(Node newChild, Node refChild):在本節點的refChild孩子節點前插入一個新的節點。 |
removeChild(Node oldChild):刪除oldChild孩子節點。 |
以上列出對DOM樹操作的一些常用的基本的方法,還有很多其他的方法,讀者可以參考有關的規范。 |
五.遞歸遍歷DOM樹 |
DOM樹結構和二叉樹很相似,元素的孩子節點集合就是該元素的分支,但是屬性節點不是元素的子節點,它只是描述該元素節點的一些性質而已,屬于元素節點結構內部的一部分。以下是用java編寫的一段遍歷DOM的程序: |
public class RecurDOM(NodeList nodelist) |
{ |
Node node; |
int i; |
if(nodelist.getLength() == 0) |
{ |
// 該節點沒有子節點返回 |
return; |
} |
for(i=0;i<nodelist.getLength();i++) |
{ |
node = nodelist.item(i); |
if(node.getNodeType() == Node.ELEMENT_NODE) |
RecurDOM(node.getChildNodes());//遞歸調用 |
} |
} |
|
六.小結: |
DOM 是一種在瀏覽器內編程的模型,同時也是XML的主要接口,它與語言和平臺無關,它是基于樹的 API,它把所有的數據以父子的節點層次結構裝入內存構成一棵樹,這些節點的類型可以是元素、文本、屬性、注釋或其它。它允許開發者讀取、創建、刪除和編 輯 XML 數據。在這再次強調,DOM的“一切都是節點(everything-is-a-node)”。 |