.Net框架下的System.Xml.XPath命名空間提供了一系列的類,允許你應用XPath數據模式查詢和展示XML文檔數據。
一、XPath介紹
XPath有七種類型的節點:元素、屬性、文本、命名空間、處理指令、注釋、根節點。
二、XPath語法
XPath使用路徑表達式來選取XML文檔中的節點或節點集。
1、常用的路徑表達式:
表達式 | 解釋 |
nodename | 選取節點下的所有子節點 |
/ | 選取根節點 |
// | 選取文檔中所有符合條件的節點,不管該節點位於何處 |
. | 選取當前節點 |
.. | 選取當前節點的父節點 |
@ | 選取屬性 |
先貼一個XML文檔,以此作為示例的試驗文檔:
<?xml version="1.0" encoding="utf-8" ?> <bookstore> <book> <title lang="en">三國演義</title> <author>羅貫中</author> <year>2005</year> <price>38.5</price> </book> <book> <title lang="eng">西游記</title> <author>吳承恩</author> <year>2004</year> <price>37.5</price> </book> </bookstore>
示例代碼:
static void Main(string[] args) { XmlDocument doc = new XmlDocument(); //創建文檔 doc.Load(@"C:\Users\Administrator\Desktop\ConsoleApplication1\ConsoleApplication1\Test.xml"); //加載xml文件 XmlNode node1 = doc.SelectSingleNode("/"); //選中根節點 Console.WriteLine(node1.LocalName); //輸出#document XmlNode node2 = doc.SelectSingleNode("bookstore"); //選中bookstore元素 Console.WriteLine(node2.Name); //輸出 bookstore XmlNode node3 = doc.SelectSingleNode("/bookstore"); //選中根節點下的bookstore元素 Console.WriteLine(node3.Name); //輸出 bookstore XmlNodeList nodelist1 = doc.SelectNodes("//id"); //選中所有符合條件的id元素,不管它的位置如何 foreach (XmlNode node in nodelist1) { Console.WriteLine(node.InnerText); //輸出 1 2 } XmlNodeList nodelist2 = doc.SelectNodes("bookstore/book/title"); //讀取bookstore下的所有book元素下的所有title元素 foreach (XmlNode node in nodelist2) { Console.WriteLine(node.InnerText); //輸出 三國演義 西游記 } XmlNode node4 = doc.SelectSingleNode("/bookstore/book[1]/title[1]/."); //獲取第一個title的當前節點 Console.WriteLine(node4.Name); //輸出title XmlNode node5 = doc.SelectSingleNode("/bookstore/book[1]/title[1]/.."); //獲取第一個title的父節點 Console.WriteLine(node5.Name); //輸出book Console.ReadKey(); }
2、通配符
通配符 | 說明 |
* | 匹配任意的節點元素 |
@* | 匹配任意的節點屬性 |
node() | 匹配任意種類的節點 |
text() | 匹配節點的文本內容 |
示例代碼:
static void Main(string[] args) { XmlDocument doc = new XmlDocument(); //創建文檔 doc.Load(@"C:\Users\Administrator\Desktop\ConsoleApplication1\ConsoleApplication1\Test.xml"); //加載xml文件 XmlNodeList nodelist1 = doc.SelectNodes("/bookstore/*"); //匹配bookstore下的直接子元素 foreach (XmlNode node in nodelist1) { Console.WriteLine(node.Name); //輸出 book book 兩個book才是直接子元素 } XmlNodeList nodelist2 = doc.SelectNodes("//title[@*]"); //匹配所有含有任意屬性的title元素 foreach (XmlNode node in nodelist2) { Console.WriteLine(node.Name); //輸出 title title 兩個title含有屬性 } XmlNodeList nodelist3 = doc.SelectNodes("//*"); //匹配所有含有任意屬性的title元素 foreach (XmlNode node in nodelist3) { Console.WriteLine(node.Name); //輸出 所有的元素名 從上至下 } XmlNodeList nodelist4 = doc.SelectNodes("//title|//author"); //匹配所有的title和author元素 foreach (XmlNode node in nodelist4) { Console.WriteLine(node.InnerText); //輸出 三國演義 羅貫中 西游記 吳承恩 } Console.ReadKey(); }
3、軸
XPath軸可定義相對於當前節點的節點集:
軸名稱 | 結果 |
ancestor | 選取當前節點的所有先輩(父,祖父等)不包括自己 |
ancestor-or-self | 選取當前節點的所有先輩,以及自己 |
attribute | 選取當前節點的所有屬性 |
child | 選取當前節點的所有子元素 |
descendant | 選取當前節點的所有后代元素(子、孫等)不包括自己 |
descendant-or-self | 選取當前節點的所有后代元素,以及自己 |
following | 選取文檔中當前節點的結束標簽之后的所有節點 |
namespace | 選取當前節點的所有命名空間節點 |
parent | 選取當前節點的父節點 |
preceding | 選取文檔中當前節點的開始標簽之前的所有節點 |
preceding-sibling | 選取當前節點之前的所有統計節點 |
self | 選取當前節點 |
與軸有關的兩個重要概念:
- 位置;
- 步;
位置路徑可以是絕對的,也可以是相對的。
絕對路徑表達式:
/step/step/...
相對路徑表達式:
step/step/...
而步的定義包括:
- 軸:定義所選節點與當前節點之間的樹關系;
- 節點測試:識別某個軸內部的節點;
- 另個或者多個謂詞:更深入地提煉所選的節點集。
步的語法:
軸名稱::節點測試[謂詞]
代碼示例:
static void Main(string[] args) { XmlDocument doc = new XmlDocument(); //創建文檔 doc.Load(@"C:\Users\Administrator\Desktop\ConsoleApplication1\ConsoleApplication1\Test.xml"); //加載xml文件 XmlNode node1 = doc.SelectSingleNode("/bookstore/book[1]"); XmlNode node2 = node1.SelectSingleNode("ancestor::*"); //選取當前節點的祖先節點,選擇單個(SelectSingleNode)就是直接父元素 Console.WriteLine(node2.Name); //輸出 bookstore XmlNodeList nodelist1 = node1.SelectNodes("ancestor-or-self::*"); //選取當前節點的所有先輩元素 foreach (XmlNode node in nodelist1) { Console.WriteLine(node.Name); //輸出 bookstore book book是self bookstore是ancestor } XmlNode node3 = node1.SelectSingleNode("child::title"); //選取當前節點的子元素叫title的節點 Console.WriteLine(node3.InnerText); //輸出 三國演義 XmlNodeList nodelist2 = node1.SelectNodes("descendant::*"); foreach (XmlNode node in nodelist2) { Console.WriteLine(node.Name); //輸出 id title author year price } XmlNodeList nodelist3 = node1.SelectNodes("descendant-or-self::*"); //獲取所有的子節點以及自身 foreach (XmlNode node in nodelist3) { Console.WriteLine(node.Name); //輸出 book id title author year price 其中book是self } XmlNodeList nodelist4 = node1.SelectNodes("following::*"); //獲取第一個book標簽結束后的所有節點 foreach (XmlNode node in nodelist4) { Console.WriteLine(node.Name); //輸出 book id title author year price } XmlNode node4 = node1.SelectSingleNode("parent::*"); //獲取當前的節點的父節點 Console.WriteLine(node4.Name); //輸出 bookstore Console.WriteLine("----------------"); XmlNode node5 = doc.SelectSingleNode("/bookstore/book[2]/title[1]"); //選取第二個book的第一個title節點 XmlNodeList nodelist5 = node5.SelectNodes("preceding::*"); //獲取當前節點(第二個book的第一個title)開始之前的所有節點 foreach (XmlNode node in nodelist5) { Console.WriteLine(node.Name); //輸出 book id title author year price id } XmlNodeList nodelist6 = node5.SelectNodes("preceding-sibling::*"); //獲取當前節點(第一個title)開始之前的所有同級別節點 foreach (XmlNode node in nodelist6) { Console.WriteLine(node.Name); //輸出 id } XmlNode node7 = node5.SelectSingleNode("self::*"); Console.WriteLine(node7.Name); //輸出 title Console.ReadKey(); }
4、XPath運算符
運算符 | 說明 |
| | 計算兩個節點集 |
+ | 加法 |
- | 減法 |
* | 乘法 |
div | 除法 |
= | 等於 |
!= | 不等於 |
< | 小於 |
<= | 小於或等於 |
>= | 大於或等於 |
> | 大於 |
or | 或 |
and | 與 |
mod | 計算除法的余數 |
5、特殊字符
特殊字符 | 說明 |
/ | 此路徑運算符出現在模式的開頭時,表示應從根節點選擇 |
// | 從當前節點開始遞歸下降,此路徑運算符出現在模式開頭時表示應從節點遞歸下降 |
. | 當前上下文 |
.. | 當前上下文節點父節 |
* | 通配符;選擇所有元素節點和元素名無關(不包括文本、注釋、指令等節點,如果也要包含這些節點請用node()函數) |
@ | 屬性的前綴 |
@* | 所有的屬性,與名稱無關 |
: | 命名空間分隔符;將命名空間前綴與元素名分隔 |
() | 括號運算符(優先級最高),強制運算優先級 |
[] | 應用篩選模式(即謂詞,包括"過濾表達式"和"軸"(向前/向后)) |
[] | 下標運算符;用於在集合中編制索引 |
6、XPath函數
XPath與XSLT、XQuery等共享函數庫,函數庫提供了功能豐富的各種內置函數。
(1)存取函數
名稱 說明
fn:node-name(node) 返回參數節點的節點名稱
fn:nilled(node) 返回是否拒絕參數節點的布爾值
fn:data(item.item,...) 接受項目序列,並返回原子序列
fn:base-uri() fn:base-uri(node)返回當前節點的base-uri屬性的值
fn:document-uri(node) 返回指定節點的document-uri屬性的值
(2)錯誤和跟蹤函數
名稱 說明
fn:error()
fn:error(error)
fn:error(error,description)
fn:error(error,description,error-object)
fn:trace(value,label) 用於對查詢進行debug
(3)有關數值的函數
名稱 說明
fn:number(arg) 返回參數的數值
fn:abs(num) 返回參數的絕對值
fn:ceiling(num) 返回大於num參數的最小整數
fn:floor(num) 返回不大於num參數的最大整數
fn:round(num) 把num參數舍入為最接近的整數
fn:round-half-to-even() 不明白
(4)有關字符串的函數
名稱 說明
fn:string(arg) 返回參數的字符串值。參數可以使數字、邏輯值或節點集
fn:codepoints-to-string(int,int...) 根據代碼點序列返回字符串
fn:string-to-codepoints(string) 根據字符串返回代碼點序列
fn:codepoint-equal(comp1,comp2) 根據Unicode代碼點對照,如果comp1的值等於comp2的值則返回True
fn:compare(comp1,comp2) 如果comp1小於comp2,則返回-1.相等返回0,如果comp1>comp2則返回1。
fn:concat(string,string...) 返回字符串的拼接
fn:string-join((string,string,...),sep) 使用sep參數作為分隔符,來返回string參數拼接后的字符串
fn:substring(string,start,len) 返回從start位置開始的指定長度的子字符串。第一個字符的下標是1。如果省略len參數,則返回從位置start到字符串末尾的 子字符串。
fn:string-length(string) 返回指定字符串的長度,如果沒有string參數,則返回當前節點的字符串的值的長度。
fn:normalize-space(string) 刪除指定字符串的開頭和結尾的空白,並把內部的所有空白序列替換為一個然后返回結果。
fn:normalize-unicode() 執行Unicode規格化
fn:upper-case(string) 把string參數轉換為大寫
fn:lower-case(string) 把string參數轉換為小寫
fn:translate(string1,string2,string3) 把string1中的string2替換為string3
fn:escape-uri(stringURI,esc-res) url編碼
fn:contains(string1,string2) 如果string1包含string2則返回true,否則返回false
fn:starts-with(string1,string2) 如果string1以string2開始,則返回true,否則返回false
fn:ends-width(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) pattern匹配到的字符進行分割,並將分割后的結果返回
(5)上下文函數
名稱 說明
fn:position() 返回當前正在被處理的節點的index位置
fn:last() 返回在被處理的節點列表中的項目數目
fn:current-dateTime() 返回當前的dateTime(帶有時區)
fn:current-date() 返回當前的日期(帶有時區)
fn:current-time() 返回當前的時間(帶有時區)
fn:implicit-timezone() 返回隱式時區的值
fn:default-collation() 返回默認對照的值
fn:static-base-uti() 返回base-uri的值
(6)關於節點的函數
名稱 說明
fn:name()/fn:name(nodeset) 返回當前節點的名稱或指定節點集的第一個節點
fn:local-name()/fn:local-name(nodeset) 返回當前節點的名稱或指定節點集的第一個節點-不帶命名空
fn:namespace-uri()/fn:namespace-uri(nodeset) 返回當前節點或指定節點集中第一個節點的命名空間URI
fn:lang(lang) 如果當前節點的語言匹配指定的語言則返回True
fn:root()/fn:root(node) 返回當前節點或指定節點所屬的節點樹的根節點。通常是文檔節點
(7)一般性函數
名稱 說明
fn:index-of((item,item,...),searchitem) 返回在項目序列中等於searchitem參數的位置
fn:remove((item,item...),position) 返回由item參數構造的新序列-同時刪除position指定的項目
fn:empty(item,item...) 如果參數是空序列則返回True,否則返回False
fn:exists(item,item,...) 如果參數不是空序列,則返回True,否則返回False
fn:distince-values((item,item,...),collation) 返回唯一不同的值
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 依據事先決定的順序來返回項目
(8)關於布爾值的函數
名稱 說明
fn:boolean(arg) 返回數字、字符串或節點集的布爾值
fn:not(arg) 首先通過boolean()函數把參數還原為一個布爾值,如果該布爾值為false則返回true,否則返回false
fn:true() 返回布爾值true
fn:false() 返回布爾值false
由於函數實在太多,因此次數僅僅寫了幾個示例,展示下用法而已,一般都是寫在謂詞里。
static void Main(string[] args) { XmlDocument doc = new XmlDocument(); //創建文檔 doc.Load(@"C:\Users\Administrator\Desktop\ConsoleApplication1\ConsoleApplication1\Test.xml"); //加載xml文件 XmlNode node1 = doc.SelectSingleNode("//title[contains(text(),'三')]"); //選取title元素,要求title的內容含有'三' Console.WriteLine(node1.InnerText); //輸出 三國演義 XmlNode node2 = doc.SelectSingleNode("//title[@lang='屬性2']"); //獲取屬性lang的值為屬性2的title節點,不管它位於何處 Console.WriteLine(node2.InnerText); XmlNode node3 = doc.SelectSingleNode("//author[starts-with(text(),'吳')]"); //選取任意位置的author節點,其中author的元素值要以 吳 開頭 Console.WriteLine(node3.InnerText); //輸出 吳承恩 XmlNode node4 = doc.SelectSingleNode("//title[string-length(text())>3]"); //選取值的長度大於3的title元素 Console.WriteLine(node4.InnerText); //輸出 三國演義 XmlNode node5 = doc.SelectSingleNode("//price[floor(text())=38]"); //獲取 向下取整后值等於38的price元素 Console.WriteLine(node5.InnerText); //輸出 38.5 Console.ReadKey(); }