若要在 Firefox 中測試 XPath,請將格式正確的 XML 測試資料貼到一個可對獨立於網頁的記憶體文件執行 XPath 1.0 的評估工具中,輸入運算式,然後檢查瀏覽器原生 DOM 所回傳的相符節點、序列化文字或純量值。匹配本身來自 Document.evaluate,這是 Firefox 在開發者主控台中同樣開放的介面,但評估是針對以 DOMParser 解析出來的 XML 文件,而不是當前的 HTML 分頁。這個區別很重要:HTML 和 XML 使用不同的規則解析,命名空間的處理也不同,在實際頁面上能通過的運算式,遇到真正的 XML 承載時仍然可能失敗。

Firefox 並不像 Chrome 那樣內建專屬的 XPath 面板,大多數開發者會改用瀏覽器主控台搭配輔助函式 $x(),再把相符的節點複製回腳本中。這在實際頁面上找元素時很方便,但目標是針對任意的 XML 片段(設定檔、SOAP 信封、RSS feed、SVG 資產,或儲存的伺服器回應)驗證 XPath 運算式時,這種方式就不太合用。這個任務的正確工具,是一個專門的 XPath 測試工具,它模擬 Firefox 內部的處理方式,但允許使用者自行提供文件。

how to test xpath in firefox
如何使用獨立 XML 文件在 Firefox 中測試 XPath

為何 XPath 1.0 需要真正的 XML 文件

Firefox 實作了 W3C DOM Level 3 XPath 規格,該規格綁定 XPath 1.0。瀏覽器並不支援後續版本,因此序列(sequences)、對映(maps)、陣列、具型別的值,或正規表示式函式等特性都無法使用。在瀏覽器中能運作的任何東西,必然是 XPath 1.0;無法運作的,則超出此引擎的詞彙範圍。這也說明了為何使用 XSLT 2.0 或 XQuery 的伺服器端函式庫中能執行的 XPath,可能會與 Firefox 回報的結果悄悄不一致。

獨立文件之所以重要的第二個原因在於解析。HTML 解析對許多錯誤較為寬容,但 XML 並不會。標籤不對應、未跳脫的 & 符號,或缺少結尾元素,都會從 DOMParser.parseFromString 產生 parsererror 結果,XPath 步驟根本不會執行。把這個錯誤視為失敗,能在錯誤答案出現之前就中止測試,並讓開發者收到一個明確的訊號,知道是哪一份輸入有問題。MDN 關於 DOMParser.parseFromString 的參考資料描述了相同的行為。

準備帶有命名空間前綴的 XML 測試資料

XML 測試資料必須格式正確,且必須宣告運算式預計使用的每個前綴。常見的偽陰性來源,是在根元素上宣告預設命名空間(例如 xmlns="urn:books"),搭配未加前綴的 XPath 名稱。在 XPath 1.0 中,未加前綴的名稱只會選取沒有命名空間的元素,因此 //book 即使在文件明顯包含書目的情況下,仍會回傳零個相符結果。解決方法是在 XML 中將命名空間綁定到前綴,並在運算式中使用該前綴。

XML 宣告範例 XPath匹配結果
xmlns="urn:books" on root//book零個相符;未加前綴的名稱會略過預設命名空間。
xmlns:b="urn:books" on root//b:book符合所有 b:book 元素。
xmlns:b="urn:books" on root//*[local-name()='book']會符合,但忽略實際的命名空間。
保留的 xml 前綴//*[@xml:lang]解析為 http://www.w3.org/XML/1998/namespace。

保留的 xml 前綴會對應到其標準命名空間,不需要額外宣告。其他任何前綴都必須出現在測試資料中,否則運算式會因為「未解析的前綴」錯誤而失敗。

在 Firefox 中執行 XPath 運算式

  1. 在 Firefox 分頁中開啟 XPath 測試工具。整個工具都在當前分頁內執行,不會上傳 XML 或運算式。
  2. 將格式正確的 XML 測試資料貼到來源窗格。請在根元素上為 XPath 將參考的每個前綴加入 xmlns:prefix="uri" 的明確宣告。測試資料長度必須低於 500,000 字元。
  3. 在運算式窗格中輸入 XPath 1.0 運算式。長度請保持在 2,000 字元以內,並盡量使用明確的絕對路徑或收斂過的上下文,避免在大型文件上進行廣泛的後代搜尋。
  4. 觸發評估。瀏覽器會以 application/xml 使用 DOMParser 解析 XML;如果結果為 parsererror,執行會中止並回報不一致之處。
  5. 讀取輸出。XPath 測試工具使用 Document.evaluate 搭配 ANY_TYPE,因此瀏覽器會回報運算式自然的結果類型:節點集、字串、數字或布林值。Document.evaluate 的參考頁面記載了相同的回傳類型契約。
  6. 把可正常運作的運算式複製到目標執行環境中,無論是伺服器端解析器、建構腳本或測試框架,並在那裡重新執行,因為伺服器函式庫可能實作了不同版本的 XPath 或不同的命名空間政策。

閱讀結果類型,而不僅僅是文字

輸出區域會以不同方式呈現每一種結果,讓開發者能辨識引擎實際回傳的內容。節點集結果會被收集起來,每個相符項目一行並加上編號;元素節點會被序列化為文字,屬性值會以明確的 @ 符號前綴顯示(例如 @id="42"),文位元組點會加上標記,註解節點同樣會加上標記。這些序列化輸出並不會以標記的形式插入實際頁面,這能避免相符的 XML 內含類似腳本文字時,引發常見的 XSS 類意外。

XPath 回傳類型範例運算式測試工具顯示的內容
node-set//book/title每個相符項目一行,顯示序列化後的元素。
stringstring(//book[1]/@isbn)加上引號的單一字串值。
numbercount(//book)整數或小數計數。
Booleanboolean(//book[@price < 10])true 或 false。
empty//missing空結果,與解析錯誤或運算式錯誤不同。

空節點集與解析錯誤在呈現上刻意區分。零個相符的成功結果會被視為空結果並回報,而格式錯誤的運算式或 XML 解析失敗,則會產生穩定的 XPath 錯誤前綴,再加上瀏覽器本身的訊息。引擎的措辭可能因 Firefox 版本而異,而前綴則能讓診斷訊息在跨版本間保持一致。

貼上之前先了解限制

在獨立文件上作業有幾項硬性上限。XML 來源上限為 500,000 字元,運算式上限為 2,000 字元。節點集結果上限為 500 個相符節點,總顯示字元數上限為 1,000,000 個字元。達到相符上限會被視為失敗,而不是顯示截斷的前綴,因為部分答案可能看起來像完整答案,導致有瑕疵的定位器被部署到正式環境。請使用更具體的路徑或述詞來收斂運算式,然後再執行一次。

務實的工作流程從小型且具代表性的測試資料開始,再視需要逐步擴充。請為正向相符保留一份測試資料,並為已知的零相符情況保留另一份,因為空結果也是契約的一部分。當運算式負責守護某個分支時,請同時測試兩個方向。如果同一個查詢預期只找出一筆紀錄,那麼像 count(...) 這類計數運算式也應該回傳 1;如果回傳 0 或多個,則周圍的程式碼需要加入守護機制。

在目標執行環境中確認運算式

在 Firefox 中通過測試是必要條件,但並非充分條件。伺服器端函式庫通常會內建自己的 XPath 引擎,而在命名空間、空白字元處理及結果類型方面的規則可能有所不同。XPath 可以選取元素、屬性、文字、註解以及處理相關的節點,但相符並不代表 XML 符合商業規則:這個工作流程中沒有 XSD 或 DTD 驗證,而 DOMParser 預設不會對結構描述進行驗證。請把本地測試視為運算式語法和結構的證明,至於資料是否夠完整以供應用程式使用,則交由真正的執行環境來判斷。

若讀者傾向直接使用瀏覽器主控台,可以在這份在 Chrome 主控台中對任意 XML 檢查 XPath 的指南中找到相同工作流程的 Chrome 版本。Firefox 並沒有對應的一鍵面板,因此獨立文件工具仍是取得乾淨、可重現的 XPath 測試最可靠的路徑。

本地 XPath 作業的安全注意事項

XML 和運算式都不會離開這個分頁。這個工具不會擷取遠端文件、跟隨連結、執行腳本、插入相符的標記、修改來源,也不會儲存歷史紀錄。話雖如此,任何貼到開發者工具中的內容,都可能落入剪貼簿歷史、螢幕擷圖或螢幕分享畫面中,因此敏感的 XML 應比照其他除錯介面,套用相同的本機畫面與剪貼簿衛生原則。一旦運算式在本地完成驗證,移轉到目標環境時也應遵循最小暴露原則。