Oracle開(kāi)發(fā)人員的 JDOM 和 XML 分析
2024-08-29 13:41:09
供稿:網(wǎng)友
JDOM使xml在java中的操作比以往任何時(shí)候都更加輕易。
碰巧,你在過(guò)去可能已經(jīng)用過(guò)眾多Java庫(kù)中的某一個(gè)以操作XML數(shù)據(jù)結(jié)構(gòu)。那么JDOM(Java文檔對(duì)象模型,Java Document Object Model)的用途是什么?開(kāi)發(fā)者又為什么需要它呢?
JDOM是用于Java優(yōu)化的XML數(shù)據(jù)操作的源代碼開(kāi)放的Java庫(kù)。盡管它與萬(wàn)維網(wǎng)協(xié)會(huì)(W3C,World Wide Web Consortium)的DOM類(lèi)似,但它是一種可供選擇的文檔對(duì)象模型,它不是在DOM基礎(chǔ)上構(gòu)建的,也不以DOM為模型。它們的主要區(qū)別是:DOM是與語(yǔ)言無(wú)關(guān)的,最初是用于Html頁(yè)的javascript操作,而JDOM專(zhuān)用于Java,因此它利用Java的特性,其中包括方法過(guò)載(method overloading)、集合(collection)、映像(reflection)和人們熟悉的編程風(fēng)格等。對(duì)Java編程人員來(lái)說(shuō),JDOM顯得更自然、更"適用"。就像Java優(yōu)化的RMI(remote method invocation,遠(yuǎn)程方法調(diào)用)庫(kù)要比與語(yǔ)言無(wú)關(guān)的CORBA(Common Object Request Broker Architecture,通用對(duì)象申請(qǐng)中介體系結(jié)構(gòu))更自然一樣。
你可以根據(jù)源代碼開(kāi)放的Apache類(lèi)型(商業(yè)友好)的許可,在jdom.org找到JDOM。它是合作設(shè)計(jì)開(kāi)發(fā)的,并擁有超過(guò)3000個(gè)訂閱者的郵件列表。此庫(kù)已經(jīng)被Sun公司的Java社區(qū)進(jìn)程(JCP,Java Community PRocess)接受作為Java規(guī)范申請(qǐng)(JSR-102),并很快成為正式Java規(guī)范。
本系列文章將對(duì)JDOM進(jìn)行技術(shù)介紹。本文提供一些關(guān)于重要類(lèi)的信息。下一篇文章將介紹如何在自己的Java程序中應(yīng)用JDOM。
JDOM軟件包結(jié)構(gòu)
JDOM庫(kù)包括六個(gè)軟件包。第一個(gè)是org.jdom包,它包括表示XML文檔以及其組件的類(lèi),這些組件有:Attribute、CDATA、Comment、DocType、Document、Element、EntityRef、Namespace、Processing InstrUCtion和Text等。假如你對(duì)XML很熟悉,通過(guò)類(lèi)的名字就可以知道它的用途了。
下一個(gè)是org.jdom.input包,它包括用于構(gòu)建XML文檔的類(lèi)。其中最主要和最重要的類(lèi)是SAXBuilder。SAXBuilder通過(guò)監(jiān)聽(tīng)輸入的XML簡(jiǎn)單API(SAX,Simple API for XML)事件建立相應(yīng)的文檔。假如需要由一個(gè)文件或其他流(stream)建立文檔,那就可以采用SAXBuilder。它采用SAX分析器讀取流,并根據(jù)SAX分析器的"回調(diào)"建立文檔。這一設(shè)計(jì)的一個(gè)好處就是SAX分析器越快,SAXBuilder也會(huì)越快。另一個(gè)主要輸入類(lèi)是DOMBuilder。DOMBuilder由DOM樹(shù)構(gòu)建。假如預(yù)先已經(jīng)有了一個(gè)DOM樹(shù),并希望用JDOM版本的樹(shù)來(lái)代替,那么采用DOMBuilder是非常方便的。
對(duì)于這些可能的生成器來(lái)說(shuō),不存在什么限制。例如,由于Xerces有Xerces本地接口(XNI,Xerces Native Interface),可用于在比SAX較低的層次上進(jìn)行操作,所以編寫(xiě)一個(gè)XNIBuilder以支持某些分析器知識(shí),而不采用SAX,就可能很有意義。一個(gè)構(gòu)成JDOM項(xiàng)目的很流行的生成器是ResultSetBuilder。它利用JDBC結(jié)果集合,生成一個(gè)XML文檔,用以表示SQL結(jié)果,根據(jù)是哪種元素和哪種屬性,它有多種不同的編排。
org.jdom.output包中包括輸出XML文檔的一些類(lèi)。其中最重要的類(lèi)是XMLOutputter。它將文檔轉(zhuǎn)換為一個(gè)字節(jié)流,用于輸出到文件、流和接口程序(sockets)中。XMLOutputter具有很多支持原始輸出(raw output)、完美輸出(pretty output)、壓縮輸出或其他輸出的非凡配置選項(xiàng)。它是一個(gè)相當(dāng)復(fù)雜的類(lèi)。
這可能是為什么DOM level2中仍然沒(méi)有這種能力的原因。
其他輸出器(outoutter)包括SAXOutputter,它可以產(chǎn)生基于文檔內(nèi)容的SAX事件。盡管它看起來(lái)有些神秘,但事實(shí)證實(shí)這個(gè)類(lèi)在XSLT變換中極其有用,這是因?yàn)橄鄬?duì)于將文檔數(shù)據(jù)傳遞到一個(gè)引擎的字節(jié)來(lái)說(shuō),SAX事件是一種更為有效的方法。還有一個(gè)DOMOutputter輸出器,它用于生成表示文檔的DOM樹(shù)。一個(gè)有趣的輸出器是JTreeOutputter,它只有幾十行代碼,它可以建立表示文檔的JTree。將它與ResultSetBuilder聯(lián)合起來(lái)后,僅用幾行代碼就可以通過(guò)SQL查詢得到結(jié)果的樹(shù)視圖。
注重,與在DOM中不同,文檔并不與它們的生成器捆綁在一起。這就形成了一個(gè)出色的模型,在這種模型中,你可以用一些類(lèi)保持?jǐn)?shù)據(jù),另一些類(lèi)構(gòu)造數(shù)據(jù),其他一些類(lèi)來(lái)定制數(shù)據(jù)??梢噪S意進(jìn)行混合和匹配。
org.jdom.transform和org.jdom.XPath包中還有支持內(nèi)置的XSLT轉(zhuǎn)換和XPath查找的類(lèi)。
最后,org.jdom.adapters包中還包括在DOM交互中對(duì)庫(kù)提供幫助的類(lèi)。該庫(kù)的使用者永遠(yuǎn)不需要調(diào)用這一軟件包中的類(lèi)。這些類(lèi)是隨時(shí)可用的,因?yàn)槊總€(gè)DOM實(shí)現(xiàn)都為特定的引導(dǎo)任務(wù)生成不同的方法名稱,所以適配器類(lèi)將標(biāo)準(zhǔn)調(diào)用轉(zhuǎn)換成分析器專(zhuān)用的調(diào)用。Java API for XML Processing(JAXP)為解決此問(wèn)題提供了另一種方法,事實(shí)上降低了對(duì)這些類(lèi)的需要,但是這些類(lèi)仍然保留了下來(lái),這是因?yàn)橛捎谠S可證的原因,并不是所有的分析器都支持JAXP,也不是任何地方都安裝有JAXP。
生成文檔
文檔由org.jdom.Documentclass表示,你可以從頭建立一個(gè)文檔:
// This builds: <root/>
Document doc = new Document(new Element("root"));
也可以由文件、流、系統(tǒng)ID或URL建立一個(gè)文檔:
// This builds a document of whatever's in the given resource
SAXBuilder builder = new SAXBuilder();
Document doc = builder.build(url);
將幾個(gè)調(diào)用結(jié)合在一起,可以很輕易地在JDOM中建立一個(gè)簡(jiǎn)單的文檔:
// This builds: <root>This is the root</root>
Document doc = new Document();
Element e = new Element("root");
e.setText("This is the root");
doc.addContent(e);
假如你是一位非常有才能的用戶,你可能更愿意使用"方法鏈",在這種方式中,多種方法是依次調(diào)用的。這種方式之所以有效是因?yàn)榧戏椒ǚ祷厮鼈兯饔玫膶?duì)象,下面是一個(gè)例子:
Document doc = new Document(
new Element("root").setText("This is the root"));
為了進(jìn)行對(duì)比,下面給出如何用JAXP/DOM創(chuàng)建相同的文檔:
// JAXP/DOM
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.newDocument();
Element root = doc.createElement("root");
Text text = doc.createText("This is the root");
root.appendChild(text);
doc.appendChild(root);
用SAXBuilder生成文檔
如前所示,SAXBuilder提供了一種由任意面向字節(jié)的數(shù)據(jù)源來(lái)創(chuàng)建文檔的簡(jiǎn)單機(jī)制。缺省的無(wú)參數(shù)SAXBuilder()構(gòu)造器在后臺(tái)利用JAXP來(lái)選擇一個(gè)SAX分析器。假如你希望改變分析器,則可以設(shè)置javax.xml.parsers.SAXParserFactory系統(tǒng)屬性,以指向你的分析器提供的SAXParser Factory實(shí)現(xiàn)。對(duì)于Oracle9i版本2 XML分析器,應(yīng)當(dāng)這樣做:
java -Djavax.xml.parsers.SAXParserFactory=
oracle.xml.jaxp.JXSAXParserFactory YourApp
對(duì)于Xerces分析器,應(yīng)當(dāng)這樣做:
java -Djavax.xml.parsers.SAXParserFactory=org.apache.xerces.jaxp
.SAXParserFactoryImpl YourApp
假如沒(méi)有安裝JAXP,SAXBuilder缺省地指向Apache Xerces。一旦你創(chuàng)建了SAXBuilder實(shí)例,你就可以在生成器中設(shè)置幾個(gè)屬性,其中包括:
setValidation(boolean validate)
這一方法告訴分析器在生成過(guò)程中是否根據(jù)Document Type Definition(DTD,文檔類(lèi)型定義)進(jìn)行驗(yàn)證。缺省設(shè)置為"否"(off)。所用的DTD是文檔中DocType引用的一個(gè)。根據(jù)任何其他DTD進(jìn)行驗(yàn)證是不可能的,因?yàn)檫€沒(méi)有分析器支持這一功能。
setIgnoringElementContentWhitespace(boolean ignoring)
這一方法告訴分析器是否忽略元素內(nèi)容中所謂的"可忽略空格(whitespace)"。按照XML1.0規(guī)范,元素內(nèi)容中的空格必須由分析器保留,但當(dāng)根據(jù)DTD進(jìn)行驗(yàn)證時(shí),分析器可能知道文檔的特定部分不會(huì)支持空格,所以這一區(qū)域的任何空格都是"可忽略的"。其缺省設(shè)置為"否"(off)。假如你不希望使一個(gè)文檔"往返旅行",將輸入內(nèi)容以原樣輸出的話,那么將這一開(kāi)關(guān)打開(kāi)通常會(huì)使性能略微有些提高。注重,這一標(biāo)志只有在驗(yàn)證已完成時(shí)才有效。而進(jìn)行驗(yàn)證會(huì)導(dǎo)致性能下降,所以這一技巧僅在已應(yīng)用驗(yàn)證時(shí)才有用。
setFeature(String name, String value)
這一方法設(shè)置基礎(chǔ)SAX分析器的一個(gè)特性。這是一個(gè)原始的"傳遞(pass-through)"調(diào)用,所以在應(yīng)用這一方法時(shí)應(yīng)非常小心,因?yàn)閷?duì)特性的錯(cuò)誤設(shè)置(如弄錯(cuò)名稱空間)可能會(huì)中斷JDOM行為。而且,依靠任何特定分析器特性都會(huì)限制可移植性。這一調(diào)用對(duì)于啟用模式驗(yàn)證最為有用。
setProperty(String name, Object value)
這一方法設(shè)置基礎(chǔ)SAX分析器的一個(gè)屬性。它也是一個(gè)原始的"傳遞"調(diào)用,它具有同樣的風(fēng)險(xiǎn),而且對(duì)于有才能的用戶同樣有用,非凡是對(duì)于模式驗(yàn)證。下面的代碼結(jié)合這些方法,利用JAXP選擇的分析器讀取本地文件,驗(yàn)證功能有效,可忽略的空格都被忽略。
SAXBuilder builder = new SAXBuilder();
builder.setValidation(true);
builder.setIgnoringElementContentWhitespace(true);
Document doc = builder.build(new File("/tmp/foo.xml"));
用XMLOutputter輸出
文檔可以以多種不同的格式輸出,但最常見(jiàn)的輸出格式還是字節(jié)流。在JDOM中,XMLOutputter類(lèi)提供這一能力。它的缺省無(wú)參數(shù)生成器試圖忠實(shí)地