XML和Java:低級或高級的XMLAPI?

字號:

XML 是關于靈活性的
    不需要詳細研究 XML 起源的長期歷史原因,在開始這個討論話題之前我想再次重申 XML 最初確實是關于靈活性的。XML 提供了一種供應商中立的格式來表示數(shù)據(jù)。根據(jù)對 XML 規(guī)范內(nèi)容和要求的一致理解,應用程序可以輕易生成這種格式,并且其它應用程序也可以方便地使用這種格式。
    以更通俗的語言來說,如果您告訴我您使用的是 XML,然后再告訴我您所使用的元素和屬性,我很快就能寫出能讀取和使用 XML 的代碼來。反過來也一樣,如果我向您提供了我的約束模型 (constraint model)(通常為 DTD 或者 XML Schema 格式),您就能夠很快地操作我的數(shù)據(jù)。
    最初的 API 可以維持這種靈活性
    不足為奇,當 XML API 剛開始出現(xiàn)的時候,它們都非常的簡單。最初版本的 Simple API for XML(SAX)和文檔對象模型(Document Object Model,DOM)只具備非?;A的操作。您可以從某個元素中獲得數(shù)據(jù),操作其子元素,找出某個屬性的值等,全部都是這方面的操作。除了處理 XML 的詞匯結(jié)構(gòu)之外,這些 API 并未提供大量的特性。
    在 XML 發(fā)展的初期,這被認為是件好事。這非常像過去程序員對 C 語言和匯編語言做的一樣,以對計算機中底層的比特和字節(jié)維持控制,SAX 特別適合于處理原始的 XML 文檔 — 具有基本格式的數(shù)據(jù) — 并允許您的程序完成需要的操作,而不需要花費業(yè)余時間研究這些 XML API。
    然后出現(xiàn)了包裝 API
    首次告別低級控制 — 從理論上說實現(xiàn)了開發(fā)人員友好的 API — 的是 JAXP,Sun 公司用于處理 XML 的 Java API。最初,JAXP 的目標是從 SAX 和 DOM 代碼中移除一些特定于供應商的信息(涉及到所使用的 XML 解析器)。
    然而,為了努力提供一些便利,JAXP 提供了幾個輔助方法(helper method),從本質(zhì)上說就是把 SAX 和 DOM 中已有的功能封裝起來。因為 Sun 公司在 Java 市場上影響如此巨大,所以開發(fā)人員很快就開始使用這些輔助方法了,并且很少再直接操作 SAX 和 DOM 了 。
    程序員仍然需要了解 SAX 的基本原理(如什么是 ContentHandler 以及如何實現(xiàn)回調(diào)方法),但是 JAXP 抽象出了很多這樣的細節(jié)。事實上,要執(zhí)行特定的動作,如設置一些 SAX 中不常見的詞匯句柄,我們不得不 繞開 JAXP 而直接操作 SAX。
    如今又出現(xiàn)了數(shù)據(jù)綁定,JDOM 和大量的 API
    差不多在十年之后(取決于您所使用的日期),又出現(xiàn)了許多其它種類的 API。除了 SAX、DOM 和 JAXP 之外,我們還可以使用 JDOM、XOM、dom4j、StAX 和一些其它的變體非常直接地操作 XML。一些數(shù)據(jù)綁定 API,如 Zeus、Castor 和 JAXB 能允許我們在對 XML 沒有多少了解的情況下處理 XML,而不用操作 XML 文檔表示為邏輯數(shù)據(jù)而不是字符串或其他數(shù)據(jù)的數(shù)據(jù)。并且 Eclipse 之類的框架將完成所有這些操作,而您只需指定、單擊和修改 XML 就可以了。從字面上看,有數(shù)百種方案可供選擇(使用 XSLT 后我甚至不需關心 XML 的轉(zhuǎn)換了)。
    我們?nèi)匀痪邆潇`活性嗎?
    掌握了所有可用于操作 XML 的 API 之后,Java 和 XML 程序員似乎具備了前所未有的高度靈活性; 那么選擇就意味著靈活性嗎?我們稍微質(zhì)疑一下這一斷言,看它是否真的站得住腳。
    解析程序中的靈活性
    毫無疑問,我們能夠使用所想要的任何 XML 解析器,任何版本和風格的解析器都可以,只要我們具有某些類文件 — 大多數(shù)情況下,這些文件都捆綁在所選的 API 中。因此要方便地從 XML4J 轉(zhuǎn)換到 Sun 公司的老式 Crimson 解析器再到 Apache Xerces(版本 1 或版本 2)是非常簡單的。JAXP 之類的 API 可以很輕松地實現(xiàn)這個過程(盡管我在側(cè)欄中指出在所有新 API 出現(xiàn)之前這在 SAX 或 DOM 中就已經(jīng)可用),并且在很多數(shù)據(jù)綁定 API 中,我們甚至完全意識不到正在進行的解析; 解析都隱藏在幕后。因此毫無疑問,我們可以馬上使用任何想要的解析器。解析器中的靈活性被證實。
    使用中的靈活性
    大量的 XML API 還為我們提供了很多處理數(shù)據(jù)的方法。使用 SAX 和 DOM,能輕易地獲得文檔中的原始數(shù)據(jù); 使用 JAXP 也同樣可行,盡管所支持的數(shù)據(jù)可能會少一點(我之前提到過必須要執(zhí)行一些操作才能處理 XML 注釋或 DTD 語法之類的數(shù)據(jù))。我們在使用某個數(shù)據(jù)綁定 API 時,可以在根本上操作 XML 文檔的數(shù)據(jù)而不需 XML 的修飾。person 元素變成了Person 對象,并且我們能夠使用 getAge() 獲取 age 屬性的值。在很多方面,您可以根據(jù)在 XML 文檔中使用數(shù)據(jù)的方式以及對 XML 的了解程度來選擇 API。因此使用中的靈活性證實無誤。
    錯誤處理中的靈活性
    這里遇到了些許麻煩,高級 API 的一些靈活性造成了一些問題。在一些 API 中,如 Sun 的 JAXB 和所提供的數(shù)據(jù)綁定 API 中,我們都是在 XML 文檔的原始字符串、元素和屬性之上的幾個層次上進行操作的。其結(jié)果是,如果文檔中的內(nèi)容格式不正確,則處理任何問題都無法具備高度的靈活性。一般而言,在遇到某種編組或非編組錯誤時,我們必須要修復 XML 本身并重新運行該過程(或者向調(diào)用程序拋出異常,這在本質(zhì)上是相同的)。但是在真正地修復錯誤并從解析器中獲得詳細信息的方面呢?這確實不屬于高級 API 的范圍。因此,此處出現(xiàn)了一個缺陷。
    操作 XML 文檔中的靈活性
    上面所提到的使用中的靈活性,看上去可能與操作 XML 文檔中的靈活性是一樣的。其實并非如此; 在很多新興的(有些人會說是易于使用的)API 中,我們是在 XML 文檔中操作數(shù)據(jù)的 — 然后有時甚至不是作為 XML 而是當作對象或者屬性來進行操作的。操作 XML 文檔本身意味著我們能直接更換、修改或者移除文檔的一部分,并能直接處理元素名稱、屬性甚至注釋和處理指令。
    最初看來可能并不是真正需要這一級別的處理和靈活性,但是我們想到了與編程的類比。正如 C 語言和匯編語言使核心編碼器在計算機編程的底層進行工作,特別是 SAX 之類的 API,和程度較輕的 DOM,使核心的 Java 和 XML 程序員幾乎可以隨心所欲地操作 XML 文檔。就像大多數(shù)技巧都內(nèi)建在 C 語言或者匯編語言中,由于這種額外的能力轉(zhuǎn)化成了真正的速度、性能和一些優(yōu)化,比起一些高級的 API(如 JAXB 甚至是 JDOM),使用 SAX 和 DOM 仍然能為有經(jīng)驗的程序員提供更多的支持。因此,雖然這些高級 API 確確實實提供了大量的優(yōu)勢,但是它們并沒有為直接操作實際的 XML 文檔提供很多的靈活性。
    考試大編輯整理:就是這樣:就是想考證究竟有多大的靈活性。顯而易見,這篇文章并不是一篇充滿了運行代碼的技巧文章,因為我想知道這些天來是否有人確實使用了運行的 XML 代碼,以及他們所使用的是哪種(或哪些)API。真的有數(shù)百計、數(shù)千計或者數(shù)萬計的讀者仍然堅持使用 SAX 和 DOM 舒適地編寫著 startProcessingInstruction() 方法,或者完全使用數(shù)據(jù)綁定和輔助 API 取代了 SAX 和 DOM?我對此非常好奇,大多數(shù) developerWork 的編輯人員同樣好奇。
    更重要的是,您是否認為自己仍然能夠控制 XML 呢?我特別要向那些早期就開始處理 XML 的程序員提這個問題,那時 SAX 是快速讀取 XML 的惟一選擇,并且 DOM 是以對象的形式處理 XML 文檔的惟一選擇。您是否發(fā)現(xiàn)您自己在一個更高的級別工作?您是否對此滿意?或者是否我們都已成為 Turbo Pascal 程序員,而只有少許人在他們的 ASM 終端上處理堆棧呢?