1. 程式人生 > >物件模型 文件物件模型DOM簡介

物件模型 文件物件模型DOM簡介

學了那麼多,大家肯定在想,我們為什麼在瀏覽器中開啟XML時必須使用樣式單才能看到效果,否則只能看到原始碼那?其實不完全是這樣的,我們現在來一起學習建立一個相應的XML例項,讓它在瀏覽器中顯示你需要的HTML效果。

不過首先我們要學習一下另一個很有用的東東――DOM。

DOM的全稱是Document Object Model,也即文件物件模型。在應用程式中,基於DOM的XML分析器將一個XML文件轉換成一個物件模型的集合(通常稱DOM樹),應用程式正是通過對這個物件模型的操作,來實現對XML文件資料的操作。通過DOM介面,應用程式可以在任何時候訪問XML文件中的任何一部分資料,因此,這種利用DOM介面的機制也被稱作隨機訪問機制。

DOM介面提供了一種通過分層物件模型來訪問XML文件資訊的方式,這些分層物件模型依據XML的文件結構形成了一棵節點樹。無論XML文件中所描述的是什麼型別的資訊,即便是製表資料、專案列表或一個文件,利用DOM所生成的模型都是節點樹的形式。也就是說,DOM強制使用樹模型來訪問XML文件中的資訊。由於XML本質上就是一種分層結構,所以這種描述方法是相當有效的。

對於XML應用開發來說,DOM就是一個物件化的XML資料介面,一個與語言無關、與平臺無關的標準介面規範。它定義了HTML文件和XML文件的邏輯結構,給出了一種訪問和處理HTML文件和XML文件的方法。利用DOM,程式開發人員可以動態地建立文件,遍歷文件結構,新增、修改、刪除文件內容,改變文件的顯示方式等等。可以這樣說,文件代表的是資料,而DOM則代表瞭如何去處理這些資料。無論是在瀏覽器裡還是在瀏覽器外,無論是在伺服器上還是在客戶端,只要有用到XML的地方,就會碰到對DOM的應用。

作為W3C的標準介面規範,目前,DOM由三部分組成,包括:核心(core)、HTML和XML。核心部分是結構化文件比較底層物件的集合,這一部分所定義的物件已經完全可以表達出任何HTML和XML文件中的資料了。HTML介面和XML介面兩部分則是專為操作具體的HTML文件和XML文件所提供的高階介面,使對這兩類檔案的操作更加方便。

目前,DOM有兩個版本,一個是由W3C於1998年8月18日通過的DOM Level 1,另一個則是正在制定過程中的DOM Level 2,W3C已於2000年3月7日通過了DOM Level 2的候選推薦版本。


一、DOM樹

前面我們講過,DOM為我們提供的訪問XML文件資訊的媒介是一種分層物件模型,而這個層次的結構,則是一棵根據XML文件生成的節點樹。

一個XML分析器,在對XML文件進行分析之後,不管這個文件有多簡單或者多複雜,其中的資訊都會被轉化成一棵物件節點樹。在這棵節點樹中,有一個根節點--Document節點,所有其他的節點都是根節點的後代節點。節點樹生成之後,就可以通過DOM介面訪問、修改、新增、刪除、建立樹中的節點和內容。

以客戶聯絡資訊的例子來說明,下面給出一個XML文件片段:

用DOM來表示這段文件,如圖所示:



在這棵文件物件樹中,文件中所有的內容都是用節點來表示的。一個節點又可以包含其他節點,節點本身還可能包含一些資訊,例如節點的名字、節點值、節點型別等。文件中的根實際上也是一個元素,之所以要把它單獨列出來,是因為在XML文件中,所有其他元素都是根元素的後代元素,而且根元素是唯一的,具有其他元素所不具有的某些特徵。

這個例子比較簡單,事實上,DOM中還包含註釋、處理指令、文件型別、實體、實體引用、名稱空間、事件、樣式單等多種物件模型。

文件物件模型利用物件來把文件模型化,這些模型不僅描述了文件的結構,還定義了模型中物件的行為。換句話說,在上面給出的例子裡,圖中的節點不是資料結構,而是物件,物件中包含方法和屬性。在DOM中,物件模型要實現:

· 用來表示、操作文件的介面
· 介面的行為和屬性
· 介面之間的關係以及互操作


二、DOM的四個基本介面

在DOM介面規範中,有四個基本的介面:Document,Node,NodeList以及NamedNodeMap。在這四個基本介面中,Document介面是對文件進行操作的入口,它是從Node介面繼承過來的。Node介面是其他大多數介面的父類,象Documet,Element,Attribute,Text,Comment等介面都是從Node介面繼承過來的。NodeList介面是一個節點的集合,它包含了某個節點中的所有子節點。NamedNodeMap介面也是一個節點的集合,通過該介面,可以建立節點名和節點之間的一一對映關係,從而利用節點名可以直接訪問特定的節點。下面將對這四個介面分別做一些簡單的介紹。

1. Document介面
Document介面代表了整個XML/HTML文件,因此,它是整棵文件樹的根,提供了對文件中的資料進行訪問和操作的入口。

由於元素、文字節點、註釋、處理指令等都不能脫離文件的上下文關係而獨立存在,所以在Document介面提供了建立其他節點物件的方法,通過該方法建立的節點物件都有一個ownerDocument屬性,用來表明當前節點是由誰所建立的以及節點同Document之間的聯絡。

在DOM樹中,Document介面同其他介面之間的關係如下圖所示:


由圖可以看出,Document節點是DOM樹中的根節點,也即對XML文件進行操作的入口節點。通過Docuemt節點,可以訪問到文件中的其他節點,如處理指令、註釋、文件型別以及XML文件的根元素節點等等。另外,從上圖我們還可以看出,在一棵DOM樹中,Document節點可以包含多個處理指令、多個註釋作為其子節點,而文件型別節點和XML文件根元素節點都是唯一的。

關於Document介面的IDL(Interface Definition Language介面定義語言)定義和其中一些比較常用的屬性和方法的詳細介紹在許多參考書都可以找到。

2. Node介面

Node介面在整個DOM樹中具有舉足輕重的地位,DOM介面中有很大一部分介面是從Node介面繼承過來的,例如,Element、Attr、CDATASection等介面,都是從Node繼承過來的。在DOM樹中,Node介面代表了樹中的一個節點。一個典型的Node介面如下圖所示:


如圖所示,Node介面提供了訪問DOM樹中元素內容與資訊的途徑,並給出了對DOM樹中的元素進行遍歷的支援。

· NodeList介面
NodeList介面提供了對節點集合的抽象定義,它並不包含如何實現這個節點集的定義。NodeList用於表示有順序關係的一組節點,比如某個節點的子節點序列。另外,它還出現在一些方法的返回值中,例如GetNodeByName。

在DOM中,NodeList的物件是"live"的,換句話說,對文件的改變,會直接反映到相關的NodeList物件中。例如,如果通過DOM獲得一個NodeList物件,該物件中包含了某個Element節點的所有子節點的集合,那麼,當再通過DOM對Element節點進行操作(新增、刪除、改動節點中的子節點)時,這些改變將會自動地反映到NodeList物件中,而不需DOM應用程式再做其他額外的操作。

NodeList中的每個item都可以通過一個索引來訪問,該索引值從0開始。

· NamedNodeMap介面
實現了NamedNodeMap介面的物件中包含了可以通過名字來訪問的一組節點的集合。不過注意,NamedNodeMap並不是從NodeList繼承過來的,它所包含的節點集中的節點是無序的。儘管這些節點也可以通過索引來進行訪問,但這只是提供了列舉NamedNodeMap中所包含節點的一種簡單方法,並不表明在DOM規範中為NamedNodeMap中的節點規定了一種排列順序。

NamedNodeMap表示的是一組節點和其唯一名字的一一對應關係,這個介面主要用在屬性節點的表示上。
與NodeList相同,在DOM中,NamedNodeMap物件也是"live"的。


三、DOM的簡單應用

1、建立Document物件

通過上面的介紹,我們已經對DOM介面有了部分了解,那麼,這些介面以及介面中的屬性和方法又應該如何使用呢?這正是接下來所要講述的內容。

如前所述,利用DOM,程式開發人員可以動態地建立文件,遍歷文件結構,新增、修改、刪除文件內容等等。在本節中,我們將通過微軟的XML分析器msxml,對DOM介面的這些應用做一詳細的介紹。

首先,我們來講一下一切操作的基礎--建立Document物件。通過建立Document物件,應用程式或者指令碼就得到了對XML文件進行操作的入口。下面給出了使用不同的程式語言建立Document物件的範例。


2、載入XML文件

在Document物件建立之後,我們就得到了對文件進行操作的入口,那麼,建立的這個文件物件是如何同實際的XML文件關聯在一起的呢?說來可笑,在W3C的DOM介面規範中,沒有任何一個地方定義了DOM中的介面物件同實際文件相關聯的方法。因此,不同的XML分析器所提供的載入XML文件的方法也不盡相同。在微軟的msxml中,提供了一個load方法來載入XML文件,建立DOM樹同XML文件之間的關聯。

依舊以聯絡人列表資訊的XML文件.xml為例,可通過下述方式來載入文件:


XML文件被載入後,就在記憶體中形成了一棵DOM樹,如圖所示:


3、遍歷XML文件

現在,我們已經可以通過DOM來建立XML文件物件,並載入XML文件了。對於已經載入的文件,我們要從文件中獲取所需要的內容,這就要求能夠通過DOM樹來訪問樹中的任何一個節點,也就是對DOM樹的遍歷。下面我們依舊以client.xml為例,通過幾個例項來說明如何遍歷DOM樹中的節點。

首先,我們要獲取XML文件的根元素節點,用VBScript語言描述這個操作如下:


該語句的實際含義如下圖黃色箭頭所示。


在得到了文件的根元素節點之後,我們又將如何訪問其他元素呢?以文件中的第二個person元素為例,對該元素節點以及其子節點的訪問可以通過下面的方式來實現:


上述訪問語句執行後,theName的值是"李四"。下圖黃色箭頭給出了這一訪問過程的示意:


在上面的程式碼中,root是文件的根元素節點addressbook節點,personNode和nameNode都是元素型別的節點,textNode是TEXT型別的節點,theName是一個字串。

childNodes是NodeList型別的屬性,item是NodeList介面中Node型別的屬性,通過item可以訪問NodeList節點集合中的任意節點(這兒有一點需要注意,當我們要訪問根元素節點addressbook的第二個person子節點personNode時,我們用的索引引數是"1",這是因為item中的索引引數是從0開始的,如果我們要訪問節點集合中的第一個節點,則應該用item(0)來表示)。

在DOM規範中,要訪問元素節點的文字內容,需要先得到元素節點的TEXT子節點,再通過TEXT節點的屬性獲取文字內容。微軟在實現DOM介面時對DOM進行了部分擴充套件,可以通過元素型別節點的text屬性直接獲得元素中的文字內容。具體實用說明可以參考微軟msdn中的幫助。

上面的例子給出瞭如何訪問DOM樹中的元素節點,對於DOM樹中的屬性節點,訪問方法略有不同,可以通過下面的語句來實現:


上述訪問語句執行後,attrContent的值是"male"。下圖用黃色箭頭標出了這一訪問的過程。


在上面的程式碼中,attr是屬性型別的節點,attributes是NamedNodeMap型別的屬性,getNamedItem是NamedNodeMap介面中的方法。屬性的內容可以通過屬性節點的nodeValue來獲得。

4、新增元素

目前,我們已經能夠通過DOM獲取XML文件中的資訊了。如前所述,通過DOM還可以動態地更改XML文件中的內容。下面我們仍舊使用上面的client.xml文件,通過例項來說明如何更改XML文件中的內容。

假如我們希望在addressbook.xml中,給第一個person元素增添一個字串為"北大方正"的company元素,實現這一新增元素操作的語句如下:


下面給出了新增元素的操作示意圖:


5、刪除元素

現在,我們再把前一小節新增的元素刪除,可通過下面的程式碼實現這一目的:


其中,oldNode中存放的是已被刪除的節點。在刪除某個節點時,以該節點為根的子樹將整個被刪除,因此得到的結果DOM樹恢復原狀。

6、修改元素

元素內容的改變包括元素名稱、元素屬性、元素所包含的文字內容等專案的改變。下面僅就元素所包含的文字內容的改變給出一個範例,其他內容的改變實現方法與此類似。

假如想把張三的電子郵件地址更改為[email protected],通過下列語句就可以實現:


下面給出了修改後的效果:


至此,我們已經把對DOM樹的常用操作做了簡單的介紹。一般說來,支援DOM的XML分析器通常會對DOM做一些擴充套件,這些擴充套件不屬於DOM規範中的標準,但卻給DOM樹的操作帶來了方便,不同的分析器所做的擴充套件也不盡相同,可以通過查詢相關技術支援資料或者幫助來獲取更多的資訊。