用Java產生XML
最後更新:2017-02-28
來源:互聯網
上載者:User
xml|產生xml 一般情況下,我們只要一提到XML,大多數問題都會集中到解析 XML和 XML結構等方面。在這類技術領域,W3C提出了 DOM 和 SAX規範用來解析資料,Sun提供了Java XML Pack,而 Apache則推出了Xerces 和Xalan。然而,幾乎沒有什麼關注的目光投射到輸出XML這一問題上來。把JavaBeans和Swing組件變成 XML的項目倒有一些,但大多數情況下,開發人員只不過希望能用定製的格式輸出資料結構,這個任務其實不難。
本文特別探討了通過Java建立XML文檔的一些方法。我會具體提到好幾種用Java建立XML文檔的方案。它們都各自具備不同的優點,有些很簡單,有些則會依賴於某些強大的類庫。下面我就從最簡單的方法說起。
使用StringBuffer 類
最簡單、同時也是最常用的XML文檔建立方法就是自己動手。你可以採用StringBuffer 類或者某些Writer 類。其優點是你不需要用到其他庫,而且也不用建立多餘的對象。可是,這一舉措同時也帶來了很多缺點。首當其衝的就是無法保證XML的格式正確性。字元在置入String 對象的時候必須仔細考慮。你得特別小心 XML實體的出現,比如用<取代<等。 清單A 對此舉例說明。
程式清單A 的輸出結果是:
<person name="Jon Smith" age="21"/>
在這個簡單的例子裡,如果人名很古怪,比如Jon "The Cat" Smith,那麼輸出格式就出問題了。這段代碼在擷取名字的時候沒有處理引號,結果輸出的代碼就成了下面這樣子,顯然這種表示是錯誤的:
<person name="Jon "The Cat" Smith" age="21"/>
在閱讀原始碼的時候很難跟蹤隱藏在Java內的 XML 。想反,這種開發措施中大約1半左右的錯誤都歸結為沒有封閉的標籤和錯誤的引號處理,簡而言之就形成了無效的XML。
更明晰和簡單的方法:DOM
第2 個辦法就是DOM,也就是所謂的文檔對象模式(Document Object Model)。在給定對象結構之後,你可以把它轉換為某種格式的XML對象結構,然後輸出結果。可用的結構類型很多,範圍包括 Jakarta Element Construction Kit (ECS)項目的 XML類到完全遵守DOM規範的解析器等,比如Xerces,通常,版本越小輸出XML的方法就越簡單。清單B 就是一個採用ECS的例子。
清單B 提出了一種輸出資料的簡明辦法。事實上,你可以把兩個輸出行合并為一個,方法是把output 方法附在新的XMLDocument之後。這是一種採用ECS的有類文法模式,用起來方便之極。不過,這種方法不能很好地針對人員的年齡複製if- null 保護。為了實現這種保護,你必須採用清單C中的代碼。
ECS 表現出了好幾種優點,你不必避免引號字元(")。你也不需要完全封閉標籤,對象會為你做這些工作的,任何XML字元,比如<或者>都被 < 和 >代替,ECS可謂最簡單的DOM方法。而用W3C的DOM、JDOM或者Dom4J來處理這種風格的代碼則更為複雜一些,當然,W3C的DOM仍然具有獨立解析的優點。
採用ECS輸出XML的缺點包括了對象所引出的問題。你必須在寫出內容之前建立對象。這樣做在大多數情況下還是不錯的,可你在輸出大型XML檔案的時候則不希望建立這種XML結構。同樣的問題對其他大多數DOM方法也存在。
比起簡單地採用Writers 或者 StringBuffer 類而言,ECS相當接近於一種標記。它的體積比較大,但只有很小一部分才用來輸出XML。最大的問題是它的活動餘地不大。它擊敗了其他同類型的方案,因為其他類型更大、更笨重而且更複雜。
SAX
SAX(Simple API for XML)可以替代DOM風格的 XML 解析。它由一系列事件或者代碼在解析XML檔案時所調用的回呼函數組成。在你把結果直接輸出到Strings的情況下它並不能派多大的用場。但是,它可以用在間接的、更為複雜的方式下。
輸出Strings 的代碼可以代替輸出SAX事件。這一招可比僅僅輸出Strings要高多了,它可以加入到一個簡單的基類由其把SAX事件轉換為XML。
讓我們看看下面的例子,這個例子中使用了以下幾個類:
• Person: 業務對象,先前已經進行了說明
• PersonInputSource: 接納Person 對象
• PersonXMLReader: 知道如何把PersonInputSource 轉換為SAX 事件
• XMLPrettyPrinter: 把SAX 事件轉換為 XML的ContentHandler
其中最重要的代碼在PersonXMLReader內,如清單D所示。
清單 D 中的代碼說明了 Person 對象是如何被轉換為一系列 SAX 事件的。但這可不是個最簡單的活。用SAX把 Person 轉換為 XML 是通過清單E中的代碼實現的。
採用SAX 顯然讓你掌握了強大的計算能力,因為你可以在XML上附帶SAX解析器而沒有採用XMLPrettyPrinter。但是,在增加處理器的時候也會增加複雜性; SAX 是一種更複雜的概念。在多數情況下,簡單的方法往往效果最佳。
一旦基本組件編寫出來(XMLPrettyPrinter是一個基本InputSource,一個XMLParser 對象),產生事件就是小事一樁了。輸出新的 XML 結構只需要 parse 方法和插入組件即可。
圍繞SAX 事件建立XML還不是一個快捷、便利的措施。
採用XmlWriter 類
最後我提出個自己的方案,這就是XmlWriter 類。我的思路是採用一種界於太簡單和太複雜之間的技術來輸出 XML 。
重要的設計需求如下:
• 封裝java.io.Writer
• 提供Writer類的API
• 儘可能地處理XML
• 避免建立大型物件結構
• 允許 ECS鏈式風格
實現以上的這些需求可以讓 XML 寫成兩種風格。首先,它可以用java.lang.Writer 代碼寫出來,如清單F所示。
其次,它可以用鏈式方法的編碼風格寫成,這倒和ECS類似,因為每個write方法都返回 XmlWriter 自身。清單G 給出了這樣的例子。
從效能角度上看,XmlWriter 具有一定的顯著優勢,它幾乎沒有建立其他對象。具有相當的功能性,可以處理基本的XML片段(但沒有注釋、縮排或者文件類型)。最重要的是,用起來很簡單。
其負面問題已經提到過了,它不能處理注釋、縮排或者文件類型。而ECS在 XML 對象寫出自身時可以封閉標籤,XmlWriter 需要你調用 endEntity 方法。如果實體沒有終止就調用該方法就會扔出 XmlWritingException。最後,還有一個close 方法。它並不封閉writer對象,但會完成任何編寫中的XML 。或許最重要的是,它會在實體沒有終止的情況下扔出XmlWritingException 。
小結
產生XML方法有好幾種方法。XmlWriter 並不一定是最佳的XML建立工具,但是這種方法填補了太簡單、太笨重乃至太複雜之間的鴻溝。