Linux中國

在命令行中使用 XMLStarlet 來解析 XML

學習解析 XML 通常被認為是一件複雜的事情,但它不一定是這樣。XML 是高度嚴格結構化的,所以也是相對來說可預測的。也有許多其他工具可以幫助你使這項工作易於管理。

我最喜歡的 XML 實用程序之一是 XMLStarlet,這是一個用於終端的 XML 工具包,藉助這個 XML 工具包,你可以驗證、解析、編輯、格式化和轉換 XML 數據。XMLStarLet 是個相對較小的命令,但瀏覽 XML 卻充滿潛力,因此本文演示了如何使用它來查詢 XML 數據。

安裝

XMLStarLet 默認安裝在 CentOS、Fedora,和許多其他現代 Linux 發行版上,所以你可以打開終端,輸入 xmlstarlet 來訪問它。如果 XMLStarLet 還沒有被安裝,你的操作系統則會為你安裝它。

或者,你可以用包管理器安裝 xmlstarlet

$ sudo dnf install xmlstarlet

在 macOS 上,可以使用 MacPortsHomebrew。在 Windows 上,可以使用 Chocolatey

如果都失敗了,你可以從 Sourceforge 上的源代碼 手動安裝它。

用 XMLStarlet 解析 XML

有許多工具可以幫助解析和轉換 XML 數據,包括允許你 編寫自己的解析器 的軟體庫,和複雜的命令,如 fopxsltproc。不過有時你不需要處理 XML 數據;你只需要一個方便的方法從 XML 數據中來提取、更新或驗證重要數據。對於隨手的 XML 交互,我使用 xmlstarlet,這是常見的處理 XML任務的一個典型的「瑞士軍刀」式應用。通過運行 --help 命令,你可以看到它提供哪些選項:

$ xmlstarlet --help
Usage: xmlstarlet [<options>] <command> [<cmd-options>]
where <command> is one of:
  ed    (or edit)      - Edit/Update XML document(s)
  sel   (or select)    - Select data or query XML document(s) (XPATH, etc)
  tr    (or transform) - Transform XML document(s) using XSLT
  val   (or validate)  - Validate XML document(s) (well-formed/DTD/XSD/RelaxNG)
  fo    (or format)    - Format XML document(s)
  el    (or elements)  - Display element structure of XML document
  c14n  (or canonic)   - XML canonicalization
  ls    (or list)      - List directory as XML
[...]

你可以通過在這些子命令的末尾附加 -help 來獲得進一步的幫助:

$ xmlstarlet sel --help
  -Q or --quiet             - do not write anything to standard output.
  -C or --comp              - display generated XSLT
  -R or --root              - print root element <xsl-select>
  -T or --text              - output is text (default is XML)
  -I or --indent            - indent output
[...]

用 sel 命令選擇數據

可以使用 xmlstarlet select(簡稱 sel)命令查看 XML 格式的數據。下面是一個簡單的 XML 文檔:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xml>
  <os>
   <linux>
    <distribution>
      <name>Fedora</name>
      <release>7</release>
      <codename>Moonshine</codename>
      <spins>
        <name>Live</name>
        <name>Fedora</name>
        <name>Everything</name>
      </spins>
    </distribution>

    <distribution>
      <name>Fedora Core</name>
      <release>6</release>
      <codename>Zod</codename>
      <spins></spins>
    </distribution>
   </linux>
  </os>    
</xml>

在 XML 文件中查找數據時,你的第一個任務是關注要探索的節點。如果知道節點的路徑,請使用 -value of 選項指定完整路徑。你越早瀏覽 文檔對象模型(DOM)樹,就可以看到更多信息:

$ xmlstarlet select --template 
  --value-of /xml/os/linux/distribution 
  --nl myfile.xml
      Fedora
      7
      Moonshine

        Live
        Fedora
        Everything     

      Fedora Core
      6
      Zod

--nl 代表「新的一行」,它插入大量的空白,以確保在輸入結果後,終端在新的一行顯示。我已經刪除了樣本輸出中的一些多餘空間。

通過進一步深入 DOM 樹來凝聚關注點:

$ xmlstarlet select --template 
  --value-of /xml/os/linux/distribution/name 
  --nl myfile.xml
Fedora
Fedora Core

條件選擇

用於導航和解析 XML 的最強大工具之一被稱為 XPath。它規範了 XML 搜索中使用的語法,並從 XML 庫調用函數。XMLStarlet 能夠解析 XPath 表達式,因此可以使用 XPath 函數來有條件的進行選擇。XPath 具有豐富的函數,由 W3C 提供了詳細文檔,但我覺得 Mozilla 的 XPath 文檔 更簡潔。

可以使用方括弧作為測試函數,將元素的內容與某個值進行比較。下面是對 <name> 元素的值的測試,它僅返回與特定匹配相關聯的版本號。

想像一下,示例 XML 文件包含以 1 開頭的所有 Fedora 版本。要查看與舊名稱 「Fedora Core」 關聯的所有版本號(該項目從版本 7 開始刪除了名稱中的 「Core」),請執行以下操作:

$ xmlstarlet sel --template 
  --value-of &apos;/xml/os/linux/distribution[name = "Fedora Core"]/release&apos; 
  --nl myfile.xml
6
5
4
3
2
1

通過將路徑的 --value-of 更改為 /xml/os/linux/distribution[name=「Fedora Core」]/codename,你便可以查看這些版本的所有代號。

匹配路徑和獲取目標值

將 XML 標記視為節點的一個好處是,一旦找到節點,就可以將其視為當前的數據的「目錄」。它不是一個真正的目錄,至少不是文件系統意義上的目錄,但它是一個可以查詢的數據集合。為了幫助你將目標和「裡面」的數據分開,XMLStarlet 把你試圖用 --match 選項匹配的內容和用 --value-of 選項匹配的數據值進行了區分。

假設你知道 <spin> 節點包含幾個元素。這就是你的目標節點。一旦到了這裡,就可以使用 --value-of 指定想要哪個元素的值。要查看所有元素,可以使用點(.)來代表當前位置:

$ xmlstarlet sel --template 
  --match &apos;/xml/os/linux/distribution/spin&apos; 
  --value-of &apos;.&apos; --nl myfile.xml 
Live
Fedora
Everything

與瀏覽 DOM 一樣,可以使用 XPath 表達式來限制返回數據的範圍。在本例中,我使用 last() 函數來檢索 spin 節點中的最後一個元素:

$ xmlstarlet select --template 
  --match &apos;/xml/os/linux/distribution/spin&apos; 
  --value-of &apos;*[last()]&apos; --nl myfile.xml
Everything

在本例中,我使用 position() 函數選擇 spin 節點中的特定元素:

$ xmlstarlet select --template 
  --match &apos;/xml/os/linux/distribution/spin&apos; 
  --value-of &apos;*[position() = 2]&apos; --nl myfile.xml
Fedora

--match--value 選項可以重疊,因此如何將它們一起使用取決於你自己。對於示例 XML,這兩個表達式執行的是相同的操作:

$ xmlstarlet select  --template 
  --match &apos;/xml/os/linux/distribution/spin&apos; 
  --value-of &apos;.&apos; 
  --nl myfile.xml
Live
Fedora
Everything     

$ xmlstarlet select --template 
  --match &apos;/xml/os/linux/distribution&apos; 
  --value-of &apos;spin&apos; 
  --nl myfile.xml
Live
Fedora
Everything

熟悉 XML

XML 有時看起來過於冗長和笨拙,但為與之交互和構建的工具卻總是讓我吃驚。如果你想要好好使用 XML,那麼 XMLStarlet 可能是一個很好的切入點。下次要打開 XML 文件查看其結構化數據時,請嘗試使用 XMLStarlet,看看是否可以查詢這些數據。當你對 XML 越熟悉時,它就越能作為一種健壯靈活的數據格式而為你服務。

via: https://opensource.com/article/21/7/parse-xml-linux

作者:Seth Kenlon 選題:lujun9972 譯者:zepoch 校對:wxy

本文由 LCTT 原創編譯,Linux中國 榮譽推出


本文轉載來自 Linux 中國: https://github.com/Linux-CN/archive

對這篇文章感覺如何?

太棒了
0
不錯
0
愛死了
0
不太好
0
感覺很糟
0
雨落清風。心向陽

    You may also like

    Leave a reply

    您的電子郵箱地址不會被公開。 必填項已用 * 標註

    此站點使用Akismet來減少垃圾評論。了解我們如何處理您的評論數據

    More in:Linux中國