轉(zhuǎn)載于:http://hi.baidu.com/leexper/blog/item/1c47f1112c1d3676ca80c4a9.html
一.引言
本文的程序是用java編寫的,使用Jaxp包來解釋XML文檔。本文的適用對(duì)象是理解 XML 基本概念并開始準(zhǔn)備用DOM編寫應(yīng)用程序來操縱 XML文檔 的開發(fā)者。
一.引言
XML 是eXtensible Markup Language的縮寫,它是一種可擴(kuò)展性標(biāo)識(shí)語言, 能夠讓你自己創(chuàng)造標(biāo)識(shí),標(biāo)識(shí)你所表示的內(nèi)容。DOM全稱是Document Object Model(文檔對(duì)象模型),定義了一組與平臺(tái)和語言無關(guān)的接口,以便程序和腳本能夠動(dòng)態(tài)訪問和修改XML文檔內(nèi)容、結(jié)構(gòu)及樣式。XML創(chuàng)建了標(biāo)識(shí),而 DOM的作用就是告訴程序如何操作和顯示這些標(biāo)識(shí)。 |
二.DOM樹結(jié)構(gòu) |
實(shí)際上XML將數(shù)據(jù)組織成為一棵樹,DOM通過解析XML文檔,為XML文檔在邏輯上建立一個(gè)樹模型,樹的節(jié)點(diǎn)是一個(gè)個(gè)的對(duì)象。這樣通過操作這棵樹和這些對(duì)象就可以完成對(duì)XML文檔的操作,為處理文檔的所有方面提供了一個(gè)完美的概念性框架。 |
如下XML文檔: |
<line id=”1”> the <bold>First</bold>line</line> |
DOM的結(jié)構(gòu)表示如下: |
|
由于DOM“一切都是節(jié)點(diǎn)(everything-is-a-node)”,XML樹的每個(gè) Document、Element、Text 、Attr和Comment都是 DOM Node。 |
由 上面例子可知, DOM 實(shí)質(zhì)上是一些節(jié)點(diǎn)的集合。由于文檔中可能包含有不同類型的信息,所以定義了幾種不同類型的節(jié)點(diǎn),如:Document、Element、Text、 Attr 、CDATASection、ProcessingInstruction、Notation 、EntityReference、Entity、DocumentType、DocumentFragment等。 |
在創(chuàng)建XML文件時(shí),如定義如下的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> |
我們很自然想象到能得到如下圖的結(jié)構(gòu),但是這只是數(shù)據(jù)的描述,而不是DOM樹的結(jié)構(gòu)。 |
|
我們可以通過以下的代碼得到上面的XML文檔的根結(jié)點(diǎn)和根結(jié)點(diǎn)下孩子節(jié)點(diǎn)的數(shù)目。 |
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"); |
} |
} |
} |
結(jié)果顯示為: |
![]() |
但 是從上面XML文檔可以看出,students一共只有3個(gè)孩子節(jié)點(diǎn)(包括注釋),但程序得到的結(jié)果確實(shí)有7個(gè)孩子結(jié)點(diǎn)。為什么呢?因?yàn)樵贒OM中節(jié)點(diǎn) 和元素不是等價(jià)的,它的7個(gè)節(jié)點(diǎn)包括:兩個(gè)student元素、注釋及它們周圍的文本節(jié)點(diǎn)。這些文本節(jié)點(diǎn)有可能是回車換行、空格或者退格,假如把這些回車 換行、空格和退格都刪除,那么DOM解釋的時(shí)候就沒有這些文本節(jié)點(diǎn),孩子節(jié)點(diǎn)就真的只有3個(gè)了。下圖是DOM樹的精確描述: |
|
|
三.常見的基本節(jié)點(diǎn)類型:文檔、元素、屬性、文本和注釋 |
XML 中共有12種節(jié)點(diǎn)類型,其中最常見的節(jié)點(diǎn)類型有5種: |
元素:元素是 XML 的基本組成單元。,描述XML的基本信息。 |
屬性:屬性節(jié)點(diǎn)包含關(guān)于元素節(jié)點(diǎn)的信息,通常包含在元素里面,描述元素的屬性。 |
文本:包含許多文本信息或者只是空白。 |
文檔:文檔節(jié)點(diǎn)是整個(gè)文檔中所有其它節(jié)點(diǎn)的父節(jié)點(diǎn)。 |
注釋:注釋是對(duì)相關(guān)的信息進(jìn)行描述、注釋。 |
四.常見的基本方法: |
通過Jaxp包來解釋XML文檔后,對(duì)DOM的節(jié)點(diǎn)對(duì)象的基本操作有: |
appendChild(Node newChild):在本節(jié)點(diǎn)上增加一個(gè)新的孩子到孩子列表的后面。 |
getAttributes():得到本節(jié)點(diǎn)的屬性列表,返回類型為NamedNodeMap。 |
getChildNodes():得到本節(jié)點(diǎn)的孩子列表,返回類型為NodeList。 |
getFirstChild()、getLastChild():得到第一個(gè)和最后一個(gè)孩子節(jié)點(diǎn)。 |
getNextSibling()、getPreviousSibling():得到本節(jié)點(diǎn)的下一個(gè)和前一個(gè)兄弟節(jié)點(diǎn)。 |
getNodeName()、getNodeType()、getNodeValue():得到本節(jié)點(diǎn)的名稱、類型和值。 |
getParentNode():得到本節(jié)點(diǎn)的父親節(jié)點(diǎn)。 |
insertBefore(Node newChild, Node refChild):在本節(jié)點(diǎn)的refChild孩子節(jié)點(diǎn)前插入一個(gè)新的節(jié)點(diǎn)。 |
removeChild(Node oldChild):刪除oldChild孩子節(jié)點(diǎn)。 |
以上列出對(duì)DOM樹操作的一些常用的基本的方法,還有很多其他的方法,讀者可以參考有關(guān)的規(guī)范。 |
五.遞歸遍歷DOM樹 |
DOM樹結(jié)構(gòu)和二叉樹很相似,元素的孩子節(jié)點(diǎn)集合就是該元素的分支,但是屬性節(jié)點(diǎn)不是元素的子節(jié)點(diǎn),它只是描述該元素節(jié)點(diǎn)的一些性質(zhì)而已,屬于元素節(jié)點(diǎn)結(jié)構(gòu)內(nèi)部的一部分。以下是用java編寫的一段遍歷DOM的程序: |
public class RecurDOM(NodeList nodelist) |
{ |
Node node; |
int i; |
if(nodelist.getLength() == 0) |
{ |
// 該節(jié)點(diǎn)沒有子節(jié)點(diǎn)返回 |
return; |
} |
for(i=0;i<nodelist.getLength();i++) |
{ |
node = nodelist.item(i); |
if(node.getNodeType() == Node.ELEMENT_NODE) |
RecurDOM(node.getChildNodes());//遞歸調(diào)用 |
} |
} |
|
六.小結(jié): |
DOM 是一種在瀏覽器內(nèi)編程的模型,同時(shí)也是XML的主要接口,它與語言和平臺(tái)無關(guān),它是基于樹的 API,它把所有的數(shù)據(jù)以父子的節(jié)點(diǎn)層次結(jié)構(gòu)裝入內(nèi)存構(gòu)成一棵樹,這些節(jié)點(diǎn)的類型可以是元素、文本、屬性、注釋或其它。它允許開發(fā)者讀取、創(chuàng)建、刪除和編 輯 XML 數(shù)據(jù)。在這再次強(qiáng)調(diào),DOM的“一切都是節(jié)點(diǎn)(everything-is-a-node)”。 |