XML學習筆記6——XPath語言

  在上一篇筆記的結尾,咱們接觸到了兩個用於選擇XML文檔中特定範圍的元素<selector>和<field>,這兩個元素的取值都是XPath表達式,那麼,什麼是XPath呢?簡單的說,XPath是用於在XML文檔中查找信息的語言,可用來在XML文檔中遍歷元素和屬性,不少XML的相關技術好比XSLT、XQuery、XPointer等都是構建於XPath的基礎之上,在這一篇筆記中,就來學習一下XPath語言。node

一、相關術語web

(1)節點(Node):格式良好的XML文檔均可以轉換爲一個樹型結構,XPath中的節點也就是這個樹型結構中的節點。概況起來,有以下所列的七種節點:編程

節點類型 說明
XML文檔根節點 XML文檔的根稱爲文檔節點或根節點
元素節點 一個元素的開始標籤、結束標籤,以及之間的所有內容總體稱之爲元素節點
屬性節點 元素的每一個屬性都構成一個屬性節點,包括屬性名稱和屬性值兩個部分,屬性節點必須依附於元素節點
命名空間節點 XML文檔中的xmlns:prefix屬性稱之爲命名空間節點,注意和屬性節點的區別
文本節點 XML元素中間的字符數據,包括CDATA段中的字符數據
註釋節點 XML文檔裏<!--和-->包含的註釋部分構成註釋節點
處理指令節點 XML文檔的處理指令部分構成處理指令節點

(2)基本值(也稱爲原子值,Atomic Value):專門用於表示簡單的字面值,如整數值,字符串等。基本值能夠當成沒有父節點也沒有子節點的節點。編程語言

(3)項目(Item):一個項目表明一個基本值或一個節點。函數

(4)節點集和序列(Sequence):XPath表達式能夠表示多個節點,多個節點的組合在XPath1.0中稱爲節點集,而在XPath2.0中添加了一個序列的術語,便可以表明普通的項目,也能夠表明節點集。學習

(5)節點關係:測試

節點關係 說明
父節點Parent 每一個元素或屬性都有一個父節點
子節點Children 元素節點能夠有0個、1個或多個子節點
兄弟節點Sibling 父節點相同的節點稱之爲兄弟節點
祖先節點Ancestor 節點的父節點、父節點的父節點一直到根節點
後代節點Descendant 節點的子節點,子節點的子節點......

(6)相對路徑和絕對路徑:與操做系統中的路徑相似,XPath中也有相對路徑和絕對路徑,絕對路徑以斜線(/)開頭,老是從根節點開始匹配,而相對路徑則不會以斜線開頭,從當前路徑開始匹配。spa

二、XPath語法操作系統

  XPath使用路徑表達式來訪問XML中的節點或節點集,每一個XPath表達式老是由一個或多個步(step)組成的,多個步直接使用斜線分隔。在XPath中,步的語法格式以下:debug

::節點測試[限定謂語]

也就是說,每一個步都經過了3次篩選,第一次是使用「」選擇節點方向,第二次使用「節點測試」選取在指定軸方向上的部分節點,第三次則是使用「限定謂語」來對選中的節點進一步過濾。

(1)軸:在XPath中,有下面列表中的各類軸:

簡化寫法 說明
ancestor   選取當前節點的全部先輩(父、祖父等)節點
ancestor-or-self   選取當前節點的全部先輩(父、祖父等)節點以及當前節點自己
attribute 選取當前節點的全部屬性節點,若是當前節點不是元素節點,則attribute軸方向上的節點集爲空
child 省略不寫  選取當前節點的全部子節點
descendant //  選取當前節點的全部後代節點(子、孫等)
descendant-or-self   選取當前節點的全部後代節點(子、孫等)以及當前節點自己
following   選取文檔中當前節點的結束標籤以後的全部節點,不會包含當前節點的後代節點和屬性節點
following-sibling   選取文檔中當前節點的結束標籤以後的全部兄弟節點
namespace   選取當前節點的全部命名空間節點,當前節點不是元素節點,則namespace軸方向上的節點集爲空
parent .. 選取當前節點的父節點
preceding   選取文檔中當前節點的開始標籤以前的全部節點,不會包含當前節點的後代節點和屬性節點
preceding-sibling   選取文檔中當前節點的開始標籤以前的全部兄弟節點
self . 選取當前節點

(2)節點測試:節點測試用於從指定軸方向上選取所匹配的特定的節點,在XPath中,經常使用的節點測試語法以下表所示:

節點測試 說明
nodename

從指定軸方向上選出具備nodename的節點

如child::book選擇當前節點的全部book子節點

   descendant::book選擇當前節點的全部book後代節點(包括book子節點、孫子節點等)

node() 選擇指定軸匹配的全部類型的節點
text()

選擇指定軸匹配的全部文本類型的節點

如child::text()選擇當前節點的全部文本子節點

  descendant::text()選擇當前節點的全部文本後代節點(包括文本子節點、文本孫子節點等)

comment() 選擇指定軸匹配的全部註釋節點
processing-instruction 選擇指定軸匹配的全部處理指令節點
* 節點測試中的通配符,表示全部,也即不進行過濾

(3)限定謂語:每一個步中能夠接受0個或多個限定謂語,用於進一步過濾所選取的節點集,限定謂語放在方括號中,一般限定謂語返回一個boolean值。看下面的一些例子:

路徑表達式 結果
/bookstore/book[1] 選取屬於 bookstore  元素的子元素的第一個 book 元素。
/bookstore/book[last()] 選取屬於 bookstore  元素的子元素的最後一個 book 元素。
/bookstore/book[last()-1] 選取屬於 bookstore  元素的子元素的倒數第二個 book 元素。
/bookstore/book[position()<3] 選取最前面的兩個屬於 bookstore 元素的子元素的 book 元素。
//title[@lang] 選取全部擁有名爲 lang 的屬性的 title 元素。
//title[@lang='eng'] 選取全部 title 元素,且這些元素擁有值爲 eng 的 lang 屬性。
/bookstore/book[price>35.00] 選取 bookstore 元素的全部 book 元素,且其中的 price 元素的值須大於 35.00。
/bookstore/book[price>35.00]/title 選取 bookstore 元素中的 book 元素的全部 title 元素,且其中的 price 元素的值須大於 35.00。

三、運算符

  從上面的實例中能夠看到,在限定謂語中,還可使用運算符、表達式,還有不少內置的函數供使用。這一小節先看看XPath中支持的運算符:

(1)算術運算符:加(+)、減(-)、乘(*)、除(div)、取模(mod)

  算術運算符很是簡單,可是須要注意幾點:

A、由於減號實際上也就是中劃線,而中劃線在XML中是合法的標識符號,從而帶來了歧義,因而XPath強制規定,使用減號的時候,須要先後各加一個空格。

B、在XPath中,全部的數值都是64位的double類型,即使直接書寫成0、100;另外,XPath還有幾個特殊的數值:正無窮大、負無窮大、非數。

C、在運算時,若是操做數不是數值類型,會自動轉換,下面的比較運算符、邏輯運算符若是有必要也會發生相應的自動類型轉換。

(2)比較運算符:等於(=)、不等於(!=)、小於(<)、小於或等於(<=)、大於(>)、大於或等於(>=)

  須要注意的是,不像其它編程語言,這裏表示相等只須要一個等於號。

(3)邏輯運算符:與(and)、或(or)

(4)集合運算符:並集(|)

四、表達式

(1)for表達式:用於循環訪問序列中的每一個項,並對每項進行一次計算,最後將每項計算獲得的結果組合成序列後返回,語法格式以下:

for $var in sequence return rtExpression

實際上,這裏的for更相似於js中的foreach。還可使用下面的形式遍歷多個序列:

for $var1 in sequence1, $var2 in sequence2 return fn($var1,$var2)

(2)if表達式:用於處理分支,根據不一樣條件獲得不一樣的返回值,語法格式以下:

if (condition1)
then rtVal1
[else if (condition2)
then rtVal2
...]
else
otherVal

(3)some表達式:迭代中只要有一項知足條件就返回true,不然返回false,語法格式以下:

some $var in sequence satisfies condition

(4)every表達式:迭代中只有有一項不知足條件就返回false,不然返回true,語法格式以下:

every $var in sequence satisfies condition

五、內置函數庫

  在XPath中還有大量的內置函數,用於加強相關功能,這些內置函數能夠參考:XPath函數。我在下面也抄錄一份供參考:

分類 函數 說明
存取函數 fn:node-name(node) 返回參數節點的節點名稱。
fn:nilled(node) 返回是否拒絕參數節點的布爾值。
fn:data(item.item,...) 接受項目序列,並返回原子值序列。
  • fn:base-uri()
  • fn:base-uri(node)
返回當前節點或指定節點的 base-uri 屬性的值。
  • fn:document-uri()
  • fn:document-uri(node)
返回當前節點或指定節點的 document-uri 屬性的值。
錯誤和跟蹤函數
  • fn:error()
  • fn:error(error)
  • fn:error(error,description)
  • fn:error(error,description,error-object)

例子:error(fn:QName('http://example.com/test', 'err:toohigh'), 'Error: Price is too high')

結果:向外部處理環境返回 http://example.com/test#toohigh 以及字符串 "Error: Price is too high"。

fn:trace(value,label) 用於對查詢進行 debug。
數值函數 fn:number(arg)

返回參數的數值。參數能夠是布爾值、字符串或節點集。

例子:number('100')

結果:100

fn:abs(num) 返回參數的絕對值。
fn:ceiling(num) 返回大於或等於 num 參數的最小整數。
fn:floor(num) 返回小於或等於 num 參數的最大整數。
fn:round(num) 把 num 參數四捨五入爲最接近的整數。
fn:round-half-to-even()

返回最接近參數num的偶數

例子:round-half-to-even(0.5) 結果:0

例子:round-half-to-even(1.5) 結果:2

例子:round-half-to-even(2.5) 結果:2

字符串函數 fn:string(arg) 返回參數的字符串值。參數能夠是數字、邏輯值或節點集。 
fn:codepoints-to-string(int,int,...)

根據一個Unicode值序列序列返回字符串。

例子:codepoints-to-string((84, 104, 233, 114, 232, 115, 101))

結果:'Thérèse'

注意:該函數的參數是一個Unicode值序列,所以必須用括號將參數括起來

fn:string-to-codepoints(string) 根據字符串返回每一個字符所對應的Unicode值的序列。
fn:codepoint-equal(comp1,comp2) 根據 Unicode 值序列比較,若是 comp1 的值等於 comp2 的值,則返回 true,不然返回 false。 
  • fn:compare(comp1,comp2)
  • fn:compare(comp1,comp2,collation)

根據對照規則,comp1小於comp2返回 -1;comp1等於comp2,返回0;comp1大於comp2返回1。

fn:concat(string,string,...) 返回字符串的拼接。
fn:string-join((string,string,...),sep) 使用 sep 參數做爲分隔符,來返回 string 參數拼接後的字符串。
  • fn:substring(string,start,len)
  • fn:substring(string,start)

返回從 start 位置開始的指定長度的子字符串。第一個字符的下標是 1。

若是省略 len 參數,則返回從位置 start 到字符串末尾的子字符串。

  • fn:string-length(string)
  • fn:string-length()
返回指定字符串的長度。若是沒有 string 參數,則返回當前節點的字符串值的長度
  • fn:normalize-space(string)
  • fn:normalize-space()
刪除指定字符串的首尾空白,並把內部連續空白壓縮爲一個,而後返回結果。沒有參數,則處理當前節點。 
fn:normalize-unicode() 執行 Unicode 規格化。
fn:upper-case(string)  把 string 參數轉換爲大寫。
fn:lower-case(string)  把 string 參數轉換爲小寫。
fn:translate(string1,string2,string3) 

把 string1 中的 string2 替換爲 string3。

例子:translate('12:30','30','45')

結果:'12:45'

例子:translate('12:30','03','54')

結果:'12:45'

例子:translate('12:30','0123','abcd')

結果:'bc:da'

fn:escape-uri(stringURI,esc-res) 

例子:escape-uri("http://example.com/test#car", true())

結果:"http%3A%2F%2Fexample.com%2Ftest#car"

例子:escape-uri("http://example.com/test#car", false())

結果:http://example.com/test#car

例子:escape-uri ("http://example.com/~bébé", false())

結果:"http://example.com/~b%C3%A9b%C3%A9"

fn:contains(string1,string2)  若是 string1 包含 string2,則返回 true,不然返回 false。
fn:starts-with(string1,string2)  若是 string1 以 string2 開始,則返回 true,不然返回 false。
fn:ends-with(string1,string2)  若是 string1 以 string2 結尾,則返回 true,不然返回 false。
fn:substring-before(string1,string2)  返回 string2 在 string1 中出現以前的子字符串。
fn:substring-after(string1,string2)  返回 string2 在 string1 中出現以後的子字符串。
fn:matches(string,pattern)  若是 string 參數匹配指定的模式,則返回 true,不然返回 false。
fn:replace(string,pattern,replace)  把指定的模式替換爲 replace 參數,並返回結果。
fn:tokenize(string,pattern)

例子:tokenize("XPath is fun", "\s+")

結果:("XPath", "is", "fun")

anyURI函數 fn:resolve-uri(relative,base)  
邏輯函數 fn:boolean(arg)  返回數字、字符串或節點集的布爾值。
fn:not(arg)  首先經過 boolean() 函數把參數還原爲一個布爾值,而後再取反。 
fn:true()  返回布爾值 true。 
fn:false()  返回布爾值 false。 
日期時間函數 fn:dateTime(date,time)  把參數轉換爲日期和時間。 
fn:years-from-duration(datetimedur) 返回參數值的年份部分的整數,以標準詞彙表示法來表示。 
fn:months-from-duration(datetimedur)  返回參數值的月份部分的整數,以標準詞彙表示法來表示。 
fn:days-from-duration(datetimedur)  返回參數值的天部分的整數,以標準詞彙表示法來表示。 
fn:hours-from-duration(datetimedur)  返回參數值的小時部分的整數,以標準詞彙表示法來表示。 
fn:minutes-from-duration(datetimedur)  返回參數值的分鐘部分的整數,以標準詞彙表示法來表示。 
fn:seconds-from-duration(datetimedur)  返回參數值的分鐘部分的十進制數,以標準詞彙表示法來表示。 
fn:year-from-dateTime(datetime)  返回參數本地值的年部分的整數。 
fn:month-from-dateTime(datetime)  返回參數本地值的月部分的整數。 
fn:day-from-dateTime(datetime)  返回參數本地值的天部分的整數。 
fn:hours-from-dateTime(datetime)  返回參數本地值的小時部分的整數。 
fn:minutes-from-dateTime(datetime)  返回參數本地值的分鐘部分的整數。 
fn:seconds-from-dateTime(datetime)  返回參數本地值的秒部分的十進制數。 
fn:timezone-from-dateTime(datetime)  返回參數的時區部分,若是存在。 
fn:year-from-date(date)  返回參數本地值中表示年的整數。 
fn:month-from-date(date)  返回參數本地值中表示月的整數。 
fn:day-from-date(date) 返回參數本地值中表示天的整數。 
fn:timezone-from-date(date)  返回參數的時區部分,若是存在。 
fn:hours-from-time(time)  返回參數本地值中表示小時部分的整數。 
fn:minutes-from-time(time) 返回參數本地值中表示分鐘部分的整數。 
fn:seconds-from-time(time)  返回參數本地值中表示秒部分的整數。 
fn:timezone-from-time(time)  返回參數的時區部分,若是存在。 
fn:adjust-dateTime-to-timezone(datetime,timezone)  若是 timezone 參數爲空,則返回沒有時區的 dateTime。不然返回帶有時區的 dateTime。 
fn:adjust-date-to-timezone(date,timezone) 若是 timezone 參數爲空,則返回沒有時區的 date。不然返回帶有時區的 date。 
fn:adjust-time-to-timezone(time,timezone) 若是 timezone 參數爲空,則返回沒有時區的 time。不然返回帶有時區的 time。 
 QName相關函數  fn:QName()   
fn:local-name-from-QName()  
fn:namespace-uri-from-QName()   
fn:namespace-uri-for-prefix()   
fn:in-scope-prefixes()   
fn:resolve-QName()   
節點函數 
  •  
  • fn:name()
  • fn:name(nodeset)
返回當前節點的名稱或指定節點集中的第一個節點。 
  • fn:local-name()
  • fn:local-name(nodeset)
返回當前節點的名稱或指定節點集中的第一個節點 - 不帶有命名空間前綴。 
  • fn:namespace-uri()
  • fn:namespace-uri(nodeset)
返回當前節點或指定節點集中第一個節點的命名空間 URI。 
fn:lang(lang) 

若是當前節點的語言匹配指定的語言,則返回 true。

例子:Lang("en") is true for <p xml:lang="en">...</p>

例子:Lang("de") is false for <p xml:lang="en">...</p>

  • fn:root()
  • fn:root(node)
返回當前節點或指定的節點所屬的節點樹的根節點。一般是文檔節點。 
上下文函數 fn:position() 

返回當前正在被處理的節點的 index 位置。

例子://book[position()<=3]

結果:選擇前三個 book 元素

fn:last() 

返回在被處理的節點列表中的項目數目。

例子://book[last()]

結果:選擇最後一個 book 元素 

fn:current-dateTime()  返回當前的 dateTime(帶有時區)。 
fn:current-date()  返回當前的日期(帶有時區)。 
fn:current-time()  返回當前的時間(帶有時區)。 
fn:implicit-timezone()  返回隱式時區的值。 
fn:default-collation()  返回默認對照的值。
fn:static-base-uri()  返回 base-uri 的值。 
序列函數 通常序列函數 fn:index-of((item,item,...),searchitem) 

返回在項目序列中等於 searchitem 參數的位置。

例子:index-of ((15, 40, 25, 40, 10), 40)

結果:(2, 4)

fn:remove((item,item,...),position)  返回由 item 參數構造的新序列 - 同時刪除 position 參數指定的項目。 
fn:empty(item,item,...)  若是參數值是空序列,則返回 true,不然返回 false。 
fn:exists(item,item,...)  若是參數值不是空序列,則返回 true,不然返回 false。 
fn:distinct-values((item,item,...),collation) 

返回惟一不一樣的值。

例子:distinct-values((1, 2, 3, 1, 2))

結果:(1, 2, 3) 

fn:insert-before((item,item,...),pos,inserts)  返回由 item 參數構造的新序列 - 同時在 pos 參數指定位置插入 inserts 參數的值。 
fn:reverse((item,item,...))  返回指定的項目的顛倒順序。 
fn:subsequence((item,item,...),start,len)  返回 start 參數指定的位置返回項目序列,序列的長度由 len 參數指定。第一個項目的位置是 1。 
fn:unordered((item,item,...)) 依據實現決定的順序來返回項目。 
容量測試函數 fn:zero-or-one(item,item,...)  若是參數包含零個或一個項目,則返回參數,不然生成錯誤。 
fn:one-or-more(item,item,...)  若是參數包含一個或多個項目,則返回參數,不然生成錯誤。 
fn:exactly-one(item,item,...)  若是參數包含一個項目,則返回參數,不然生成錯誤。 
比較函數 fn:deep-equal(param1,param2,collation) 若是 param1 和 param2 與彼此相等(deep-equal),則返回 true,不然返回 false。
合計函數 fn:count((item,item,...))  返回節點的數量。 
fn:avg((arg,arg,...)) 返回參數值的平均數。
fn:max((arg,arg,...)) 返回參數中的最大值。
fn:min((arg,arg,...)) 返回參數中的最小值。
fn:sum(arg,arg,...) 返回指定節點集中每一個節點的數值的總和。
序列生成函數 fn:id((string,string,...),node)  
fn:idref((string,string,...),node)  
fn:data((item1,item2,...)) 返回item一、item2等各項的值所組成的序列。
fn:doc(URI)  
fn:doc-available(URI) 若是 doc() 函數返回文檔節點,則返回 true,不然返回 false。
  • fn:collection()
  • fn:collection(string)
 

很明顯,把這些內置函數放在這裏的目的並非要強行記住,而只是須要的時候當字典查查(XQuery1.0和XPath共享了這些內置函數,有事沒事看看,混個眼熟也挺好的)。

相關文章
相關標籤/搜索