xpath 函數大全


在本文的第一部分中,我們介紹了XPath並討論了各種各樣的從簡單到復雜的XPath查詢。 通過把XPath查詢應用到XML示例文件,我們詳細說明了各種重要的XPath定義比如location step、context node、location path、axes和node - test。 我們然后討論了多個簡單查詢組合成的復雜的XPath查詢。 我們還討論了無線二進制XML(WBXML)--XML在無線應用領域的對應物--的抽象結構。 最后我們介紹一個簡單的XPath處理引擎的設計。

  在這一部分里,我們打算討論XPath的更進一步的特性--在一個XML文件上執行復雜檢索的操作。 我們將討論謂詞或者過濾器查詢以及在XPath中的函數的使用。我們將介紹各種的用於處理WSDL和WML的XPath查詢。 我們還將增強我們的XPath引擎的功能,使之包括謂詞、函數和不同的數據類型。

  過濾查詢和謂詞

  讓我們從一個將返回任何XML文件當中的根節點的簡單查詢開始:

  ./node()

  我們可以更進一步,使用另一個簡單查詢,選擇根節點的全部的直接子節點:

  ./node()/*

  如果你想要得到所有的是根節點的直接子節點並且只有一個type屬性的節點,那么該怎么辦呢? 那么就使用下面的這個查詢:

  ./node()/*[attribute::type]
 
  在代碼段1中,這個查詢將返回binding元素。 由此可見,寫在方括號之內的代碼attribute::query擔負一個過濾器的功能。 XPath中的過濾器被稱作謂詞(predicate),寫在方括號內。 一個謂詞作用在一個結點集上--在這個例子中,結點集由根節點的所有的直接子節點組成---應用過濾條件(在這里,結點肯定有一個type屬性)到結點集上。 產生的結果就是一個經過過濾的結點集。

  謂詞可以從簡單到很復雜。 也許XPath謂詞的簡單形式就像下面的查詢中的只是一個數字,返回根元素的第二個子節點(message元素):

  ./node()/*[2]

  查詢語句./node()/message[attribute::name="TotalBill"]/text() 將尋找根元素的一個屬性name值為TotalBill的特定的message子節點。 查詢將返回特定的message元素的所有文本結點。 這個查詢將返回代碼段1中兩個message元素中的第二個。

  XPath 函數

  假定你想要回答下面對代碼段1中的WSDL文件所提出的問題:

  1. 最后一個operation元素的name屬性的值是什么?

  2.定義元素有多少個message子元素?

  3. 根元素的第一個子元素的名稱是什么?

  last()函數

  last()函數將總是指向結點集的最后一個結點。 下面的這個查詢,當被應用於代碼段1中的WSDL文件的時候,將返回第二message元素(即 名稱是TotalBill的message元素):

  ./node()/message[last()]

  注意下面的這條查詢也返回相同的message元素:

  ./node()/message[2]

  這兩個查詢之間唯一的區別就是我們使用數字2來代替last()方法。 事實上在本例中last()函數返回的值就是2(特定location step的結點集中的結點數)。 把這兩個相同的查詢應用到代碼段2中的WSDL文件,這次你會發現兩個查詢沒有返回相同的結果。 代碼段2中有三個message元素,所以現在last()函數返回數字3。
注意本討論中的last()函數總是返回一個數字。

  position()函數

  如果你把下面的這些查詢應用到代碼段2中的WSDL文件,

  ./node()/message[1]/part

  ./node()/message[2]/part

  ./node()/message[3]/part

  它們將分別返回message元素的第一個、第二個和第三個part子元素。 由此可見節點集中的每個節點都有一個位置。 第一個節點的位置是1,第二個節點的位置是2,以此類推。

  如果你想要得到除第二個以外的所有的message元素,你該怎么辦? 你可以使用position()函數取得一個節點的位置。 下面的這條查詢將返回代碼段2中的第一個和第三個message元素:

  ./node()/message[position()!=2]

  position()函數只是返回指定值所表示的節點的位置。 謂詞[position()!=2] 把所有的message元素的位置和2做比較,然后找出位置不是2的節點。
  count()函數
  
  代碼段1中的portType元素有多少個message子元素? 數一數你就發現有兩個message元素。 在XPath中解決"多少個"這種問題是一個二步的操作。 首先,寫一個用來找到你想要統計的所有的子元素的XPath查詢。 然后地像下面給出的那樣,把 XPath查詢傳送到count()函數中:

  步驟1: ./node()/message

  步驟2: count(./node()/message)

  count()函數統計XPath查詢所得到的節點集中的節點數,並返回這個節點數。

  name()、local-name()和namespace-uri()函數

  如果把下面的查詢應用到代碼段1中的WSDL文件的話,那么會出現什么情況呢?

  ./node()/*[5]

  它返回根元素的第五個子元素(即service元素)。 service元素本身是一個完整結構,也包含子元素。 因此,這個XPath查詢的返回值實際上是一個XML節點而不僅僅是一個元素名。

  name()函數返回XML節點的名稱。 例如,下面的查詢應用到代碼段1中將返回字符串"service":

  name(./node()/*[5])

  同樣,下面的查詢將返回字符串"wsd:definitions"(使用域名空間前綴的根元素的全名):

  name(./node())

  local-name()和names

pace-uri()函數與name()函數類似,除了local-name方法只返回不帶域名空間前綴的元素的局部名稱,而namespace-uri函數僅僅返回域名空間URI。舉例來說,請在代碼段1中試驗下面的查詢:

  local-name(./node())

  namespace-uri(./node())

  第一個查詢返回一個字符串" definitions",而第二個查詢返回" http://schemas.XMLsoap.org/wsdl/ "。

  String函數

  我們已經知道name()、local-name()和namespace-uri()函數返回字符串。 XPath提供了許多函數用於處理字符串,比如string()、 substring()、substring-before()、 substring-after()、 concat()、starts-with()等等。 下面給出了一個例子來演示一下如何使用string()函數:

  string(./node()/*[2]/part/attribute::name)

  上面的這條查詢將尋找根元素的第二個子元素,然后它將得到根元素的第二子元素的所有的part子元素。 接着它將尋找part子元素的name屬性,最后它把name屬性的值轉換為一個字符串格式。 當把這條語句應用到代碼段1中的時候,它將輸出bill。

  XPath也提供一些布爾函數,返回"true/false",研究一下下面的這條查詢:

  boolean(./node()/message)

  當把它應用到代碼段1的時候,它返回true。 這是因為boolean()函數判斷一個XPath查詢產生的節點集是否為空(在我們的例子中,根元素包含兩個message子元素)。 如果是空,boolean()函數返回false,否則返回true。


  一個復雜的WSDL處理實例

  下面的WSDL處理方案使用了我們前面討論過的所有的XPath概念。 這個方案的檢索要求如下:

  尋找一個service元素,這個元素是definitions元素(根元素)的一個直接子元素,並且name屬性與definitions元素的name屬性匹配。 然后察看service元素,尋找一個port元素,這個port元素的binding屬性與definitions元素的直接子元素binding的name屬性匹配。

  這個WSDL過程可以用四步完成:

  1. 查找definitions元素的name屬性值。 下面給出的XPath查詢(從代碼段中返回字符串BillingService)執行這步操作:

  string(//node()[1]/@name)

  2. 然后查找name屬性匹配definitions元素的name的service元素。 下面的查詢將返回所需要的service元素:

  ./node()[1]/service[@name=string(//node()[1]/@name)]

  3. 然后查找binding元素的name屬性值:

  string(//node()[1]/binding/@name)

  4. 最后尋找需要的port元素:

  ./node()[1]/service[@name=string(//node()[1]/@name)]

  /port[@binding=string(//node()[1]/binding/@name)]

  這個實例說明XPath謂詞可以包含簡單邏輯條件,函數調用乃至完整的XPath查詢。

  使用XPath處理WML

  WML是WAP Forum定義的一種XML語言。 WML為小型設備的顯示提供了一種表現格式。 WML對於一個小型設備就好像HTML對於一台個人電腦一樣。

  想象一下,一個WML文件是由一組卡片(card)組成,每個卡片由一個card元素封裝。 代碼段3是一個簡單WML文件,只包含兩個card元素。

  下面的XPath查詢將返回代碼段3中包含在第一個卡片之內(這卡片id是" first")的所有的p(paragraph)元素:

  ./node()/card[string(@id)="first"]/p

  下面這個查詢返回第二個卡片中的第一段的文本內容:

  string(./node()/card[string(@id)="second"]/p[1]/text())

  實現XPath謂詞與函數

  我們現在將看看如何在我們前面的那個簡單的XPath引擎中插入謂詞與函數的支持。

  四個偽代碼類XPathExpression(代碼段4)、XPathLocationStep(代碼段5)、XPathResult(代碼段6)和Predicate(代碼段7)組成了支持謂詞與函數的更新的版本。 我們在上一篇文章介紹的XPath引擎的基礎上,增加了下列功能,使之更加強大:

  1. XPath可以返回各種類型的數據。 XPath可以返回節點、字符串、數字和布爾變量。 我們設計的XPath引擎只支持XML節點作為返回數據類型。 我們現在已經提供了一個名為XPathResult(見代碼段6)的類來支持不同的數據類型。 基於我們的設計的實現需要擴展為每種數據類型分別地擴展XPathResult。

  2. 更新的設計現在包括一個支撐函數的結構。 一個函數調用可以發生在一個XPath查詢開始時,也可以發生在任何XPath location step。 因此,XPathExpression類(代碼段4)和XPathLocationStep類(代碼段5)現在都添加了對函數調用的支持。

  3. 我們還提供了一個單獨的類用於支持謂詞(見代碼段7)。 一個謂詞可以只由一個邏輯條件組成也可以由一個完整的XPath查詢組成。 因此,Predicate類構造器將判斷謂詞到底是一個完整的查詢還是僅僅只是一個條件。 如果是一個完整的XPath查詢,Predicate表達式將實例化一個新的XPathExpression對象,否則它將只是取得邏輯條件的值。

  小結

  在前面,我們討論XPath中謂詞與函數的語法和使用。 我們介紹WSDL和WML處理的實例並說明了如何構成更加復雜的XPath查詢。 最后,我們增強了在第一篇文章中介紹的XPath引擎的功能。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM