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