DIV CSS 佈局教程網

 DIV+CSS佈局教程網 >> 網頁腳本 >> XML學習教程 >> XML詳解 >> 使用 XQuery 開發 mashup
使用 XQuery 開發 mashup
編輯:XML詳解     

 Web 2.0 應用程序為用戶提供了更動態的體驗,常常使用 AsynchronousJavaScript and XML (Ajax)。加載了 Html 主文檔之後,可以使用 Ajax 更新 Web 內容而不需要刷新整個網頁。使用 AJax,可以把 Web 內容看作是能夠隨時推出的數據片段。此外,客戶端 Javascript 過程能夠自己格式化數據,無論普通文本、XML、JavaScript Object Notation (JSON) 對象還是 Html 片段形式的數據。

  新的 Web 應用程序開發范型遠遠超出了傳統的 “模型-視圖-控制器(MVC)” 模型。不幸的是,很多 AJax Web 應用程序框架,如 Direct Web Remoting (DWR) 和 JavaServer Faces (JSF) 都帶來了一些挑戰。盡管 AJax 框架可以在很多方面簡化應用程序開發,但框架的機制或多或少地控制著 Web 內容。很多現有的 AJax 沒有提供能夠解決現實世界復雜性的統一解決方案,尤其是來自 XML 的數據集成和來自 RSS 提要的內容聯合的要求越來越高。這些新的需求表明在服務器端需要高效的 Web 服務支持。

  為了利用這些變化的技術,可以創建 mashup 應用程序將 Web 內容與 XML 數據和 Web 服務結合起來。我將說明如何使用 XQuery(一種用於 Web 服務的很有前途的技術)和 XML 創建一個 mashup 應用程序。

  這個應用程序允許用戶在當地所有圖書館組成的公共圖書館系統中搜索新書。每個圖書館中,管理員都定期購買新書,但不知道其他公共圖書館是否已經購買了這些書。這個應用程序通過 Web 服務發布和共享它存儲的信息。應用程序從圖書館中匯集了所有的新書資料,為用戶提供了搜索新書的功能。

 XQuery 來救援

  XQuery 是一種萬維網聯盟(W3C)標准,專門為從 XML 文檔中提取信息而設計。它的 XML 處理能力和已有的面向對象編程模型如 Java™ 文檔對象模型(DOM)API 相比有很多優勢。

  簡化服務器端 XML 處理

  可以通過 Javascript 使用 DOM API 來解析 XML。但是,這並非意味著可以用 JavaScript 在客戶端完成所有的 XML 處理。尤其是現在業務邏輯處理變得越來越復雜。如何平衡客戶端和服務器端的 XML 處理是設計 Web 應用程序時要考慮的基本問題之一。XQuery 將復雜的業務邏輯留給了服務器端,這樣做有很多好處。比方說,可以更全面地考慮安全問題,可以更容易地維護應用程序。此外,XQuery 函數還簡化了整個開發過程。

  限制在網絡上傳輸的內容

  設計 Web 應用程序時,必須考慮有多少內容在網絡上傳輸以及傳輸的頻率高還是低。對服務器的每次請求都會產生開銷。應避免對每次按鍵或鼠標移動都發出異步調用。如果不能正確地使用服務器調用,很容易就會讓不必要的網絡流量和負荷使應用程序陷於困境。

  56K 的撥號網絡傳輸 100KB 的 Web 內容需要 14 秒鐘。XQuery 通過減少在網絡上傳輸的內容提供了更好的用戶體驗。比如,為了限制 XML 內容的大小,可以在返回 XML 之前調用標准 XQuery 函數 string-length()。不過這個例子沒有限制 XML 內容的大小,而是通過計算節點數把 XML 元素限制為 100 個 book 項。

  集成多個搜索字段

有時候,Web 搜索使用多個項作為搜索條件。比如,這個示例應用程序為用戶提供了三個選擇。用戶可以輸入其中的一個字段或者多個字段組合(最多三個)。XQuery 函數與 XPath 表達式的結合為實現搜索需求提供了強大的搜索機制。

  不需要另外編程集成業務邏輯

  XQuery 是一種聲明性語言。為了使用 XML 簡化已有數據和服務的集成,它緊湊地封裝了業務邏輯。查詢輸出可以采用用戶定義的格式,這樣不需要另外編程就能很容易地實現業務邏輯。

  示例應用程序

  圖 1 顯示了應用程序設計。服務器響應可以是客戶要求的任何格式,包括 Html 片段、XML、普通文本或者 JSON 對象。內嵌的 XQuery 根據動態搜索條件執行預定義的查詢。在查詢中定義業務邏輯和表示邏輯。XML 數據可以來自多個數據源,如文件系統、數據庫或者表示 Representational State Transfer (REST) Web 服務的 URI。


圖 1. 示例應用程序體系結構
使用 XQuery 開發 mashup

  嵌入 XQuery 引擎

  可以使用簡單的 Java servlet 嵌入 XQuery 引擎。有很多 XQuery 引擎可供選擇,既有廠商提供的也有開放源代碼的。該應用程序使用開放源代碼的 Saxon 8.7(如 清單 1 所示)。


清單 1. 嵌入 Saxon XQuery 引擎
Configuration config = new Configuration(); 
staticQueryContext = new StaticQueryContext(config); 
dynamicQueryContext = new DynamicQueryContext(config); 

  收集 XML 數據和定義數據格式

  為了收集 XML 數據,需要考慮 XML 數據來自何處、是否需要使用文檔類型定義(DTD)或模式、是否需要執行 XML 驗證。該程序對 XML 數據格式使用了一個 DTD,並假定在 XQuery 處理之前所有的數據源都是對該 DTD 有效的 XML 文檔。清單 2 給出了 XML 數據格式的一個例子。

清單 2. 示例 XML 數據格式
<?XML version="1.0" encoding="UTF-8"? > 
<!DOCTYPE library SYSTEM "dtd/book.dtd"> 
<booklist> 
<book category="COOKING"> 
 <title lang="en">Everyday Italian</title> 
 <authors> 
  <author>Giada De LaurentIIS</author> 
 </authors> 
 <isbn></isbn> 
 <numberCopies>1</numberCopIEs> 
 <status>On Shelf</status> 
 <year>2005</year> 
 <library>John C. Hart Library</library> 
 <price>30.00</price> 
</book> 
... 
</booklist> 

  用業務邏輯定義 XQuery 查詢

  在 XQuery 業務邏輯中,使用三個字段搜索圖書,需要建立六種查詢策略。此外,還需要考慮沒有提供搜索參數的默認場景。與傳統的 Web 應用程序框架不同,Xquery 很容易在查詢文件中構造業務邏輯。如果需要可以在以後修改該文件,甚至不需要停止應用程序的運行。比方說,可以將查詢改為查找最近三年中出版的新書。

  XML 數據可能有不同的來源,book_collection.xml 文件定義了一個 XML 數據集合。一個 XML 數據來源是這個應用程序本身:http://localhost:9080/bookinfor/newbooks_localhost.xml。測試該應用程序時,一定要將 Web 應用程序上下文根目錄設置正確,如 bookinfor。清單 3 給出了一個 XML 數據集合。


清單 3. XQuery 集合
<collection > 
<doc href="newbooks_library_01.XML"/> 
<doc href="newbooks_library_02.XML"/> 
<doc href="newbooks_library_03.XML"/> 
<doc href="newbooks_library_04.XML"/> 
<doc href="http://localhost:9080/bookinfor/newbooks_localhost.XML"/> 
</collection> 

設計 XQuery Web 應用程序時務必要考慮性能問題。在這裡,我把搜索輸出的阈值設為 100 本書。與傳統的對象編程如 Java 相比,XQuery 實現業務邏輯不需要服務器端的開發。在處理大量 XML 數據時,可以把內嵌 XQuery 引擎與 IBM DB2 Viper 版結合起來,它能夠處理大量 XML 內容,最高可達 2GB。清單 4 顯示了 booklist_app.xql 文件中的應用程序業務邏輯。


清單 4. 包含簡單業務邏輯的 XQuery
(: -------------------------- :) 
(: declares ......:) 
(: -------------------------- :) 
declare namespace local = "http://localhost/ns"; 
declare variable $title as xs:string external; 
declare variable $author as xs:string external; 
declare variable $year as xs:string external; 
declare variable $emptymsg as xs:string external; 
declare variable $oversizedmsg as xs:string external; 
declare variable $outputformat as xs:string external; 
(: -------------------------- :) 
(: functions         :) 
(: -------------------------- :) 
declare function local:error_vIEw($helpmsg as xs:string) { 
  if($helpmsg) then $helpmsg 
  else ('<report status="0">Please call 1-800-123-4567</report>') 
}; 
declare function local:Html_vIEw($doc) { 
  <table> 
  <tr> <td>Library Name</td> 
     <td>Book Title</td> 
     <td>Number of CopIEs</td> 
     <td>Status</td> 
  </tr> 
  {  for $book in $doc/book 
      where $book/title/@lang="en" 
      order by $book/library 
    return <tr> 
          <td>{$book/library}</td> 
          <td>{$book/title/text()}</td> 
          <td>{$book/numberCopIEs}</td> 
          <td>{$book/status}</td> 
        </tr> 
  } 
  </table> 
}; 
(: -------------------------- :) 
(: the business logic     :) 
(: -------------------------- :) 
let $docs := ('bookinfor/book_collection.XML') 
let $searchdoc := ( 
<report status='1'> 
{ 
  if($title and $year and $author) then ( 
    for $doc in collection($docs)//booklist/book[contains(title,$title) 
        and (year = $year)] 
    where contains($doc//authors, $author) 
    return $doc 
  ) else if($title and $year ) then ( 
    for $doc in collection($docs)//booklist/book[contains(title,$title) 
        and (year = $year)] 
    order by $doc//booklist/book/title 
    return ($doc) 
  ) else if($title and $author ) then ( 
    for $doc in collection($docs)//booklist/book[contains(title,$title)] 
    where contains($doc//authors, $author) 
    order by $doc//booklist/book/title 
    return ($doc) 
  ) else if($author and $year ) then ( 
    for $doc in collection($docs)//booklist/book[(year=$year)] 
    where contains($doc//authors, $author) 
    order by $doc//booklist/book/title 
  return ($doc) 
  ) else if($title) then ( 
    for $doc in collection($docs)//booklist/book[contains(title,$title)] 
    order by $doc//booklist/book/title 
    return ($doc) 
  ) else if($author) then ( 
    for $doc in collection($docs)//booklist/book 
    where contains($doc//authors, $author) 
    order by $doc//booklist/book/title 
    return ($doc) 
  ) else if($year) then ( 
    for $doc in collection($docs)//booklist/book[(year=$year)] 
    order by $doc//booklist/book/title 
    return ($doc) 
  ) else ( 
    for $doc in collection($docs) 
    return ($doc//booklist/book) 
  ) 
} 
</report> 
) 
(: -------------------------- :) 
(: return results       :) 
(: -------------------------- :) 
return if(count($searchdoc//book) eq 0) then local:error_vIEw($emptymsg ) 
    else if(count($searchdoc//book) gt 100) 
      then local:error_vIEw($oversizedmsg) 
      else if($outputformat eq $Html) 
        then local:Html_vIEw($searchdoc) 
        else $searchdoc 

在應用程序中調用 XQuery 查詢

  為了在內嵌引擎中執行查詢,需要設置相關的參數並預編譯查詢。查詢執行後,最終結果發送回 Web 客戶機。客戶端 JavaScript 代碼組裝數據並呈現給用戶。請注意,這個示例應用程序將目錄 c:/tmp/xmldatasources/ 設置為靜態的查詢上下文。一定要保證 bookinfor 目錄在其中,並在測試該應用程序之前將 XML 數據文件復制過去。清單 5 顯示了內嵌的 XQuery 調用。


清單 5. 在應用程序中調用 XQuery 查詢
dynamicQueryContext.setParameter("emptymsg", "No results exist!"); 
dynamicQueryContext.setParameter("oversizedmsg", 
                  "Too many results, please refine querIEs"); 
   
staticQueryContext.setBaseURI("c:/tmp/XMLdatasources/"); 
fileReader = new FileReader(request.getRealPath("/")+ "/querIEs/booklist_app.xql"); 
queryExpression = staticQueryContext.compileQuery(fileReader);  
   
writer = new StringWriter(); 
StreamResult result = new StreamResult(writer); 
Properties props = new PropertIEs(); 
queryExpression.run(dynamicQueryContext, result, props); 
retContent = writer.getBuffer();    

  結束語

  需要注意的是,XQuery 技術仍然存在一些局限性,學起來也不是很簡單。要記住,沒有一種技術能夠解決所有的業務問題。很可能仍然需要把 XQuery 與其他技術(如 XPath 和 XSLT)結合起來才能滿足要求。

  雖然 XQuery 還沒有成為最終標准,但它的主要特性和功能已經引起了很大關注。它有強大的 XML 處理功能,而且在建立 marshup 應用程序方面顯示了很大的潛力。一旦用 XQuery 實現了您的動態 Web 應用程序,可以很快地擴展您的網站,並以相對簡單和敏捷的方式達到您的業務目標。

  本文示例源代碼或素材下載



 

 

XML學習教程| jQuery入門知識| AJAX入門| Dreamweaver教程| Fireworks入門知識| SEO技巧| SEO優化集錦|
Copyright © DIV+CSS佈局教程網 All Rights Reserved