日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

XML 和 Java 技術(shù): XML 持久性的三種方式

系統(tǒng) 2663 0

序列化、TrAX 和數(shù)據(jù)綁定:哪種方法更適合您?

級(jí)別: 初級(jí)

Brett D. McLaughlin, Sr. ( brett@newInstance.com ), 作家兼編輯, O'Reilly Media, Inc.

2007 年 10 月 22 日

使用 XML 可以實(shí)現(xiàn)各種有趣的功能,但是如果無(wú)法將其持久化保存到文件中,那么一切都將是徒勞而已。Brett McLaughlin 將討論實(shí)現(xiàn) XML 持久化存儲(chǔ)的各種不同的技巧,并分別比較其優(yōu)點(diǎn)和缺點(diǎn)。
<!--START RESERVED FOR FUTURE USE INCLUDE FILES--><!-- include java script once we verify teams wants to use this and it will work on dbcs and cyrillic characters --><!--END RESERVED FOR FUTURE USE INCLUDE FILES-->

必須將 XML 存儲(chǔ)在某個(gè)地方

XML 是一種偉大的數(shù)據(jù)格式 — 顯而易見(jiàn),整個(gè) IBM developerWorks 專(zhuān)區(qū)都在專(zhuān)注于研究這個(gè)主題。2007 年,關(guān)于 XML 的討論多半是 Web 服務(wù),或者 XML 和 Java? 對(duì)象之間的轉(zhuǎn)換,或者讀取 XML 配置文件,或者甚至是使用 XML 格式的數(shù)據(jù)庫(kù)代替關(guān)系或面向?qū)ο蟮臄?shù)據(jù)庫(kù)。

目前,我們還沒(méi)有聽(tīng)到有人在談?wù)撊绾螌⑺褂玫膬?nèi)存表示 — DOM、JDOM 等等 — 中的 XML 保存到靜態(tài)文件中去,并在其中填滿(mǎn)尖括號(hào)和引號(hào)。坦白的說(shuō),獲取 XML 并將其寫(xiě)入文件算不上激動(dòng)人心 — 不過(guò)這卻是有必要的。試問(wèn),編程領(lǐng)域若永遠(yuǎn)都不能將 XML 持久化存儲(chǔ)到文件中會(huì)是怎樣一番情境?您可以在內(nèi)存中創(chuàng)建 XML 文檔,并且甚至可以將其發(fā)送給應(yīng)用程序中的其他組件(或者其他應(yīng)用程序的組件);但是卻無(wú)法存儲(chǔ)這些 XML。您可以使用 XML 存儲(chǔ)配置數(shù)據(jù),同時(shí)編寫(xiě)各種工具來(lái)讀取該數(shù)據(jù),但是實(shí)際上卻無(wú)法存儲(chǔ)配置文件本身。您甚至還可以讀取 SOAP 信封的內(nèi)容 — 但是卻無(wú)法將這些內(nèi)容存儲(chǔ)在磁盤(pán)上,以供應(yīng)用程序離線時(shí)使用。

顯然,將 XML 寫(xiě)入文件非常重要。事實(shí)上,如果只是想將數(shù)據(jù)停留在內(nèi)存中并且不需要擔(dān)心數(shù)據(jù)的存儲(chǔ)方式,您可以想象得到不需要存儲(chǔ) XML 的編程世界是什么樣子,毫無(wú)疑問(wèn)這在如今的編程領(lǐng)域中是不可能的。

因此,問(wèn)題十分簡(jiǎn)單:如何將 XML 持久化存儲(chǔ)到文件中去?我假定本文的讀者需要自己處理這一任務(wù)。換句話說(shuō),如果您在編程中從未涉及到持久化存儲(chǔ) XML,那么本文將使您受益匪淺。(但是,了解如何執(zhí)行這些任務(wù)會(huì)更利于對(duì)文章的理解)對(duì)于那些確實(shí)關(guān)注持久性存儲(chǔ)的人,我總結(jié)了三種相當(dāng)常用的主流方法:

  1. 使用 DOM 和 JDOM 之類(lèi)的 API 將 XML 數(shù)據(jù)結(jié)構(gòu)直接寫(xiě)入文件
  2. 使用 Transformation API for XML (TrAX) 和標(biāo)識(shí)轉(zhuǎn)換(identity transformation)持久化存儲(chǔ)您的 XML
  3. 使用 JAXB 之類(lèi)的較高級(jí)別的 API 處理持久化存儲(chǔ)

直接使用 API

如果使用一個(gè)或多個(gè) API 讀取 XML,那么很明顯的一個(gè)方法就是使用與之相同的 API 將 XML 寫(xiě)入文件。比如說(shuō),如果您使用 JDOM API 和一個(gè) JDOM Document 對(duì)象操作 XML,那么可以編寫(xiě)以下代碼:

            XMLOutputter outputter = new XMLOutputter();
outputter.setFormat(Format.getPrettyFormat());
outputter.output(myDocument, new FileWriter("outputFile.xml"));

          

與此類(lèi)似,在 DOM Level 3 中可以使用新的 Load 和 Save API:

            DOMWriter writer = new org.apache.xml.serialize.XMLSerializer();
writer.setNewLine("\r\n");
writer.setEncoding("UTF-8");
writer.writeNode(new FileOutputStream(new File("outputFile.xml")), myDocument);

          

注意,使用新 DOM API 的方法多種多樣,其中有一些具有較低的供應(yīng)商獨(dú)立性。上面的示例代碼中含有一個(gè)特定于 Xerces 的類(lèi),但是其他方法不會(huì)像它一樣與某個(gè)特定的供應(yīng)商類(lèi)緊密綁定在一起。從學(xué)習(xí)的角度來(lái)說(shuō),那些方法都不夠直觀,因此我保留了特定于供應(yīng)商的代碼。

優(yōu)點(diǎn)

這種方法的優(yōu)勢(shì)是可以相當(dāng)直接地與您的 API 進(jìn)行交互,從而實(shí)現(xiàn)良好和全面的控制。您可以設(shè)置新行,您可以處理首行縮進(jìn),您可以控制輸出文件的各個(gè)方面。此外,還可以盡可能拉近您與文件之間的距離;即沒(méi)有包裝器 API 也沒(méi)有間接層,您可以直接編寫(xiě) XML。如果您對(duì) JDOM 和 DOM 比較熟悉,那么它們將是輸出 XML 的不二選擇。

缺點(diǎn)

任何方法有優(yōu)點(diǎn)就必然有缺點(diǎn)。雖然您可以全面地控制輸出的各種細(xì)節(jié),但是如果輸出配置不當(dāng)則會(huì)導(dǎo)致諸多混亂的問(wèn)題。換行錯(cuò)誤,編寫(xiě)錯(cuò)誤和 I/O 錯(cuò)誤都是這種方法產(chǎn)生的一些常用問(wèn)題。除此之外,您還工作于一個(gè)非常低的層次,并沒(méi)有大量的輔助工具(JDOM 在 Format.getPrettyFormat() Format.getCompactFormat() 方法中提供了一些:而 DOM 幾乎是一毛不拔)。這意味著您必須要理解編碼、輸出格式、縮進(jìn)格式,以及對(duì)輸出有影響的任何內(nèi)容。

轉(zhuǎn)換格式

另一個(gè)流行的選擇是使用 TrAX 和標(biāo)識(shí)轉(zhuǎn)換。TrAX 是 Transformation API for XML 的縮寫(xiě),它現(xiàn)在是 JAXP 的一部分,而 Java 平臺(tái)的每一個(gè)發(fā)行版中都含有 JAXP(除了 Micro Edition)。TrAX 允許您使用 XSL 樣式表對(duì) XML 進(jìn)行轉(zhuǎn)換。由于 XML 經(jīng)常需要結(jié)合 SAX 和 DOM 一起使用,因此 TrAX 可以接收 SAX 事件和 DOM Document 作為輸入,并能夠輕易地產(chǎn)生輸出文件。此外,TrAX 還可以輕松地對(duì)這些格式進(jìn)行相互轉(zhuǎn)換。比如說(shuō),您可以使用以 DOM 表示的 XML 文檔作為輸入,并對(duì)它進(jìn)行轉(zhuǎn)換,然后再將輸出發(fā)送到文件中。或者您也可以讀取文件中的內(nèi)容,并對(duì)它進(jìn)行轉(zhuǎn)換操作,然后再將結(jié)果文檔存儲(chǔ)到 DOM Document 中。

這種方法的另外一個(gè)作用是,您可以使用一個(gè)不含任何文檔操作的樣式表,并使用某種格式作為輸入,然后將這種格式輸出為任意其他的格式。使用不具轉(zhuǎn)換功能的樣式表 — 實(shí)際上指不執(zhí)行任何操作但回轉(zhuǎn)所接收的輸入內(nèi)容的樣式表 — 稱(chēng)作 標(biāo)識(shí)轉(zhuǎn)換(identity transformation) 。因此您可以從文件中獲得文檔,然后應(yīng)用標(biāo)識(shí)轉(zhuǎn)換,最終在 DOM Document 中生成相同的 XML。如果您采用相反的方式 — 從 DOM 到文件 — 那么實(shí)際上可以實(shí)現(xiàn)持久化存儲(chǔ) XML。這種方法類(lèi)似于以下過(guò)程:

            Source domSource = new DOMSource(myDOMDocument);
Result fileResult = new StreamResult(new File("outputFile.xml"));
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer();
transformer.transform(domSource, fileResult);

          

此處,DOM 文檔中的 XML 最終轉(zhuǎn)換為了一個(gè) outputFile.xml 文件。

TrAX 的優(yōu)點(diǎn)

TrAX 最大的優(yōu)點(diǎn)就是易于使用。擁有 Java 平臺(tái)訪問(wèn)權(quán)的任何人都可以使用它,并且不需要對(duì) SAX 或 DOM 有深入的了解。因此,這對(duì)于只有基本 XML 編程技能的開(kāi)發(fā)人員來(lái)說(shuō)是一個(gè)極具吸引力的選擇。此外,不熟悉 SAX 或 DOM 的初級(jí)程序員也可以使用 TrAX — 只需要了解 10 到 20 行函數(shù)代碼 — 快速將 XML 持久化存儲(chǔ)到文件中,或者甚至是 DOM Document s 和 SAX 事件中。

TrAX 的缺點(diǎn)

使用 TrAX 的最大缺點(diǎn)是:雖然可以很容易執(zhí)行標(biāo)識(shí)轉(zhuǎn)換,但是處理輸出細(xì)節(jié)卻需要很高的技巧。換行、編碼、空格和縮進(jìn) — 所有這些都是 TrAX 提供的配置選項(xiàng),但是它并不像使用 DOM 或 JDOM 直接配置那樣簡(jiǎn)單。在大多數(shù)情況下,TrAX 為普通任務(wù)所提供的易用性常常伴隨著較低的靈活性,至少不能開(kāi)箱即用。

注意:在輸出方面,使用 TrAX 和標(biāo)記轉(zhuǎn)換幾乎可以實(shí)現(xiàn) JDOM 或 DOM 可以完成的所有任務(wù);只是不夠簡(jiǎn)單或直觀而已。您只需要了解一些 XSLT 和 TrAX API 的知識(shí),這兩者與所執(zhí)行的實(shí)際輸出任務(wù)并沒(méi)有密切的聯(lián)系。

使用數(shù)據(jù)綁定實(shí)現(xiàn)持久化存儲(chǔ)

將 XML 轉(zhuǎn)換為靜態(tài)格式的另一種方法 — 特別是您希望這種格式是位于磁盤(pán)上的文件 — 是使用 JAXB 之類(lèi)的數(shù)據(jù)綁定 API。雖然通常人們不會(huì)考慮使用數(shù)據(jù)綁定來(lái)實(shí)現(xiàn)持久化存儲(chǔ),但是它可以有效地實(shí)現(xiàn):讀取內(nèi)存中表示的 XML 文檔并將其寫(xiě)入文件。

我沒(méi)有太多時(shí)間詳細(xì)介紹數(shù)據(jù)綁定的概念(您可以在 developerWorks 網(wǎng)站上閱讀一些這方面的文章);下面這段簡(jiǎn)短的代碼使用了 JAXB 方式的數(shù)據(jù)綁定實(shí)現(xiàn)持久性存儲(chǔ):

            FileOutputStream stream = new FileOutputStream("outputFile.xml");
Marshaller marshaller = myJaxbContext.createMarshaller();
marshaller.marshal(myJavaObject, stream);

          

您可以設(shè)置一些選項(xiàng),比如說(shuō)輸出文件的編寫(xiě),所有設(shè)置都在 Marshaller 對(duì)象中。事實(shí)上,JAXB 在設(shè)置輸出屬性方面的靈活性與前面兩種方法是不相上下的。

JAXB 的優(yōu)點(diǎn)

JAXB 的最大優(yōu)點(diǎn)就是:它具有極大的易用性,特別是對(duì)于一些簡(jiǎn)單的任務(wù)。同時(shí),雖然人們?nèi)匀徽J(rèn)為 SAX 和 DOM 是主流方法(至少在普通 Java 編程領(lǐng)域是如此),但是 JAXB 對(duì)于使用 Java 語(yǔ)言的任何人來(lái)說(shuō)都是家常便飯。這意味著我們可以找到更多 JAXB 方面的文章和教程(2007 發(fā)布的一篇調(diào)查文章將證實(shí)這一點(diǎn))。此外,對(duì) JAXB 的支持也要優(yōu)于 DOM 和 SAX。SAX 和 DOM 是 Java 平臺(tái)標(biāo)準(zhǔn)版本的一部分,而 JAXB 在很大程度上是由 Sun Microsystems, Inc. 發(fā)明的。因此,JAXB 的支持稍高一籌也不足為奇了。

此外,使用 JAXB 基本不需要掌握任何 XML 知識(shí)。您可以操作普通 Java 對(duì)象 — 不是特定于 XML 的對(duì)象,如 DOM 的 Node Text 接口 — 并將這些對(duì)象直接表示為 XML。這意味著較低的入門(mén)門(mén)檻,并且任何人都希望可以在很短的時(shí)間內(nèi)掌握它,尤其是當(dāng)老板在辦公室對(duì)著您頤指氣使的時(shí)候。

JAXB 的缺點(diǎn)

有其利必有其弊。JAXB 的不足之外在于我們不需要過(guò)多了解 XML 便可以使用它。這看上去似乎是我剛剛提到的優(yōu)點(diǎn),但是它同時(shí)也潛藏著缺點(diǎn)。對(duì) XML 的了解越少,要合理使用 JAXB 就愈加顯得困難。您可以輕松地生成一個(gè) XML 文件,但是卻會(huì)發(fā)現(xiàn)這個(gè)文件的格式并不可用,或者它只含有一部分需要持久化存儲(chǔ)的對(duì)象,或者其中的對(duì)象與您所編制的對(duì)象并不相同。

所有這些常常會(huì)導(dǎo)致開(kāi)發(fā)人員將 JAXB 放在一旁,或者大量學(xué)習(xí) XML、SAX 和 DOM 方面的知識(shí)。這樣一來(lái),許多開(kāi)發(fā)人員都會(huì)繼續(xù)使用 SAX 和 DOM 實(shí)現(xiàn)持久性存儲(chǔ),而使用 JAXB 只是為實(shí)現(xiàn)其最簡(jiǎn)單的功能:在 XML 和 Java 對(duì)象之間相互轉(zhuǎn)換。

另一種選擇……

我特意將最后一種選擇留給大家思考:將 XML 作為一系列比特、節(jié)點(diǎn)和字符串直接寫(xiě)入 FileOutputStream FileWriter 。毫無(wú)疑問(wèn),這種方法可以將 XML 寫(xiě)入文件,并且這種方法的采用也相當(dāng)多;但是在本例中,持久化存儲(chǔ)已有 XML 數(shù)據(jù)并沒(méi)有從 非 XML 格式的數(shù)據(jù)中創(chuàng)建 XML 那么頻繁。您可以認(rèn)出這種代碼,它們通常類(lèi)似于以下形式:

            String xmlString = setupXMLBuffer(
  new StringBuffer("<firstName>")
       .append(customer.firstName)
       .append("</firstName>")
       .append("<lastName>")
       .append(customer.lastName)
       .append("</lastName>")
  // etc...
       .toString()
);
bufferedWriter.write(xmlString);
// other file I/O code

          

這段代碼并沒(méi)有任何錯(cuò)誤;我們只是將數(shù)據(jù)持久化存儲(chǔ)于 XML 中,所有操作都在一步之內(nèi)完成。因此,關(guān)于如何持久化存儲(chǔ)數(shù)據(jù),以及哪種方式是最佳的,這些問(wèn)題都無(wú)關(guān)緊要。寫(xiě)入數(shù)據(jù)并將其存入 XML 的操作是無(wú)法分開(kāi)的,因此再多的討論也無(wú)濟(jì)于事。

結(jié)束語(yǔ)

我們應(yīng)該如何處理 XML 持久性存儲(chǔ)呢?并沒(méi)有完全正確的答案。也就是說(shuō),Java 和 XML 開(kāi)發(fā)人員都需要經(jīng)過(guò)仔細(xì)討論才能做出選擇。您趨向于使用一致的方法解決通用問(wèn)題嗎?有沒(méi)有一種持久性存儲(chǔ)方法可以在磁盤(pán)上生成易于讀取、使用并能發(fā)送給其他應(yīng)用程序的 XML 文檔呢?

對(duì)于大多數(shù)技巧,我的觀點(diǎn)是人們應(yīng)該重點(diǎn)關(guān)注這些技巧是否能夠真正奏效。如果您發(fā)現(xiàn)某個(gè)技巧更適用于其他人,那么您應(yīng)該能夠提高自己的編程技巧 — 至少,這是基本思想!因此,請(qǐng)花幾分鐘逛逛 developerWorks 網(wǎng)站的 Java 和 XML 論壇(請(qǐng)參閱 參考資料 獲得訪問(wèn)鏈接),并讓我們知道您所使用的持久性存儲(chǔ)方法。如果需要基于一些特定的功能,也請(qǐng)告訴我們。我希望能在論壇中見(jiàn)到您的身影。

參考資料

學(xué)習(xí)

  • 您可以參閱本文在 developerWorks 全球網(wǎng)站上的 英文原文

  • Sun's online Java 和 XML 總部 :說(shuō)到 JAXP,您將發(fā)現(xiàn)沒(méi)有比 Sun 公司的在線頁(yè)面更佳的地方了。

  • 核 心 API 文檔 用于 Java 5.0 技術(shù):獲取有關(guān) JAXP JavaDoc 的信息,現(xiàn)在已集成在這一規(guī)范中。

  • SAX Web 站點(diǎn) :找到更多有關(guān) JAXP 的 API。開(kāi)始了解用于 Java 環(huán)境的 SAX 2。

  • W3C Web 站點(diǎn) :有關(guān) SAX 支持的 XML 的另一看法,請(qǐng)了解 DOM。

  • Apache Xerces 解析器:了解 Sun 在他們的 JDK 5.0 實(shí)現(xiàn)中所使用的解析器。

  • XML 入門(mén) (Doug Tidwell,developerWorks,2002 年 11 月):想了解 XML 的基礎(chǔ)知識(shí)嗎?請(qǐng)閱讀這篇教程和一些 其他培訓(xùn)服務(wù) ,其中介紹的都是最基本的內(nèi)容。

  • IBM XML 認(rèn)證 :看看如何才能成為一名 IBM 認(rèn)證的 XML 及相關(guān)技術(shù)的開(kāi)發(fā)人員。


討論

關(guān)于作者

Photo of Brett McLaughlin

Brett McLaughlin 從 Logo 時(shí)代就開(kāi)始使用計(jì)算機(jī)。(還記得那個(gè)小三角嗎?)近年來(lái)他已經(jīng)成為 Java 技術(shù)和 XML 社區(qū)最知名的作家和程序員之一。他曾經(jīng)在 Nextel Communications 實(shí)現(xiàn)過(guò)復(fù)雜的企業(yè)系統(tǒng),在 Lutris Technologies 編寫(xiě)應(yīng)用程序服務(wù)器,最近在 O'Reilly Media, Inc. 繼續(xù)撰寫(xiě)和編輯這方面的圖書(shū)。在他的新書(shū) Head Rush Ajax 中,Brett 與暢銷(xiāo)書(shū)作家 Eric 及 Beth Freeman 為 Ajax 帶來(lái)了獲獎(jiǎng)的創(chuàng)新方法 Head First。他的上一本書(shū) Java 1.5 Tiger: A Developer's Notebook 是第一本可獲得的關(guān)于最新版本 Java 技術(shù)的書(shū)籍,而他的經(jīng)典著作 Java and XML 仍然是在 Java 語(yǔ)言中使用 XML 技術(shù)的權(quán)威圖書(shū)。

XML 和 Java 技術(shù): XML 持久性的三種方式


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 崇阳县| 云阳县| 诸暨市| 衡水市| 桓仁| 安平县| 泊头市| 伊金霍洛旗| 阿坝| 南宁市| 巴彦县| 元江| 衡南县| 大洼县| 三亚市| 大宁县| 新乐市| 许昌市| 喀什市| 阳高县| 河南省| 永城市| 洪江市| 崇信县| 黎城县| 乌鲁木齐县| 东兴市| 尼木县| 西青区| 黑河市| 台前县| 博兴县| 河曲县| 津南区| 绵阳市| 上犹县| 佳木斯市| 甘谷县| 明光市| 桃江县| 邓州市|