在 SOA 架構中,程序員經常使用 XML 在應用程序之間交換結構化和半結構化的數據。XML 及其相關技術 — 文檔對象模型(Document Object Model,DOM)、XPath、HTTP、XQuery 和可擴展樣式表語言轉換(Extensible Stylesheet Language Transformations,XSLT) — 為快速應用程序開發提供了一個強大的環境。構建在這些技術之上的應用程序將占用更小的內存空間,需要更低的維護成本,同時又擁有更高的品質和靈活性。
DB2 和其他關系數據庫的 XML 方面的特性已經相當成熟,因此除了存儲和管理關系數據之外,它們還是存儲和管理 XML 數據的理想選擇。DB2 9 XML 支持(稱為 pureXML)提供了以純 XML 的形式(換句話說,就是帶注釋的、樹型的分層存儲)存儲 XML 的能力。在 DB2 9 中,XML 數據可以用 XML 模式索引,可以從關系數據組合而成,可以分解為關系數據,可以查詢和轉換,可以獨立發布,或者通過混合使用 SQL/XML 和 XQuery 與關系數據組合起來。
Web 浏覽器也正在為客戶機腳本提供更多的功能來有效地處理 XML。通過使用異步 JavaScript 和 XML(Asynchronous JavaScript and XML,Ajax),Web 頁面現在可以直接對應用服務器進行遠程過程調用,並且可以在任何返回的 XML 數據上使用 DOM API。
本文將展示如何利用 DB2 XML、Ajax 和 PHP Hypertext Preprocessor (PHP) 提供的功能來編寫簡單的基於 XML 的應用程序。通過示例場景的幫助,您將學習如何在 JavaScript 中調用 PHP 應用程序;如何使用 DOM 和 SimpleXML API 修改 XML 數據;如何將 XML 從客戶機傳送到應用程序再到數據庫;以及如何創建 PHP Web 服務來使用 SQL/XML 和 XQuery 發布關於 XML 數據的報告。
XML 優點
大多數應用程序都用於創建、存儲、操縱和呈現業務數據。對象包裝是指將業務數據綁在一起,使業務邏輯更容易處理它們。這些包裝器對象的很多功能都是根據關系和格式化規則來提供業務數據的結構,並使業務邏輯能夠操縱、發布和串行化封裝的數據。
圖 1. 基於對象包裝器的應用程序
圖 1 闡釋了使用對象包裝器的一個示例人壽保險應用程序。每個方框表示一個對象,每個對象至少有:
·一個構造函數
·Getter 和 Setter 方法
·驗證代碼
·內部對象層次的串行化
這些對象與實際的業務邏輯沒有關系。對象包裝是為了使業務邏輯更容易管理業務數據。包裝數據所需的代碼比業務邏輯要多得多。更多的代碼將導致更多的 bug、更大的固定性、更多的維護和更高的成本。
如果對象中的數據變量可以格式化為 XML 結構,並且對象的主要作用是將這些數據暴露給業務邏輯並讓業務邏輯操縱它們,那麼可以用 DOM 代替對象。
圖 2. 基於 XML 的應用程序
圖 2 展示了一個使用 XML 和 DOM 包裝器的示例保險應用程序。圖 1 中的所有數據包裝器對象都用一個 DOM 對象代替。業務數據是用 XML 建模的,DOM 提供了必要的 API 來:
·創建新的 XML 對象。
·更新 XML 對象的值。
·導航 XML 對象。
·使用 XPath 在對象層次中搜索。
·串行化和反串行化 XML 對象層次(換句話說,就是內建持久性)。
通過使用 XML,可以避免使用大多數用於管理業務數據的包裝器對象。應用程序將變得更加簡潔,並且更多地將重點放在業務邏輯上,而不是數據管理上。
XML 和架構
將 XML 引入架構中可以為表示業務數據帶來一種標准化的方式。XML 可以提供數據的結構;XML 模式施加結構和格式化規則;DOM API 和 XQuery、XPath 及 XSLT 之類的語言使業務邏輯可以有效地操縱、發布和串行化數據。由於業務數據的 XML 表示在客戶機、中間層和數據庫中都是一致的,因此操縱這些對象的代碼也是類似的。
我將展示如何在三層環境中構建基於 XML 的應用程序,這個三層環境由以下幾個部分組成:
·Web 客戶機:Asynchronous JavaScript and XML (Ajax),DOM
·應用服務器:PHP 和 SimpleXML
·數據庫: DB2 9 和 SQL/XML,XQuery
基於 ACORD 人壽數據模型的場景
我們來考慮一個簡單的人壽保險場景,在這個場景中,首先創建一個表示新保單的 XML 文檔,然後查詢和操縱這個文檔,另外還將這個文檔從一層移動到另一層。這個文檔基於合作運營研究與發展協會(Association for Cooperative Operations Research & Development,ACORD)用於人壽保險規范的 XML,它定義了健康保險和年金保險需要交換的數據。
為了申請一個新的保險,客戶需要提供一些基本信息。部分信息是在一個 PHP 應用程序中填寫的,還有一部分是在客戶機浏覽器中填寫的。然後,保單存儲在一個 DB2 XML 列中。在 DB2 9 中,XML 類型的列在內部將 XML 數據存儲為一棵解析後的樹,與關系數據存儲在不同的地方。這種方法是 DB2 9 特有的,更早的 DB2 版本則使用關系存儲基礎設施來存儲 XML。
下面是保單 XML 文檔在客戶機與應用程序之間的流程:
·在 Web 客戶機中,客戶更新頁面並單擊 Submit。
·Web 客戶機向 PHP 發出一個 XMLHTTP 請求,以獲得新的空白保單文檔。
·PHP 應用程序打開一個空白的保單文檔,用一個全局惟一標識符(GUID)更新它,然後將該文檔返回給 Web 客戶機。
·Web 客戶機使用 Ajax 捕捉返回的事件,並檢索 XML DOM,然後用 Web 頁面中輸入的信息填充該文檔。
·Web 客戶機使用 XMLHTTP 將更新後的 XML 發送給 PHP 應用程序。
圖 3. 創建新的保單請求的 Web 站點。
圖 3 展示了用於創建新的保單請求的 Web 頁面。當用戶單擊 Submit 按鈕後,JavaScript 函數 submitPolicy() 被調用(見清單 1)。該函數向 PHP 應用程序 createNewPolicy.php 發出一個 HTTP 請求,以獲得一個空白的保單。它還設置一個回調函數 fillPolicy(),用於捕捉從 HTTP 請求返回的事件。
當第一個請求到達中間層的 PHP 應用服務器時,一個新的 XML 保單文檔被裝載到 SimpleXML 對象中。通過使用 SimpleXML API,用 PHP 應用程序中創建的 GUID 更新 TransRefGUID 元素。
header('Content-type: text/xml');
$fileContents = file_get_contents("$basedir/acord.xml");
$dom = simplexml_load_string($fileContents);
$dom->TXLifeRequest->TransRefGUID=$guid;
echo $dom->asXML();
然後,這個文檔被發送到客戶機。
對於本文,我們假設 GUID 是通過某種機制(例如時間和隨機數的組合)創建的。更重要的是理解如何將表示保單的 XML 文檔視作內存中的業務對象層次結構,以及如何使用 SimpleXML API (或 DOM/XPath)來導航和更新這個對象。
填充基本客戶信息
在 Web 客戶機中,fillPolicy() 函數讀取返回的值。現在,包含返回 XML 的內存中表示的 DOM 對象可用於操縱保單文檔。客戶在 Web 頁面上輸入的信息被直接用於更新 DOM。當使用客戶信息更新了保單之後,使用 XMLHTTP 將修改後的 DOM 對象提交回 PHP 應用程序(見清單 2)。即使是 HTML 組件值也是用 DHTMLDocument Object Model (DOM) 讀取的。