第七章DOM接口技術(shù)_第1頁(yè)
第七章DOM接口技術(shù)_第2頁(yè)
第七章DOM接口技術(shù)_第3頁(yè)
第七章DOM接口技術(shù)_第4頁(yè)
第七章DOM接口技術(shù)_第5頁(yè)
已閱讀5頁(yè),還剩27頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、第七章DOM接口技術(shù)主要內(nèi)容Ø DOM概述Ø DOM規(guī)范主要接口Ø JAXP、DOM和解析器Ø JAXP讀取XML文檔信息Ø JAXP編輯XML文檔Ø JAXP生成XML文檔難點(diǎn)Ø JAXP操作XML文檔現(xiàn)在,應(yīng)該開(kāi)始研究XML文檔的結(jié)構(gòu),以及如何利用它描述層次化信息。下面,我們將說(shuō)明如何通過(guò)程序訪(fǎng)問(wèn)XML文檔。其中一種方法是通過(guò)文檔對(duì)象模型(Document Object Model,DOM)。在本章中,我們將介紹文檔對(duì)象模型,并借助幾個(gè)程序?qū)嵗忉屗墓δ堋?.1 什么是文檔對(duì)象模型文檔對(duì)象模型一詞在Web瀏覽器領(lǐng)域并不

2、陌生。窗口、文檔和歷史等對(duì)象都被認(rèn)為是瀏覽器對(duì)象模型的一部分。然而,任何做過(guò)Web開(kāi)發(fā)的人都知道各種瀏覽器實(shí)現(xiàn)這些對(duì)象的方式不盡相同。對(duì)于如何通過(guò)Web訪(fǎng)問(wèn)和操作文檔結(jié)構(gòu)這個(gè)問(wèn)題,為了創(chuàng)建更加標(biāo)準(zhǔn)化的方法, W3C提出了目前的W3C DOM規(guī)范。W3C DOM是一種獨(dú)立于語(yǔ)言和平臺(tái)的定義,即:它定義了構(gòu)成DOM的不同對(duì)象的定義,卻沒(méi)有提供特定的實(shí)現(xiàn),實(shí)際上,它能夠用任何編程語(yǔ)言實(shí)現(xiàn)。例如,為了通過(guò)DOM訪(fǎng)問(wèn)傳統(tǒng)的數(shù)據(jù)存儲(chǔ),可以將DOM實(shí)現(xiàn)為傳統(tǒng)數(shù)據(jù)訪(fǎng)問(wèn)功能之外的一層包裝。利用DOM中的對(duì)象,開(kāi)發(fā)人員可以對(duì)文檔進(jìn)行讀取、搜索、修改、添加和刪除等操作。DOM為文檔導(dǎo)航以及操作HTML和XML文檔的

3、內(nèi)容和結(jié)構(gòu)提供了標(biāo)準(zhǔn)函數(shù)。7.1.1 XML文檔結(jié)構(gòu)剛剛接觸XML的開(kāi)發(fā)人員常常會(huì)認(rèn)為XML的主要目的是為文件中的信息片段命名,使之易于被其他人理解。結(jié)果,這些新手開(kāi)發(fā)的文檔簡(jiǎn)直如同“標(biāo)記湯”無(wú)序的數(shù)據(jù)元素列表與有意義的標(biāo)記名稱(chēng)組合在一起,但是它與普通的文件一樣都將信息置于同一層。<?xml version=”1.0”?><訂單><客戶(hù)>陳紅</客戶(hù)><地址>大學(xué)路100號(hào)<地址><城市>南寧</城市><產(chǎn)品>芒果</產(chǎn)品><數(shù)量>30</數(shù)量><

4、;產(chǎn)品>荔枝</產(chǎn)品><數(shù)量>130</數(shù)量><產(chǎn)品>木瓜</產(chǎn)品><數(shù)量>60</數(shù)量></訂單> 許多開(kāi)發(fā)人員都忽略了XML能夠顯示元素之間的關(guān)系這一特性特別是表示兩個(gè)元素的父子關(guān)系。如果將上述文件改寫(xiě)為以下形式,將產(chǎn)生更好的效果:<?xml version=”1.0”?><訂單><客戶(hù)><姓名>陳紅</姓名><地址>大學(xué)路100號(hào)</地址><城市>南寧</城市></客戶(hù)>

5、;<ITEM><產(chǎn)品>芒果</產(chǎn)品><數(shù)量>30</數(shù)量></ITEM><ITEM><產(chǎn)品>荔枝</產(chǎn)品> <數(shù)量>130</數(shù)量></ITEM><ITEM><產(chǎn)品>木瓜</產(chǎn)品><數(shù)量>60</數(shù)量></ITEM></訂單>此文檔在瀏覽器中的顯示形式如圖7.1所示。圖7.1 XML文檔在IE瀏覽器中顯示效果 在這種形式的文檔中,發(fā)票元素顯然包括四個(gè)子元素。它還簡(jiǎn)化了文

6、檔的搜索如果我們要尋找木瓜的所有訂單,可以查詢(xún)“產(chǎn)品”子元素為“木瓜”的ITEM元素而不必依次查看每個(gè)“產(chǎn)品”元素。 以上文檔結(jié)構(gòu)可以用圖7.2中的節(jié)點(diǎn)樹(shù)表示,它顯示了所有元素以及它們之間的相互關(guān)系。如果要給文本文件中的發(fā)票增加項(xiàng)目,必須讀取文件直至發(fā)票的最后一個(gè)項(xiàng)目的末尾,插入新的項(xiàng)目文本,然后繼續(xù)處理文檔的后續(xù)部分。正如你所料,這種技術(shù)很快會(huì)變得非常棘手,特別是當(dāng)節(jié)點(diǎn)樹(shù)變得越來(lái)越深時(shí)。然而,如果你能夠根據(jù)樹(shù)結(jié)構(gòu)以節(jié)點(diǎn)形式對(duì)文檔進(jìn)行操作,添加項(xiàng)目就輕而易舉了只需創(chuàng)建新的ITEM節(jié)點(diǎn),并將它作為“訂單”節(jié)點(diǎn)的子節(jié)點(diǎn)。訂單客戶(hù)ITEMITEMITEM圖 7.2 文檔分層結(jié)構(gòu)圖 這就是DOM的工作

7、原理。 當(dāng)你使用DOM對(duì)XML文本文件進(jìn)行操作時(shí),它首先要解析文件,將文件分解為獨(dú)立的元素、屬性和注釋等。然后,它以節(jié)點(diǎn)樹(shù)的形式(在內(nèi)存中)創(chuàng)建XML文件的表示。此后,開(kāi)發(fā)人員可以通過(guò)節(jié)點(diǎn)樹(shù)訪(fǎng)問(wèn)文檔的內(nèi)容,并根據(jù)需要修改文檔。 事實(shí)上, DOM執(zhí)行了更進(jìn)一步的操作,它將文檔中的每個(gè)項(xiàng)目看作節(jié)點(diǎn)元素、屬性、注釋、處理指令,甚至構(gòu)成屬性的文本。因此,對(duì)于我們上面的例子, DOM實(shí)際上會(huì)將文檔表示為圖7.3所示的形式。元素:訂單元素:客戶(hù)元素:ITEM元素:ITEM元素:ITEM文檔元素:姓名元素:地址元素:城市元素:產(chǎn)品元素:數(shù)量元素:產(chǎn)品元素:數(shù)量元素:產(chǎn)品元素:數(shù)量文本:陳紅文本:大學(xué)路文本:

8、南寧文本:芒果文本:30文本:荔枝文本:130文本:木瓜文本:60<?xml version=”1.0”?>圖7.3 DOM節(jié)點(diǎn)樹(shù)圖 圖中文檔為根節(jié)點(diǎn),是訪(fǎng)問(wèn)整棵樹(shù)的入口,其子節(jié)點(diǎn)可以是根元素、處理指令、注釋等類(lèi)型的節(jié)點(diǎn)。本圖中根元素為“訂單”,處理指令為<?xml version=”1.0”?>,注釋本例沒(méi)有。一般地講,元素類(lèi)型的節(jié)點(diǎn)可以有的子節(jié)點(diǎn)類(lèi)型為元素類(lèi)型和文本類(lèi)型。本例中根節(jié)點(diǎn)的子節(jié)點(diǎn)為4個(gè)元素類(lèi)型,客戶(hù)和3個(gè)ITEM??蛻?hù)節(jié)點(diǎn)又有三個(gè)元素型子節(jié)點(diǎn)“姓名”、“地址”和“城市”。每個(gè)ITEM節(jié)點(diǎn)包含兩個(gè)元素“產(chǎn)品”和“數(shù)量”。圖中最后一行中的節(jié)點(diǎn)類(lèi)型為文本型的節(jié)

9、點(diǎn)是分析時(shí)需要特別注意的地方,因?yàn)樯圆蛔⒁饩涂赡苷J(rèn)為姓名的值為陳紅而不是將之作為兩個(gè)不同類(lèi)型的節(jié)點(diǎn)。在DOM節(jié)點(diǎn)樹(shù)分析中還有一點(diǎn)需特別注意,有些元素含有屬性,屬性類(lèi)型的節(jié)點(diǎn)也出現(xiàn)在DOM樹(shù)中,它只能和元素類(lèi)型的節(jié)點(diǎn)相關(guān)聯(lián),而且不是作為元素類(lèi)型的子節(jié)點(diǎn)出現(xiàn)的,以和子元素相區(qū)別。5.1.2 DOM規(guī)范 與其他Internet標(biāo)準(zhǔn)一樣, DOM規(guī)范也是由W3C維護(hù)的。W3C提出了兩個(gè)DOM文檔Level 1和Level 2文檔。1. DOM Level 1 Level 1文檔包含兩個(gè)主要部分。第一部分,文檔對(duì)象模型(核心) Level 1定義了用于訪(fǎng)問(wèn)任何結(jié)構(gòu)化文檔的接口,以及用于訪(fǎng)問(wèn)XML文檔的特

10、殊擴(kuò)展。文檔的第二部分描述了DOM針對(duì)HTML的擴(kuò)展,它超出了本書(shū)的討論范圍。 DOM規(guī)范通過(guò)定義數(shù)據(jù)類(lèi)型DOM String描述了DOM如何操作字符串。該數(shù)據(jù)類(lèi)型定義為雙字節(jié)字符集,采用UTF-16編碼機(jī)制進(jìn)行編碼。對(duì)于特定的實(shí)現(xiàn),接口通常被綁定到也采用UTF-16編碼的系統(tǒng)數(shù)據(jù)類(lèi)型,例如: Java的String類(lèi)型。2. DOM Level 2 Level 2規(guī)范不僅包含上述所有對(duì)象,而且新增了以下特征: 支持命名空間正如我們將在第7章中看到的,命名空間用于區(qū)分XML中具有相同名稱(chēng)的離散數(shù)據(jù)元素。它們通常提供返回原始的XML結(jié)構(gòu)文件的鏈接,該文件包含某種格式的元素信息。DOM Level

11、 2將提供查詢(xún)和修改文檔命名空間的機(jī)制。 樣式表DOM Level 2包含樣式表的對(duì)象模型,以及用于查詢(xún)和操作特定文檔的樣式表的方法。 過(guò)濾DOM Level 2新增了用于過(guò)濾XML文檔內(nèi)容的方法。 事件模型DOM Level 2計(jì)劃提供XML的事件模型。 范圍(Range)DOM Level 2包含用于操作大塊文本的函數(shù),它有助于在XML中處理傳統(tǒng)的文檔。3. 理解IDL和綁定 W3C將DOM定位為獨(dú)立于平臺(tái)的,即: W3C指定了特定系統(tǒng)的實(shí)現(xiàn)需要提供哪些方法和屬性,但沒(méi)有詳細(xì)說(shuō)明如何獲得這些實(shí)現(xiàn)。為此, W3C選擇通過(guò)以下幾種方式表達(dá)與DOM的接口:通過(guò)OMG IDL(它是CORBA 2.

12、2規(guī)范的一部分),而CORBA是分布式計(jì)算中廣泛使用的中間件,獨(dú)立于軟件和硬件平臺(tái)?,F(xiàn)在DOM已經(jīng)得到廣泛的支持,比如VBScript、JavaScript、VB、ASP、php和Java等。本書(shū)以Java技術(shù)為例介紹。7.2 DOM對(duì)象 XML DOM 把 XML 文檔視為一種樹(shù)結(jié)構(gòu)。這種樹(shù)結(jié)構(gòu)被稱(chēng)為節(jié)點(diǎn)樹(shù)。可通過(guò)這棵樹(shù)訪(fǎng)問(wèn)所有節(jié)點(diǎn)??梢孕薷幕騽h除它們的內(nèi)容,也可以創(chuàng)建新的元素。W3C DOM僅僅提供了DOM類(lèi)庫(kù)的接口定義,而沒(méi)有提供特定的實(shí)現(xiàn)。編寫(xiě)通過(guò)DOM訪(fǎng)問(wèn)XML文件的軟件時(shí),必須使用特定的DOM實(shí)現(xiàn)。實(shí)現(xiàn)是某種形式的類(lèi)庫(kù),它設(shè)計(jì)為運(yùn)行在特定的硬件和軟件平臺(tái)上,并訪(fǎng)問(wèn)特定的數(shù)據(jù)存儲(chǔ)。下

13、面對(duì)DOM的基本接口做一個(gè)簡(jiǎn)單的介紹。7.2.1 DOM基本接口 在DOM接口規(guī)范中有許多接口,其中最基本的接口為Document, Node, NameNodeMap, NodeList。在這四個(gè)基本接口中Node接口是其它大多數(shù)接口的父接口,Document、Element、Attribute、Text、Comment等接口都繼承自Node接口。Document接口是對(duì)文檔進(jìn)行操作的入口,對(duì)應(yīng)于DOM樹(shù)的根節(jié)點(diǎn)。NodeList接口是節(jié)點(diǎn)的集合,它包含某個(gè)節(jié)點(diǎn)的所有子節(jié)點(diǎn)。NameNodeMap接口也是節(jié)點(diǎn)的集合,通過(guò)該接口可以建立節(jié)點(diǎn)名和節(jié)點(diǎn)之間的一一映射關(guān)系,從而利用節(jié)點(diǎn)名可以直接訪(fǎng)問(wèn)

14、特定節(jié)點(diǎn),常用于某元素節(jié)點(diǎn)的所有屬性的操作。下面對(duì)這四個(gè)接口分別做一些介紹。1.Document接口Document接口代表了整個(gè)XML/HTML文檔,因此,它是整棵文檔樹(shù)的根,提供了對(duì)文檔中的數(shù)據(jù)進(jìn)行訪(fǎng)問(wèn)和操作的入口。由于元素、文本節(jié)點(diǎn)、注釋、處理指令等都不能脫離文檔的上下文關(guān)系而獨(dú)立存在,所以在Document接口提供了創(chuàng)建其他節(jié)點(diǎn)對(duì)象的方法,通過(guò)該方法創(chuàng)建的節(jié)點(diǎn)對(duì)象都有一個(gè)ownerDocument屬性,用來(lái)表明當(dāng)前節(jié)點(diǎn)是由誰(shuí)所創(chuàng)建的以及節(jié)點(diǎn)同Document之間的聯(lián)系。 Document節(jié)點(diǎn)是DOM樹(shù)中的根節(jié)點(diǎn),也即對(duì)XML文檔進(jìn)行操作的入口節(jié)點(diǎn)。通過(guò)Docuemt節(jié)點(diǎn),可以訪(fǎng)問(wèn)到文檔

15、中的其他節(jié)點(diǎn),如處理指令、注釋、文檔類(lèi)型以及XML文檔的根元素節(jié)點(diǎn)等等。另外,在一棵DOM樹(shù)中,Document節(jié)點(diǎn)可以包含多個(gè)處理指令、多個(gè)注釋作為其子節(jié)點(diǎn),而文檔類(lèi)型節(jié)點(diǎn)和XML文檔根元素節(jié)點(diǎn)都是唯一的。2.Node接口Node接口在整個(gè)DOM樹(shù)中具有舉足輕重的地位,DOM對(duì)象模型接口中有很大一部分接口是從Node接口繼承過(guò)來(lái)的,例如,Element、Attr、CDATASection等接口,都是從Node繼承過(guò)來(lái)的。在DOM樹(shù)中,Node接口代表了樹(shù)中的一個(gè)節(jié)點(diǎn)。Node接口提供了訪(fǎng)問(wèn)DOM樹(shù)中元素內(nèi)容與信息的途徑,并給出了對(duì)DOM樹(shù)中的元素進(jìn)行遍歷的支持。3.NodeList接口Nod

16、eList接口提供了對(duì)節(jié)點(diǎn)集合的抽象定義,它并不包含如何實(shí)現(xiàn)這個(gè)節(jié)點(diǎn)集的定義。NodeList用于表示有順序關(guān)系的一組節(jié)點(diǎn),比如某個(gè)節(jié)點(diǎn)的子節(jié)點(diǎn)序列。另外,它還出現(xiàn)在一些方法的返回值中,例如GetNodeByName。在DOM對(duì)象模型中,NodeList的對(duì)象是"live"的,換句話(huà)說(shuō),對(duì)文檔的改變,會(huì)直接反映到相關(guān)的NodeList對(duì)象中。例如,如果通過(guò)DOM獲得一個(gè)NodeList對(duì)象,該對(duì)象中包含了某個(gè)Element節(jié)點(diǎn)的所有子節(jié)點(diǎn)的集合,那么,當(dāng)再通過(guò)DOM對(duì)Element節(jié)點(diǎn)進(jìn)行操作(添加、刪除、改動(dòng)節(jié)點(diǎn)中的子節(jié)點(diǎn))時(shí),這些改變將會(huì)自動(dòng)地反映到NodeList對(duì)象

17、中,而不需DOM對(duì)象模型應(yīng)用程序再做其他額外的操作。NodeList中的每個(gè)item都可以通過(guò)一個(gè)索引來(lái)訪(fǎng)問(wèn),該索引值從0開(kāi)始。4.NamedNodeMap接口實(shí)現(xiàn)了NamedNodeMap接口的對(duì)象中包含了可以通過(guò)名字來(lái)訪(fǎng)問(wèn)的一組節(jié)點(diǎn)的集合。不過(guò)注意,NamedNodeMap并不是從NodeList繼承過(guò)來(lái)的,它所包含的節(jié)點(diǎn)集中的節(jié)點(diǎn)是無(wú)序的。盡管這些節(jié)點(diǎn)也可以通過(guò)索引來(lái)進(jìn)行訪(fǎng)問(wèn),但這只是提供了枚舉NamedNodeMap中所包含節(jié)點(diǎn)的一種簡(jiǎn)單方法,并不表明在DOM對(duì)象模型規(guī)范中為NamedNodeMap中的節(jié)點(diǎn)規(guī)定了一種排列順序。NamedNodeMap表示的是一組節(jié)點(diǎn)和其唯一名字的一一對(duì)

18、應(yīng)關(guān)系,這個(gè)接口主要用在屬性節(jié)點(diǎn)的表示上。與NodeList相同,在DOM中,NamedNodeMap對(duì)象也是"live"的。除上面的四個(gè)基本接口,常用的接口還有Element接口、Text接口、CDATASection接口、Attr接口等。 其中Element接口繼承自Node接口,表示XML或HTML文檔中的一個(gè)元素。元素可能與有與之相關(guān)的屬性,由于Element繼承Node,所以可以使用Node接口屬性attributes來(lái)獲得元素所有屬性的集合。Element接口上有通過(guò)名稱(chēng)獲得Attr對(duì)象或?qū)傩缘姆椒?。在XML中,應(yīng)該獲得Attr對(duì)象來(lái)檢查表示屬性值的可能相當(dāng)復(fù)雜

19、的子樹(shù)。 Text接口繼承CharacterData,并且表示Element或Attr的文本內(nèi)容。如果元素的內(nèi)容中沒(méi)有標(biāo)記,則文本包含在實(shí)現(xiàn)Text接口的單個(gè)對(duì)象中,此接口是該元素的唯一的孩子。如果有標(biāo)記,則將它解析為信息項(xiàng)(元素、注釋等)和組成該元素的子元素列表的Text節(jié)點(diǎn)。7.3 Java處理XML概述 XML文件是一個(gè)數(shù)據(jù)載體,也是程序之間進(jìn)行溝通的方式,在程序設(shè)計(jì)中占有著重要地位。對(duì)文件的操作可以歸結(jié)為對(duì)XML文件的讀入、處理和保存等三個(gè)基本技術(shù)。處理XML文件,需要一個(gè)XML解析器,解析器的作用在于為應(yīng)用程序提供現(xiàn)成的讀寫(xiě)、維護(hù)XML數(shù)據(jù)文件的途徑。如果沒(méi)有XML解析器,程序員只能

20、將XML文件當(dāng)作文本來(lái)處理,需要做很多底層程序設(shè)計(jì)工作,例如,從文件查找標(biāo)記、識(shí)別標(biāo)記名稱(chēng)等。由于XML解析器的存在,才將程序員從繁復(fù)的底層工作中解放出來(lái),進(jìn)而將精力集中到數(shù)據(jù)使用的算法上,而不是數(shù)據(jù)讀寫(xiě)的細(xì)節(jié)。圖7.4演示了XML解析器在程序開(kāi)發(fā)中的作用。XML文件XML解析器應(yīng)用程序 圖7.4 解析器和應(yīng)用程序關(guān)系示意圖 解析器在XML數(shù)據(jù)操作中起著重要作用,在XML規(guī)范發(fā)布之初,很多機(jī)構(gòu)和個(gè)人都發(fā)布了自己的XML解析器。不同的解析器往往具有不同的操作接口,為了規(guī)范XML解析器的操作接口,W3C提出了DOM操作規(guī)范。此外還有一些接口,雖然不是W3C提出,但由于使用的人員眾多,從而形成事實(shí)標(biāo)

21、準(zhǔn),SAX就是其中一種。目前,SAX也是被W3C認(rèn)可的標(biāo)準(zhǔn)。還有一些解析器,雖然沒(méi)有形成統(tǒng)一標(biāo)準(zhǔn),但由于使用群體十分眾多,并且一直在一些領(lǐng)域使用,所以長(zhǎng)時(shí)間存在。JDOM和DOM4J就是這種類(lèi)型的軟件模塊??傮w上,接口代表操作方法,DOM SAX只是規(guī)范接口的標(biāo)準(zhǔn),而不是一種軟件,它們和解析器間的關(guān)系,如圖7.5所示(其中,小圓圈代表接口,它是XML分析器向外界提供服務(wù)的標(biāo)準(zhǔn))。XML文件XML解析器應(yīng)用程序 圖7.5 解析器和標(biāo)準(zhǔn)接口之間的關(guān)系7.3.1 Java處理XML文件的接口對(duì)XML文件進(jìn)行維護(hù)和操作的接口,目前存在兩類(lèi)標(biāo)準(zhǔn):DOM和SAX。前者將XML文件當(dāng)作整體來(lái)處理;后者將XM

22、L文件當(dāng)作數(shù)據(jù)流來(lái)處理。除此之外,還有一些非標(biāo)準(zhǔn)的XML接口,例如,jDOM、DOM4j等。這些接口和標(biāo)準(zhǔn)的DOM不兼容,但由于其易用性,在Java開(kāi)發(fā)中有著十分廣泛的應(yīng)用。1、 DOM標(biāo)準(zhǔn)DOM是一種操作XML數(shù)據(jù)文件最廣泛的標(biāo)準(zhǔn),獨(dú)立于特定語(yǔ)言和平臺(tái)。DOM只是用來(lái)規(guī)范軟件的,而不是一種具體軟件。目前,很多XML解析器都實(shí)現(xiàn)DOM接口標(biāo)準(zhǔn)。DOM標(biāo)準(zhǔn)最基本的思想是將整個(gè)XML數(shù)據(jù)文件加載入內(nèi)存,并在內(nèi)存中解析成一棵樹(shù)形對(duì)象,程序通過(guò)DOM接口可以自由操作該樹(shù)對(duì)象。因而,基于DOM的處理器對(duì)內(nèi)存要求比較高,但其速度相對(duì)較快。2、 SAX標(biāo)準(zhǔn)SAX標(biāo)準(zhǔn)是由一家公司推出的操作XML數(shù)據(jù)文件的方法

23、,目前已經(jīng)成為一個(gè)標(biāo)準(zhǔn)。該接口以流的方式操作XML數(shù)據(jù)文件,由于是讀一部分?jǐn)?shù)據(jù),再處理一部分?jǐn)?shù)據(jù),所以對(duì)系統(tǒng)的內(nèi)存要求不高。該接口通常是基于事件的,其將XML數(shù)據(jù)文件中不同的內(nèi)容歸類(lèi)為不同對(duì)象。當(dāng)SAX處理器分析到不同的對(duì)象時(shí),就產(chǎn)生不同的事件,進(jìn)而調(diào)用不同的事件處理器。3、 JAXP規(guī)范JAXP是Sun公司提出的一種Java操作XML數(shù)據(jù)文件的標(biāo)準(zhǔn),目前被很多Java XML解析器支持。JAXP的作用是在Java應(yīng)用程序和具體解析器之間提供一個(gè)統(tǒng)一編程接口,從而提高Java應(yīng)用程序的可移植性。JAXP本身不是解析器,也不能替代標(biāo)準(zhǔn)的DOM和SAX接口,但其規(guī)范了Java應(yīng)用程序獲取DOM或S

24、AX接口的方式,規(guī)范了Java應(yīng)用程序加載XML解析器的方式。圖7.6展示了JAXP和DOM SAX以及XML解析器之間的關(guān)系。DOM/SAXXML文件XML解析器1應(yīng)用程序XML解析器2XML解析器3 JAXP 圖7.6 JAXP和解析器以及DOM和SAX關(guān)系示意圖 JAXP本身只是一個(gè)接口框架,它的正確使用需要有XML解析器JDK1.5之后,采用Xerces為默認(rèn)的解析器,提供了JAXP的默認(rèn)實(shí)現(xiàn)。但這種設(shè)置可以通過(guò)修改系統(tǒng)屬性而改變。7.3.2 Java常用的解析器XML解析器的作用在于為應(yīng)用程序提供操作XML數(shù)據(jù)的調(diào)用服務(wù)。目前市場(chǎng)上流通許多XML解析器,其中以Apache開(kāi)發(fā)組織維護(hù)

25、的開(kāi)源XML解析器應(yīng)用面最廣。下面對(duì)各種解析器的特點(diǎn)作簡(jiǎn)單介紹。1、 Crimson解析器Crimson解析器是比較有名的解析器,目前由Apache開(kāi)發(fā)組織維護(hù),最新版本為Crimson1.1。Crimson項(xiàng)目起源于Sun公司的ProjectX項(xiàng)目。后來(lái)該項(xiàng)目由Apache開(kāi)發(fā)組織,Crimson就是在該項(xiàng)目基礎(chǔ)上發(fā)展起來(lái)的。目前,Crimson已經(jīng)停止開(kāi)發(fā)新版本,最新版本Crimson1.1是2001年、2002年左右的產(chǎn)品。Crimson1.1支持XML規(guī)范1.0、JAXP接口、SAX2.0、SAX2.0 Extensions 1.0、DOM Level 2等規(guī)范。JDK1.4的XML默

26、認(rèn)實(shí)現(xiàn)采用的就是Crimson,但是新版的JDK中,這種情況已經(jīng)發(fā)生了變化,原因在于Crimson不是一種性能很好的XML解析器。2、 Xerces解析器Xerces是一個(gè)和Crimson歷史同樣悠久的XML解析器,目前由Apache開(kāi)發(fā)組織的Xerces項(xiàng)目組維護(hù)。該項(xiàng)目起源于IBM給Apache開(kāi)發(fā)組織的XML4J項(xiàng)目。目前,最新版 本是Xerces-J2.11.0。從JDK1.5以后,Xerces就成了JDK的XML默認(rèn)實(shí)現(xiàn)。 Xerces-J2.11.0支持XML規(guī)范1.0、1.1;DOM levels 1, 2, 3; SAX 1 , 2, Namespaces, and W3C X

27、ML Schema。它是一個(gè)無(wú)論從效率,還是從界面友好性都是十分成功的XML解析器。3、 Xalan解析器Xalan嚴(yán)格意義上不是一個(gè)XML解析器,而是XSLT轉(zhuǎn)換器。目前由由Apache開(kāi)發(fā)組織負(fù)責(zé)維護(hù)。以前Xalan是作為Apache開(kāi)發(fā)組織XML項(xiàng)目組中的一個(gè)子項(xiàng)目而存在,現(xiàn)在為了突出其在XSLT和XPATH方面的重要性,已經(jīng)分出XML項(xiàng)目組,成為一個(gè)獨(dú)立的項(xiàng)目組,其最新版本為Xalan-J2.7.1。Xalan-Java實(shí)現(xiàn)了JAXP1.3的轉(zhuǎn)換接口,同時(shí)實(shí)現(xiàn)了JAXP1.3的XPATH。Xalan-Java建立在SAX2.0和DOM Level 3之上。通常需要綁定一個(gè)XML解析器使

28、用。4、 JDOM解析器JDOM嚴(yán)格意義上不是一個(gè)獨(dú)立的解析器,而是在JAXP和Xerces基礎(chǔ)上開(kāi)發(fā)的一個(gè)非標(biāo)準(zhǔn)的操作XML數(shù)據(jù)文件的XML模塊。JDOM提供了以DOM思想操作XML數(shù)據(jù)文件的方式,但和標(biāo)準(zhǔn)的DOM并不兼容。盡管如此,由于其開(kāi)發(fā)接口簡(jiǎn)單等原因,在Java開(kāi)發(fā)領(lǐng)域有著廣泛的用戶(hù)群體。7.3.3 使用JAXP操作XML數(shù)據(jù)XML標(biāo)準(zhǔn)接口規(guī)定了應(yīng)用程序通過(guò)XML解析器操作XML數(shù)據(jù)的方式,但并沒(méi)有規(guī)定Java應(yīng)用程序或取解析器對(duì)象的方式。多數(shù)XML解析器在遵守XML標(biāo)準(zhǔn)的同時(shí),提供了各式各樣的解析器對(duì)象的獲取和調(diào)用方式,影響了Java程序在該方面的可移植性。JAXP的存在就是為了在

29、該方面形成統(tǒng)一,規(guī)定了Java應(yīng)用程序獲得解析器對(duì)象的行為,其作用是將Java應(yīng)用程序和具體的XML解析器隔離開(kāi),圖7.7演示了JAXP在XML分析器與應(yīng)用程序之間的關(guān)系。XML文件XML解析器應(yīng)用程序 JAXP 圖7.7 JAXP在應(yīng)用程序操作解析器過(guò)程中的作用當(dāng)應(yīng)用程序請(qǐng)求XML解析器時(shí),JAXP會(huì)根據(jù)JRE LIB目錄下的配置文件內(nèi)容選擇相應(yīng)的解析器,并構(gòu)造相應(yīng)對(duì)象返回給Java應(yīng)用程序。JAXP中比較核心的類(lèi)有如下幾個(gè):(1) DocumentBuilder(2) DocumentBuilderFactory(3) SAXParser(4) SAXParserFactory本章只介紹利

30、用JAXP進(jìn)行DOM接口的操作,SAX接口下一章介紹。7.4 利用DOM讀取XML文檔信息7.4.1 XML文檔遍歷首先,創(chuàng)建一個(gè)XML文檔,打開(kāi)記事本輸入下面的代碼,如例7-1所示。例7-1<?xml version="1.0" ?><圖書(shū)信息><圖書(shū) isbn="7-111-10288-6"><書(shū)名>C#技術(shù)內(nèi)幕</書(shū)名><作者>Joseph Mayo</作者><售價(jià)>59.00</售價(jià)></圖書(shū)><圖書(shū) isbn="

31、;7-5084-1152-8/TP.456"><書(shū)名>JAVA 2網(wǎng)絡(luò)協(xié)議內(nèi)幕</書(shū)名><作者>AI Williams</作者><售價(jià)>48.00</售價(jià)></圖書(shū)><圖書(shū) isbn="7-121-02807-7"><書(shū)名>Eclipse完全手冊(cè)</書(shū)名><作者>周競(jìng)濤</作者><售價(jià)>55.00</售價(jià)></圖書(shū)><圖書(shū)信息>將文件保存,文件名example1.xml

32、。其次,創(chuàng)建Java文件,打開(kāi)記事本,在里面輸入下面代碼,如下列7-2所示。例7-2import org.w3c.dom.*;import javax.xml.parsers.*;import java.io.*;public class traveler public static void main(String args) try DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance(); DocumentBuilder builder=factory.newDocumentBuilder(); Documen

33、t document=builder.parse(new File("example1.xml"); Element root=document.getDocumentElement(); String rooName=root.getNodeName(); System.out.println("XML文件根結(jié)點(diǎn)的名稱(chēng)為:"+rooName); NodeList nodelist=document.getElementsByTagName("圖書(shū)"); int size=nodelist.getLength(); for(int i

34、=0;i<size;i+) Node node=nodelist.item(i); String name=node.getNodeName(); String content=node.getTextContent(); System.out.println(name); System.out.println(""+content); catch(Exception e) System.out.println(e); 將該文件保存,文件名為traveler.java。編譯后執(zhí)行該文件,結(jié)果顯示如圖7.8所示。圖7.8 遍歷XML文檔結(jié)果圖在此例中,首先引入Java文

35、件在運(yùn)行的時(shí)候所需要加載的三個(gè)包:W3C DOM定義的規(guī)范的接口、獲取XML文檔對(duì)象的包、Java讀取文件的時(shí)候需加載的包。在mian方法中,DocumentBuilderFactory是一個(gè)抽象類(lèi),其主要作用是定義工廠(chǎng)API,使應(yīng)用程序能夠從XML文檔獲得生成DOM對(duì)象樹(shù)的解析器。DocumentBuilder定義API,使其從XML文檔中獲取DOM文檔實(shí)例。使用此類(lèi),應(yīng)用程序可以從XML中獲取一個(gè)Document對(duì)象,之后開(kāi)始解析XML文檔。具體“DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();”這句表

36、示創(chuàng)建一個(gè)工廠(chǎng)factory?!癉ocumentBuilder builder=factory.newDocumentBuilder();”表示創(chuàng)建一個(gè)文檔建設(shè)者?!癉ocument document=builder.parse(new File("example1.xml");”表示由XML文檔“example1.xml”生成一個(gè)Document對(duì)象,對(duì)文檔的一切操作從此開(kāi)始。當(dāng)獲得XML文檔的入口之后,通過(guò)getDocumentElement()方法獲得文檔的根元素對(duì)象,進(jìn)而通過(guò)getNodeName()方法獲得根元素名稱(chēng)。本例的目標(biāo)是遍歷元素的內(nèi)容,這要訪(fǎng)問(wèn)根元素的所

37、有子元素,用到NodeList對(duì)象,即節(jié)點(diǎn)集合。本例中通過(guò)“document.getElementsByTagName("圖書(shū)");”實(shí)現(xiàn)。接下來(lái)的內(nèi)容相對(duì)簡(jiǎn)單,在集合中作循環(huán),依次取出每一個(gè)子元素“圖書(shū)”查看數(shù)據(jù)。循環(huán)中所用到方法,.item(i)獲取集合中的第i個(gè)節(jié)點(diǎn)(以0為起始),.getNodeName()返回節(jié)點(diǎn)的名稱(chēng),getTextContent()返回文本數(shù)據(jù)。7.4.2 Element節(jié)點(diǎn)的操作Element接口是十分重要的接口,該接口被實(shí)例化后,會(huì)對(duì)應(yīng)節(jié)點(diǎn)樹(shù)上的元素類(lèi)型的節(jié)點(diǎn)。這樣的節(jié)點(diǎn)使用getNodeType()方法測(cè)試,返回值為Node.ELEMEN

38、T_NODE。Element節(jié)點(diǎn)具備一些常用方法獲取相關(guān)信息。getNodeName()獲取節(jié)點(diǎn)的名稱(chēng),此處指XML中的標(biāo)記名稱(chēng);getAttribute(String name)返回該節(jié)點(diǎn)對(duì)應(yīng)的名稱(chēng)為name的屬性值。下面通過(guò)一個(gè)實(shí)例講解。打開(kāi)記事本,在其中輸入如下代碼,如下例7-3所示。例7-3import org.w3c.dom.*;import javax.xml.parsers.*;import java.io.*;public class element_do public static void main(String args) try DocumentBuilderFacto

39、ry factory=DocumentBuilderFactory.newInstance(); DocumentBuilder builder=factory.newDocumentBuilder(); Document document=builder.parse(new File("example1.xml"); Element root=document.getDocumentElement(); String rooName=root.getNodeName(); System.out.println("XML文件根結(jié)點(diǎn)的名稱(chēng)為:"+rooNa

40、me); NodeList nodelist=root.getChildNodes(); int size=nodelist.getLength(); for(int i=0;i<size;i+) Node node=nodelist.item(i); if(node.getNodeType()=Node.ELEMENT_NODE) Element elementNode=(Element)node; String name=elementNode.getNodeName(); String id=elementNode.getAttribute("isbn"); S

41、tring content=elementNode.getTextContent(); System.out.println(name+"n"+id+"n"+content+"n"); catch(Exception e) System.out.println(e); 將該文件保存為element_do.java。編譯執(zhí)行后得到的結(jié)果如圖7.9所示。該例主要說(shuō)明Element節(jié)點(diǎn)的用法。獲取根元素之后,使用了方法getChildNodes()獲取根節(jié)點(diǎn)的子節(jié)點(diǎn),得到的事一個(gè)節(jié)點(diǎn)集合。而Element的子節(jié)點(diǎn)不一定是Element節(jié)點(diǎn),

42、有可能是Text節(jié)點(diǎn)、ProcessInstruction節(jié)點(diǎn)和CharacterData節(jié)點(diǎn)等。所以對(duì)于集合中的每一個(gè)節(jié)點(diǎn)首先判斷其是否為Element節(jié)點(diǎn)。如果是,進(jìn)行強(qiáng)制類(lèi)型轉(zhuǎn)換(Element elementNode=(Element)node;)。只有這樣,Element節(jié)點(diǎn)的特別方法才可以使用。本例中輸出了每一個(gè)圖書(shū)節(jié)點(diǎn)的名稱(chēng)、屬性值和文本內(nèi)容(子元素文本內(nèi)容)。圖7.9 Element節(jié)點(diǎn)操作結(jié)果圖7.4.2 DTD相關(guān)信息 一個(gè)規(guī)范的XML文件,在裝入內(nèi)存中的時(shí)候,會(huì)被封裝成一個(gè)Document節(jié)點(diǎn),或?yàn)镈OM節(jié)點(diǎn)樹(shù)。在XML文件存在關(guān)聯(lián)的DTD時(shí),Document節(jié)點(diǎn)有兩個(gè)節(jié)

43、點(diǎn):Element節(jié)點(diǎn)、DocumentType節(jié)點(diǎn)。Element節(jié)點(diǎn)對(duì)應(yīng)根元素;DocumentType節(jié)點(diǎn)對(duì)應(yīng)DTD文件。通過(guò)Document節(jié)點(diǎn)的getDoctype()返回當(dāng)前節(jié)點(diǎn)的DocumentType子節(jié)點(diǎn)。下面通過(guò)實(shí)例說(shuō)明讀取有關(guān)DTD信息使用。首先準(zhǔn)備XML文檔內(nèi)容,打開(kāi)記事本,輸入如下內(nèi)容。<?xml version="1.0" encoding="utf-8" ?><!DOCTYPE HXUCC PUBLIC "-/ISO77/hebei/forXML/ch" "wanghong.d

44、td" <!ELEMENT HXUCC ANY> <!ELEMENT YEAR (#PCDATA)> ><HXUCC> &chen; <YEAR>2010</YEAR> <DEPARTMENT> <DEPARTMENT_NAME>network lab</DEPARTMENT_NAME> </DEPARTMENT>&kkk; <DEPARTMENT> <DEPARTMENT_NAME>room</DEPARTMENT_NAME

45、> </DEPARTMENT></HXUCC>將文件保存為example2.xml。然后準(zhǔn)備DTD內(nèi)容,在記事本中,輸入如下內(nèi)容<?xml version="1.0" encoding="gb2312"?><!ENTITY chen "河西大學(xué)計(jì)算中心" ><!ENTITY kkk SYSTEM "kk.xml"><!ELEMENT DEPARTMENT (DEPARTMENT_NAME)><!ELEMENT DEPARTMENT_

46、NAME (#PCDATA)>將文件保存為wanghong.dtd。再次準(zhǔn)備實(shí)體文件如下<poem>This is a example of entity!</poem>將其存為kk.xml。最后,準(zhǔn)備Java程序,在記事本中輸入如下內(nèi)容。import org.w3c.dom.*;import javax.xml.parsers.*;import java.io.*;public class do_dtd public static void main(String args) try DocumentBuilderFactory factory=Document

47、BuilderFactory.newInstance(); DocumentBuilder builder=factory.newDocumentBuilder(); Document document=builder.parse(new File("example2.xml"); DocumentType doctype=document.getDoctype(); String DTDName=doctype.getName(); System.out.println("DTD的名字:" +DTDName); String publicId=doct

48、ype.getPublicId(); System.out.println("PUBLIC的標(biāo)識(shí):" +publicId); String systemId=doctype.getSystemId(); System.out.println("systemId的標(biāo)識(shí):" +systemId); String internalDTD=doctype.getInternalSubset(); System.out.println("內(nèi)部DTD:" +internalDTD); NamedNodeMap map=doctype.getEnt

49、ities(); for(int i=0;i<map.getLength();i+) Entity node=(Entity)map.item(i); String encoding=node.getInputEncoding(); String content=node.getTextContent(); System.out.println(encoding); System.out.println(content); catch(Exception e) System.out.println(e); 將文件存為do_dtd.java,編譯后執(zhí)行該文件,其執(zhí)行結(jié)果如圖7.10所示。圖

50、7.10 讀取DTD信息結(jié)構(gòu)圖在該例中,首先通過(guò)“DocumentType doctype=document.getDoctype();”獲得DTD節(jié)點(diǎn)的對(duì)象doctype,然后通過(guò)該節(jié)點(diǎn)的幾個(gè)方法獲得DTD的相關(guān)信息。其中g(shù)etName()獲取根元素名稱(chēng);getPublicId()獲取外部DTD的公共標(biāo)識(shí);getSystemId()獲取外部DTD的系統(tǒng)標(biāo)識(shí);getInternalSubset()獲取內(nèi)部DTD的內(nèi)容。程序的最后一部分是獲取實(shí)體的內(nèi)容。語(yǔ)句“NamedNodeMap map=doctype.getEntities();”將DTD中定義的實(shí)體封裝到一個(gè)節(jié)點(diǎn)集合里,此中節(jié)點(diǎn)沒(méi)有順序

51、關(guān)系。接下來(lái)的循環(huán)結(jié)構(gòu)從集合中取出每一個(gè)實(shí)體進(jìn)行處理。在每一步的處理過(guò)程中都是輸出實(shí)體的編碼(通過(guò)getInputEncoding())和內(nèi)容(通過(guò)getTextContent()),當(dāng)然只有外部實(shí)體才有返回的結(jié)果,內(nèi)部實(shí)體沒(méi)有。本例設(shè)定了一個(gè)內(nèi)部實(shí)體和一個(gè)外部實(shí)體。7.4.3 Attr節(jié)點(diǎn)操作 Attr節(jié)點(diǎn)是一個(gè)相當(dāng)特殊的節(jié)點(diǎn),它對(duì)應(yīng)于XML文檔中元素的屬性。在XML文件中的元素可以包含子元素、文本數(shù)據(jù)和屬性。其中子元素對(duì)應(yīng)Element型的節(jié)點(diǎn),文本數(shù)據(jù)對(duì)應(yīng)Text型的節(jié)點(diǎn),這兩種節(jié)點(diǎn)都是節(jié)點(diǎn)樹(shù)中Element節(jié)點(diǎn)的子節(jié)點(diǎn)。而屬性對(duì)應(yīng)的Attr節(jié)點(diǎn)不是作為Element的子節(jié)點(diǎn)出現(xiàn)的,也就

52、是說(shuō)在遍歷DOM樹(shù)的時(shí)候訪(fǎng)問(wèn)不到Attr節(jié)點(diǎn)。要想訪(fǎng)問(wèn)Attr節(jié)點(diǎn),只有先找到其所屬的Element節(jié)點(diǎn)之后,用特別的方法訪(fǎng)問(wèn)。下面的實(shí)例說(shuō)明其操作。首先,制作XML文檔,本文檔改編自example1.xml,在此基礎(chǔ)上添加屬性,構(gòu)成的文檔內(nèi)容如下,并將其命名為example_attr.xml。<?xml version="1.0" ?><圖書(shū)信息><圖書(shū) isbn="7-111-10288-6" 出版日期="1999.8"><書(shū)名>C#技術(shù)內(nèi)幕</書(shū)名><作者>

53、Joseph Mayo</作者><售價(jià)>59.00</售價(jià)></圖書(shū)><圖書(shū) isbn="7-5084-1152-8/TP.456" 出版日期="2002.9"><書(shū)名>JAVA 2網(wǎng)絡(luò)協(xié)議內(nèi)幕</書(shū)名><作者>AI Williams</作者><售價(jià)>48.00</售價(jià)></圖書(shū)><圖書(shū) isbn="7-121-02807-7" 出版日期="2006.7">&l

54、t;書(shū)名>Eclipse完全手冊(cè)</書(shū)名><作者>周競(jìng)濤</作者><售價(jià)>55.00</售價(jià)></圖書(shū)></圖書(shū)信息>打開(kāi)記事本,在里面輸入下列Java代碼,并將其命名為attribute_do.java。import org.w3c.dom.*;import javax.xml.parsers.*;import java.io.*;public class attribute_do public static void main(String args) try DocumentBuilderFacto

55、ry factory=DocumentBuilderFactory.newInstance(); DocumentBuilder builder=factory.newDocumentBuilder(); Document document=builder.parse(new File("example_attr.xml"); Element root=document.getDocumentElement(); String rooName=root.getNodeName(); System.out.println("XML文件根元素的名稱(chēng)為:"+rooName); NodeList nodelist=root.getElementsByTagName(&quo

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論