xml 是現在非常流行的數據表達格式,其特點是可移植、與平臺無關以及具有直接可讀的形式。Document Object Model (DOM) 是應用程序存取 XML 數據的接口。不幸的是,DOM 是一種相當復雜的 API,因而較難以迅速把握。但是,如能知道所存取數據的 DTD,這時就輕易得多了。本文將通過若干簡單步驟,對如何利用 java 版的 DOM 來存取 XML 數據進行介紹。
可擴展標記語言 (XML) 已經相當普及,它是一種可移植的、與平臺無關的且直接可讀的數據格式。許多軟件廠商均已宣稱“支持 XML”,這通常是指他們的軟件產品將生成或用到 XML 格式的數據。
XML 也同樣被看作是企業間交流數據的通用格式。它答應企業在 XML 文檔類型定義(即 DTD)的基礎上對所交流的數據取得一致。這些 DTD 文件獨立于企業中所使用的數據類型。
許多標準化組織正在致力于規范交流數據的 DTD。其中一個例子就是國際出版通信委員會(請參見資源)已經定義了一個 XML 的 DTD,這個 DTD 可以使“所傳輸的帶有標記的新聞信息能夠輕松地轉換為電子出版格式”。這些市場標準將使不同應用程序之間能夠在未事先確定方式的情況下進行數據的交換。
由 W3C 定義的 XML 規范(請參見資源)中規定了 XML 的語法和語義。一個 XML 文檔必須經過語法分析才能被處理。假如每個程序都必須先對 XML 進行語法分析再去處理,那將是非常困難的,因為給出這種語言的語法和語義是很復雜的。W3C 已經定義了文檔對象模型(DOM)(請參見資源)來解決這一問題。DOM 是一個針對XML數據的應用編程接口。大部分 XML 語法分析器都為所分析的 XML 生成一個 DOM 描述。
DOM 標準 DOM API 被定義為一系列 CORBA IDL 接口(請參見資源)。它用一個抽象樹來描述一個經過語法分析的 XML 文檔。之所以說它是抽象的,這是因為只有這些接口反映出樹形的結構。而用來實現抽象樹的實際數據結構和算法不必是樹形結構。
由于 DOM API 是以 CORBA IDL 形式規定的,所以它被許多編程語言所支持,包括 Java 語言。我們假定本文中使用標準的 Java 語言。DOM 規范給出了具體的基于Java 接口。
DOM 第一層規范是在 1998 年被采用的。它留下一些保留部分,以根據后來的實踐經驗來進一步擴充。DOM 第二層規范在第一層的基礎上增加了對 XML 命名空間、文檔創建、視圖和式樣單等內容的支持。第二層規范尚有待公眾評價。雖然從技術上而言還沒有最終完成,但是也已經相當穩定。
對于一個 XML 文檔,許多 XML 語法分析器均可供 Java 程序使用,以生成 DOM 的第一層描述。因此,這里的代碼只假定為基于DOM 的第一層子集。
通用或特定 DTD 代碼 在Java中使用DOM API編寫的代碼要么是通用的,要么是基于特定的DTD。通用代碼在所有 XML 文檔中都能正常工作。通用代碼一般更難編寫,因為它通常必須遍歷整個 DOM 樹,考慮各種可能。代碼不能依靠任何特定的元素、屬性和文檔結構。通用代碼用于處理一般性事務,例如檢查文檔中的拼寫錯誤、計算文字數目、通過網絡發送文件,等等。
另一方面,特定 DTD 代碼是在根據特定的 DTD 寫出的。它不能用來操作由另一種 DTD 定義的 XML 文檔。特定的 DTD 比較輕易編寫,因為它假設 XML 文檔具有該特定 DTD 所指定的格式。例如,假設一個 DTD 聲明一個名為“NAME”的元素要求具有一個名為“GIVEN”的屬性,Java 代碼可以假設這個屬性存在并通過簡單地 DOM getAttribute() 調用來訪問它
應當注重的是,這個接口的實現可有多種不同方式,其中的一些與 XML 無關(例如,某個實現可向數據庫發出請求)。當然,這里我們只關心用DOM API 來實現處理 XML 數據的操作,這些數據同前面基于DTD的訂單一致。
實現接口 現在編寫一個實現該接口并封裝 DOM 文檔的類。例如,我們定義:
class orderImpl implements order { Document theDocument;
在構建器中將 DOM 文檔捆綁至封裝類 將 DOM 文檔傳遞給封裝類的構建器。構建器檢查文檔類型,以確定該文檔確實符合訂單 DTD。記住這些代碼只是針對這個 DTD 的,并對數據的結構和內容做出假設。
public orderImpl(Document document) throws Exception { theDocument = document; DocumentType docType = theDocument.getDoctype(); if (docType==null) throw new Exception("Cannot determine document type."); if (!docType.getName().equals("order")) throw new ? Exception("Document is not an order."); }
從唯一的子樹中返回一個元素的屬性值 在諸如 name 這樣的名稱不唯一的情況下,billingName 方法是獲得元素值的一種方法。注重 name 在這個文檔中不唯一,但是在 billing 子樹中卻是唯一的。另外還要注重,billing 元素在整個文檔中是唯一的。這樣,我們可以在文檔中簡單地調用 getElementsByTagName("billing"),然后在返回的 billing 元素中調用 getElementsByTagName。由于 getElementsByTagName 也是在 DOM API 中的 Element 接口中定義的,所以可以這樣做。
public String billingName() { NodeList bl = theDocument.getElementsByTagName("billing"); NodeList nl = ((Element)bl.item(0)).getElementsByTagName("name"); Element name = (Element)nl.item(0); return name.getAttribute("given")+" "+name.getAttribute("family"); }
public class test { public static void main(String[] args) { XML4J2DOMSource parser = new XML4J2DOMSource(); try { parser.parse("order.xml"); order theOrder = new orderImpl(parser.getDocument()); System.out.println("The credit card is "+theOrder.creditCard()); System.out.println("The total price is "+theOrder.totalPrice()); System.out.println("The billing name is "+theOrder.billingName()); theOrder.authorizeCredit() } catch(Exception e) { e.printStackTrace(); } } }
我們通過這個非常簡單的例子向大家展示了 DOM API 的 10 個重要的操作。通過這些操作,我們說明了如何在已知 DTD 時進行查找、瀏覽、遍歷元素以及獲得元素及其屬性值。這將為學習其它 DOM API 打下堅實的基礎。
資源
XML 語法分析器及 DOM 實現 假如您想用 DOM API 編寫 Java 代碼,就需要一個 DOM 的實現,也就是一個語法分析器。幸運的是,現在已經可以找到一些了。這里有一些相關的資源:
Apache Xerces XML Parser IBM's XML Parser for Java Oracle (要訪問 Oracle Technology Network,您必須成為其會員。注冊是免費的。) Sun's Java Project X Xbeans Xbeans 是一個開放源代碼的 Java Beans 知識庫,使用最一般的方法來處理 DOM 文檔。通過構造 Xbeans,可以創建分布式應用程序來處理 XML。這里是通用DOM 代碼的極佳來源。 jGuru XML FAQ 國際出版通訊委員會 (International Press Telecommunications Council)是一個對數據交流中的 DTD 進行統一的標準化組織。 XML 規范 DOM 規范 CORBA IDL 關于作者 BrUCe Martin 是分布式對象計算領域的一位帶頭人。90 年代初期,他在惠普實驗室設計并實現了一種接口定義語言,它后來成為惠普最初的 CORBA 子項目的基礎。在 Sun 微系統公司,他是 Sun 的 CORBA 體系結構設計者之一,同時還是五項 OMG 的 CORBA 服務規范的制定者。在 Inprise 公司,Bruce 是該公司第一個以 CORBA 為基礎的 Java 應用服務器的設計者和開發者。Bruce 具有關于 Java、XML 和 DOM 的淵博的實踐經驗。
現在,Bruce 已經成為 jGuru 的軟件領袖。他正在致力于維護 xbeans.org(一個開放源代碼計劃),以創建一個用來處理 XML 并且能夠很輕易地融入分布式應用的 Java Beans 的知識庫。
Bruce 在加利福尼亞大學圣地亞哥分校獲得了計算機科學碩士和博士學位,此前他在位于加利福尼亞大學伯克利分校獲得了計算機科學學士學位。