command-line-interface - XMLStarlet 不选择任何内容

标签 command-line-interface pom.xml xmlstarlet

我有一个典型的 pom.xml,想打印 groupId、artifactId 和 version,用冒号分隔。我认为XMLStarlet是正确的工具。我尝试了几种方法,但我总是得到一个空行。

xml sel -t -m project -v groupId -o : -v artifactId -o : -v version pom.xml

预期输出:
org.something.apps:app-acct:5.4

实际输出:空行

即使我尝试只打印 groupId,我也一无所获:
xml sel -t -v project/groupId pom.xml

我确信该工具可以看到这些元素,因为我可以毫无问题地列出它们:
xml el pom.xml

打印以下(正确):
project
project/modelVersion
project/parent
project/parent/groupId
project/parent/artifactId
project/parent/version
project/groupId
project/artifactId
project/version
project/packaging

怎么了?

这是 pom.xml 的精简版:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                        http://maven.apache.org/maven-v4_0_0.xsd">

    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.something</groupId>
        <artifactId>base</artifactId>
        <version>1.16</version>
    </parent>

    <groupId>org.something.apps</groupId>
    <artifactId>app-acct</artifactId>
    <version>5.4</version>
    <packaging>war</packaging>

</project>

最佳答案

不幸的是,XMLStarlet 对默认 namespace 非常挑剔。如果文档已经声明了它( xmlns= ),您也必须为 XMLStarlet 声明它,并用您选择的名称作为元素的前缀(参见 here ):

xml sel -N my=http://maven.apache.org/POM/4.0.0 -t -m my:project -v my:groupId -o : -v my:artifactId -o : -v my:version pom.xml



运行上面的命令会得到预期的输出:
org.something.apps:app-acct:5.4

但是,如果文档没有声明默认命名空间(或者命名空间的 URL 略有不同),则上述命令将不起作用,这是一个真正的 PITA。更通用的解决方案是在选择元素之前删除默认命名空间声明。从 XMLStarlet 1.3.1 开始,将 XML 转换为 PYX 格式并返回会删除命名空间声明:

xml pyx pom.xml | xml p2x | xml sel -t -m project -v groupId -o : -v artifactId -o : -v version 2>nul



更新 (2014-02-12): 从 XMLStarlet 1.4.2 开始,PYX <-> XML 转换是固定的(不删除命名空间声明),因此上述命令将不起作用(感谢 Peter Gluck 的提示)。请改用以下命令:

xml pyx pom.xml | grep -v ^A | xml p2x | xml sel -t -m project -v groupId -o : -v artifactId -o : -v version



注意:上面的 grep 从文档中删除了所有属性,而不仅仅是命名空间声明。对于这种特定情况(从 pom.xml 中选择元素值,其中不需要具有非默认命名空间的元素)是可以的,但是对于一般的 XML,您将只删除默认命名空间声明而不是其他任何内容:

xml pyx pom.xml | grep -v "^Axmlns " | xml p2x | xml sel -t -m project -v groupId -o : -v artifactId -o : -v version



注意(已过时):错误重定向( 2>nul )对于隐藏对(现在)未知命名空间 xsi 的提示是必要的:

-:1.28: Namespace prefix xsi for schemaLocation on project is not defined



摆脱提示的另一种方法是删除 schemaLocation 属性(实际上,此命令从 PYX 文档中删除了所有属性,而不仅仅是 xsi:schemaLocation):

xml pyx pom.xml | grep -v ^A | xml p2x | xml sel -t -m project -v groupId -o : -v artifactId -o : -v version

关于command-line-interface - XMLStarlet 不选择任何内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9025492/

相关文章:

python - 我想使用 TOTP 将我的响应发送到 API?

git - 强制 git 自定义 merge 驱动程序以 merge pom.xml (maven) 文件

java - 通过命令行覆盖 Surefire 配置

xml - 如何根据给定的文件名更新 XML 中的 <path>

xmlstarlet - 如何开始学习 XMLSTARLET?

git - 获取后是否有 git 命令显示新的上游提交?

azure - 我可以使用 Azure CLI 执行与 Azure Powershell 相同的操作吗? (上传VHD)

Android string.xml 和 xmlstarlet

linux - 如何确定 tar 存档的格式

java - Dockers 上的多模块 Maven 项目