在 Linux 终端中使用 XMLStarlet 解析 XML

使用 XMLStarlet,一个用于终端的 XML 工具包,成为 XML 明星。
53 位读者喜欢这篇文章。
How Linux became my job

Opensource.com

学习解析 XML 通常被认为是一项复杂的任务,但其实不必如此。XML 具有高度和严格的结构,因此它相对可预测。 也有很多工具可以帮助您使这项工作变得可管理。

我最喜欢的 XML 实用程序之一是 XMLStarlet,一个用于终端的 XML 工具包。 使用 XMLStarlet,您可以验证、解析、编辑、格式化和转换 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 交互,我使用 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 '/xml/os/linux/distribution[name = "Fedora Core"]/release' \
--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 '/xml/os/linux/distribution/spin' \
--value-of '.' --nl myfile.xml \
Live
Fedora
Everything

与导航 DOM 一样,您可以使用 XPath 表达式来限制返回数据的范围。 在此示例中,我使用 last() 函数仅检索 spin 节点中的最后一个元素

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

在此示例中,我使用 position() 函数选择 spin 节点中的特定元素

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

--match--value-of 选项可以重叠,因此如何一起使用它们取决于您。 就示例 XML 而言,这两个表达式执行相同的操作

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

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

熟悉 XML

XML 有时看起来可能过于冗长和笨拙,但用于与其交互的工具始终让我感到惊讶。 如果您希望利用 XML,那么 XMLStarlet 可能是一个不错的切入点。 下次您要打开 XML 文件以查看结构化数据时,请尝试使用 XMLStarlet,看看是否可以改为查询该数据。 您越熟悉 XML,它就越能作为一种强大而灵活的数据格式为您服务。

接下来阅读

什么是 XML?

了解 XML,一种严格而灵活的标记语言,用于从文档到图形的所有内容。

(团队,红帽)
2021 年 7 月 12 日
标签
Seth Kenlon
Seth Kenlon 是一位 UNIX 极客、自由文化倡导者、独立多媒体艺术家和 D&D 爱好者。 他曾在电影和计算行业工作,而且经常同时进行。

2 条评论

有什么类似的 JSON 等工具吗?

jq 非常流行,并且非常好用:https://open-source.net.cn/article/20/6/modern-linux-command-line-tools#jq

还有一些 Python 库可以帮助您设计自己的解决方案。 https://#/sysadmin/yaml-tips 但我认为 jq 可能是最好的全能工具。

回复 ,作者 madtom1999

Creative Commons License本作品根据 Creative Commons Attribution-Share Alike 4.0 International License 许可。
© . All rights reserved.