使用 XMLStarlet 在 Linux 终端中解析 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,一种严格而灵活的标记语言,用于从文档到图形的所有内容。

标签
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.