DIV CSS 佈局教程網

 DIV+CSS佈局教程網 >> 網頁腳本 >> XML學習教程 >> XML詳解 >> 使用 XML: XPath 2.0 入門
使用 XML: XPath 2.0 入門
編輯:XML詳解     

對舊標准的一次重大更新

  雖然還是候選推薦標准,但 XPath 2.0 即將得到正式批准。這是 1999 年以來對 XPath 推薦標准的第一次修訂,市場對此抱有很大期望,事實上一些工具已經開始實現最新的草案。這些修改是根本性的,我預料到時候人們也許會把 XPath 1.0 看作是 XPath 2.0 的草案。

  XPath 2.0 推薦標准是 XSLT 2.0 和 XQuery 1.0 的基礎。這兩種語言都以 XPath 作為核心查詢引擎,並增加了一些語句來格式化查詢結果(請參閱 參考資料)。

  XPath 1.0 和 XPath 2.0 之間的區別包括:

  基於序列而非節點集的新的數據模型

  綁定變量的能力,以前的變量綁定在宿主語言(XSLT)中

  完全支持 XML Schema 數據類型

  很多新功能,包括正則表達式、日期/時間和字符串操作

  注釋,雖然不是一個重要的特性,但是在調試查詢時很方便:測試時可以注釋掉路徑的一部分

  本文主要討論新的數據模型,具體來說即序列的使用,因為對表達能力來說這是最根本的變化。

  XPath 2.0 中的序列

  XPath 2.0 將一切都作為序列來處理。序列 是不同類型的項組成的有序集合。項可以是 XML 文檔中的節點或者原子值。原子值可以是 XML Schema 推薦標准中定義的任何類型,包括復雜類型。在 XPath 中聲明一個序列,只需要把項用逗號分開,整個序列用括號括起來:

  (2, 'declencheur', 5.10)

  實際上,基本上所有有效的 XPath 1.0 請求在 XPath 2.0 中仍然是有效的。換句話說,XPath 2.0 保留了熟悉的 XPath 1.0 語法:路徑仍然由正斜槓(/)分開的定位步組成,如:

  /po:PurchaSEOrder/po:ProductList/po:Name。

  但是,在 XPath 2.0 中定位步表示的是序列(重復一次,這些項可以是 XML 節點)中的項而不是樹中的節點(XPath 1.0 數據模型)。


 

XPath 2.0 中的每個概念都因序列而改變了。比如,XPath 1.0 中接受節點集的函數改為處理序列。

  既然 XML 文檔是層次化的,XPath 1.0 模型(樹結構)不是更合理嗎?但它有自己的局限性,因為 XPath 不能生成樹,所以不能把一次請求的結果傳遞給另一個請求作進一步處理。不能編寫像 SQL 那樣復雜的請求。

  使用序列

  如前所述,仍然使用 XPath 1.0 語法,但是 XPath 2.0 也引入了一些專門用於序列的新語句。首先來看一看 for 表達式,顧名思義,它用於循環遍歷序列中的項。

  典型的 for 表達式如清單 1 所示:

  清單 1. XPath 2.0 例子

for $line in /po:PurchaSEOrder/po:OrderLines/po:Line
  return $line/po:Price * $line/po:Quantity

  該 XPath 將用於清單 2 所示的訂單。它計算訂單中每一訂單行的總金額並返回下面的序列:

  (29.99, 89.98, 80, 3.1)

  清單 2. 訂單(示例 XML 文檔)

<?XML version="1.0" encoding="ISO-8859-1"?>
<po:PurchaSEOrder XMLns:po="http://www.marchal.com/2006/po">
  <po:Buyer>Pineapplesoft<po:Buyer>
  <po:Seller>Bookstore<po:Seller>
  <po:OrderLines>
   <po:Line>
     <po:Code type="ISBN">0-7897-2504-5<po:Code>
     <po:Quantity>1<po:Quantity>
     <po:Description>XML by Example<po:Description>
     <po:Price>29.99<po:Price>
   </po:Line>
   <po:Line>
     <po:Code type="ISBN">0-672-32054-1</po:Code>
     <po:Quantity>2<po:Quantity>
     <po:Description>ApplIEd XML Solutions<po:Description>
     <po:Price>44.99</po:Price>
   </po:Line>
   <po:Line>
     <po:Code type="ISBN">2-10-005763-4<po:Code>
     <po:Quantity>2<po:Quantity>
     <po:Description>Huit Solutions Concrètes avec XML et Java</po:Description>
     <po:Price>40.00<po:Price>
   <po:Line>
   <po:Line>
     <po:Quantity>1<po:Quantity>
     <po:Description>Internet Magazine<po:Description>
     <po:Price>3.10<po:Price>
   <po:Line>
  </po:OrderLines>
<po:PurchaSEOrder><

 清單 1 中的關鍵字是 for,它遍歷行序列並將每個項(每一行)綁定到變量 $product。

  該路徑使用類似 XPath 1.0 的定位步(po:PurchaSEOrder/po:OrderLines/po:Line)選擇該序列。

  然後是表達式的返回部分。Return 動態創建一個序列。基本上就是對循環中的每個項在輸出序列中增加零個、一個或多個項。

  返回序列很重要,因為序列可以通過 XPath 進一步處理。比如,通過將返回的序列傳遞給 sum() 函數來計算訂單總值非常簡單。sum() 是一個 XPath 1.0 函數,擴展後可以處理序列,如清單 3 所示:

  清單 3. 處理 XPath 的返回結果

fn:sum(for $line in /po:PurchaSEOrder/po:OrderLines/po:Line
  return $line/po:Price * $line/po:Quantity)

  原來的方式

  清單 4 的算法和 清單 3 類似,不過采用 XPath 1.0 和 XSLT 1.0 實現:

  清單 4. 用 XPath 1.0 計算訂單總值

<xsl:stylesheet XMLns:xsl="http://www.w3.org/1999/XSL/Transform"
        XMLns:po="http://www.marchal.com/2006/po"
        XMLns:exslt="http://exslt.org/common"
        version="1.0">
<xsl:output method="text"/>
<xsl:template match="/">
  <xsl:variable name="lines">
   <xsl:for-each select="/po:PurchaSEOrder/po:OrderLines/po:Line">
     <line-total><xsl:value-of select="po:Price * po:Quantity"/><line-total>
   <xsl:for-each>
  </xsl:variable>
  <xsl:value-of select="sum(exslt:node-set($lines)/line-total)"/>
<xsl:template>
</xsl:stylesheet>

 清單 4 首先計算每一行的總金額然後將結果傳遞給 sum() 函數。但是在 XPath 1.0 中,變量必須在宿主語言(這裡是 XSLT)中聲明,因此在變量 lines 中創建了臨時結果集。然後將變量的內容提供給第二個 XPath 表達式計算訂單總值。

  比較 清單 3 和 清單 4,可以看到 XPath 2.0 的表達能力明顯提高。清單 4 使用了兩個 XPath 語句而不是一個,並且依賴於宿主語言(XSLT)與中間結果通信。清單 4 可讀性比較差,因為將請求分在兩個 XPath 語句,也限制了查詢優化的可能性。

  條件表達式

  XPath 2.0 還引入了條件表達式(if),如清單 5 所示。語法的含義很明確:根據括號中表達式的計算結果為 true 還是 false,表達式返回 then 或 else 部分。

  清單 5. 條件表達式

if(/po:PurchaSEOrder/po:Seller = 'Bookstore') then 'ok' else 'ko'

  限定性表達式

  如果不討論限定性表達式關於序列的討論就是不完整的。簡而言之,限定性表達式 就是作用於整個序列的測試。限定性表達式有兩種:every 和 some。

  清單 6 是一個 every 表達式。包括兩部分;首先將序列綁定到變量(和循環一樣),然後指定序列中的項必須滿足的條件。限定性表達式和循環之間的差別在於條件表達式 返回 Boolean 值,而循環 返回序列。

  具體來說,如果序列中的每一項都符合條件則 every 表達式返回 true,如果序列中至少有一項滿足條件表達式則 some 表達式返回 true。

  清單 6. 限定性表達式

every $line in /po:PurchaSEOrder/po:OrderLines/po:Line satisfIEs $line/po:Code

  如果對 清單 2 中的文檔運行 清單 6 將返回 false,因為第四行沒有 po:Code 元素。如果將關鍵字 every 替換為 some,表達式就會返回 true,因為至少有一行包含 po:Code 元素。

  無限組合

  XPath 2.0 的強大在於能夠將表達式組合起來創建復雜的請求。清單 7 用不同的公式計算訂單總值:只計算包含產品代碼的那些行,其他行被忽略掉(大概因為這些產品不能發貨)。代碼很簡單,因為增加一個 if 表達式就足夠了,如果不滿足條件,該表達式就返回 empty 序列。

  清單 7. 組合表達式

fn:sum(for $line in /po:PurchaSEOrder/po:OrderLines/po:Line
  return if($line/po:Code) then $line/po:Price * $line/po:Quantity else ())

  總之,感謝 XPath 2.0 基於序列的新數據模型,編寫復雜請求大大簡化了。過去需要很多 XSLT 代碼的請求現在可以單純用 XPath 編寫。




 

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