XPath

**XPath** 即為 XML 路徑語言（XML Path Language），它是一種用來確定 XML 檔案中某部分位置的電腦語言。

XPath 基於 XML 的樹狀結構，提供在資料結構樹中找尋節點的能力。起初 XPath 的提出的初衷是將其作為一個通用的、介於 XPointer 與 XSL 間的語法模型。但是 XPath 很快的被開發者採用來當作小型查詢語言。

## 表示法

最常見的 XPath 表達式是路徑表達式（XPath 這一名稱的另一來源）。路徑表達式是從一個 XML 節點（當前的上下文節點）到另一個節點、或一組節點的書面步驟順序。這些步驟以「/」字元分開，每一步有三個構成成分：

* 軸描述（用最直接的方式接近目標節點）
* 節點測試（用於篩選節點位置和名稱）
* 節點描述（用於篩選節點的屬性和子節點特徵）

一般情況下，我們使用簡寫後的語法。雖然完整的軸描述是一種更加貼近人類語言，利用自然語言的單詞和語法來書寫的描述方式，但是相比之下也更加羅嗦。

### 簡略的語法

最簡單的 XPath 如下：

* `/A/B/C`

在這裡選擇所有符合規矩的 C 節點：C 節點必須是 B 的子節點（`B/C`），同時 B 節點必須是 A 的子節點（`A/B`），而 A 是這個 XML 檔案的根節點（`/A`）。此時的這種描述法類似於磁碟中檔案的路徑（URI），從磁碟機代號開始順著一級一級的目錄最終找到檔案。

這裡還有一個複雜一些的例子，包含了全部構成成分（請詳細的看）：

* `A//B/*[1]`

此時選擇的元素是：在 B 節點下的第一個節點（`B/*[1]`），不論節點的名稱如何（`*`）；而 B 節點必須出現在 A 節點內，不論和 A 節點之間相隔幾層節點（`//B`）；與此同時 A 節點還必須是當前節點的子節點（`A`，前邊沒有 `/`）。

### 擴充的語法

在未縮簡語法裡，兩個上述範例可以寫為：

* `/child::A/child::B/child::C`
* `child::A/descendant-or-self::B/child::node()[1]`

在 XPath 的每個步驟裡，通過完整的**軸描述**（例如：`child` 或 `descendant-or-self`）進行明確的指定，然後使用 `::`，它的後面跟著**節點測試**的內容，例如上面範例所示的 `A` 以及 `node()`。

## 軸描述語法

軸描述元表示 XML 檔案分支樹表達式的瀏覽方向。這些坐標──包括全名及縮寫語法──列舉如下：

關於使用 **attribute** 坐標簡寫語法的一個範例，`//a/@href` 在檔案樹里任何地方的元素下選擇了一個叫 `href` 的屬性。**self** 坐標最通常與述語同用，以參考現行選定節點。例如，`h3[.='See also']` 在現行上下文選取了叫 `h3` 的元素，該元素文字內容是 `See also`。

如果需要了解更多，請檢視 ZVON.org 給出的 XPath 幫助 （頁面存檔備份，存於網際網路檔案館）

## 節點測試

節點測試包括特定節點名或者更一般的表達式。至於 XML 里命名空間字首 `gs` 已定義的檔案，`//gs:enquiry` 將找到所有在那命名空間裡 `enquiry` 的節點。

其他節點格式：

**comment()**
: 尋找 XML 注釋節點，例如 `<!-- 注释 -->`

**text()**
: 尋找某點的文字型別，例如 `hello` 於 `<k>hello</k>`

**processing-instruction()**
: 尋找 XML 處理指令如 `<?php echo $a; ?>`。在這個例子裡，將符合 `processing-instruction('php')` 會傳回值。

**node()**
: 尋找所有點

## 節點描述

節點描述為一個邏輯真假表達式，任何真假判斷表達式都可在節點後方括號里表示，這條件必須在 XPath 處理這個節點前先被滿足。在某一步驟可有多少個描述並沒有限制。

範例如下：`//a[@href='help.php']`，這將檢查元素 `a` 有沒有 `href` 屬性，並且該它的值是 `help.php`。

複雜一些的範例如下：

* `//a[@href='help.php'][../div/@class='header']/@target`

或

* `//a[@href='help.php'][name(..)='div'][../@class='header']/@target`

此例將會選擇符合條件的元素 `a` 的 `target` 屬性。
要求元素 `a`：

* 具有屬性 `href` 且值為 `help.php`；
* 並且元素 `a` 具有父元素 `div`；
* 並且父元素（`div`）其自身具備 `class` 屬性，值為 `header`。

## 函式與運算子

XPath 1.0 定義四種資料型別：節點型（本身無序的節點組）、字串型、數字型、與布林型。

有效的運算子有：

* `/`、`//` 以及 `..` 運算子，一般用於軸描述。
* 合集運算子 | 把兩個節點形成聯集。
* 布林運算子 and、or 以及 not () 函式
* 數學運算子 +、-、\*、div（除）以及 mod（取餘數）
* 比較運算子 =、!=（不等於）、<、>、<=、>=

函式有：

* 文字運算函式

　
: concat(), substring(), contains(), substring-before(), substring-after(), translate(), normalize-space(), string-length()

* 數學運算函式

　
: sum(), round(), floor(), ceiling()

* 節點屬性取得函式

　
: name(), local-name(), namespace-uri()

* 處理上下文資料取得函式

　
: position(), last()

* 類型轉換函式

　
: string(), number(), boolean()

某些常用的函式詳列如下。完整明細請參照 W3C 建議書。

### 節點組函式

**position()**
: 返回當前節點集合內，該節點的位置。

**count(_node-set_)**
: 返回符合 XPath 的節點集合的節點總數。

### 字串函式

**string(_object_?)**
: 根據內建法則轉換任何四種 XPath 資料型別為字串。參數可為 XPath，此時符合條件的節點（群）被轉換成字串返回。

**concat(_string_, _string_, _string_\*)**
: 連結任何數量的字串。

**contains(_s1_, _s2_)**
: 如果 `s1` 包含 `s2` 返回真。

**normalize-space(_string_?)**
: 所有在字串頭和尾的空白字元都被移除，或者將字元間兩個及以上的空白字元置換成單一空格。有些 XML 因列印關係被美化，但可能讓後來的字串處理結果不可靠，故使用此函式有時能很好地改善情況。

### 布林函式

**not(_boolean_)**
: 布林否運算函式。

### 數學運算函式

**sum(_node-set_)**
: 根據內建轉型規則，轉換所有 XPath 參數定義找到的節點字串值成為數字，然後返回這些數字總合

使用運算子：`=, !=, <=, <, >=` 和 `>` 的表達式可以創造於術語內。布林表達式可用括號 `()`、布林運算子 `and` 與 `or`、和／或者上述的 `not()` 函式聯合起來。數值計算使用 `*, +, -, div` 和 `mod`。字串可包含任何 Unicode 字元。

述語內外，整個節點組可利用 "|" 字元聯合起來。

`v[x or y] | w[z]` 會返回單一節點組，包括現行上下文找到的所有擁有 `x` 或 `y` 子元素的 `v` 元素、有 `z` 子元素的 `w` 元素。

`//item[@price > 2*@discount]` 會選取 price 屬性至少兩倍於 discount 屬性數值的物件

## XPath 2 及 XPath 3

在 W3C 建議下，XPath 1.0 於 1999 年 11 月 16 日發表。XPath 2.0 於 2007 年 1 月 23 日成為 W3C 推薦標準。XPath 2.0 表達了 XPath 語言在大小與能力上顯著的增加。

最值得大書特書的改變是 XPath 2.0 有了更豐富的型別系統；XPath 2.0 支援不可分割型態，如在 XML Schema 內建型態定義一樣，並且也可自綱要（schema）匯入使用者自訂型別。現在每個值都是一個序列（一個單一不可分割值或節點都被視為長度一的序列）。XPath 1.0 節點組被節點序列取代，它可以是任何順序。

為了支援更豐富的型別組，XPath 2.0 提供相當延展的函式與運算子群。

XPath 2.0 實際上是 XQuery 1.0 的子集合。它提供了一個 for 表達式。該式是 XQuery 里「FLWOR」表達式的縮減版。利用列出 XQuery 省去的部分來描述該語言是可能的。主要範例是查詢前導語（query prolog）、元素和屬性建構式、「FLWOR」語法的餘項式、以及 `typeswitch` 表達式。

XPath 3.0 於 2014 年 4 月 8 日成為 W3C 推薦標準，而 XPath3.1 則於 2017 年 3 月 21 日成為 W3C 推薦標準。

## 參看

* **XML**
* XSLT，XSL-FO
* XLink，XPointer
* XPointer
* Xquery
* XML Schema
* STXPath

## 參照

## 外部連結

* W3C XPath1.0 規範（英文）
* W3C XPath 2.0 候選推薦（頁面存檔備份，存於網際網路檔案館）（英文）