27

我有一个典型的 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>
4

3 回答 3

58

更新:自 1.5 版起,默认命名空间前缀“_”可用,因此解决方案简化为:

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

感谢@JamieNelson 的提醒。


不幸的是,XMLStarlet 对默认命名空间非常挑剔。如果文档声明xmlns=它(

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 项目 -v groupId -o : -v artifactId -o : -v 版本 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 项目 -v groupId -o : -v artifactId -o : -v 版本

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

xml pyx pom.xml | grep -v "^Axmlns" | xml p2x | xml sel -t -m 项目 -v groupId -o : -v artifactId -o : -v 版本


注意(已过时):错误重定向 ( 2>nul) 是隐藏有关(现在)未知名称空间 xsi 的投诉所必需的:

-:1.28: 项目上 schemaLocation 的命名空间前缀 xsi 未定义

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

xml pyx pom.xml | grep -v ^A | xml p2x | xml sel -t -m 项目 -v groupId -o : -v artifactId -o : -v 版本

于 2012-01-27T08:46:17.807 回答
9

XML-> PYX -> XML 技巧对我不起作用(使用 XMLStarlet 版本 1.4.2)。但是,XMLStarlet 文档包含这个方便的sed命令,可以从 XML 文档中删除命名空间声明:

sed -e 's/ xmlns.*=".*"//g'

那行得通。对于原始问题,语法为:

cat pom.xml | sed -e 's/ xmlns.*=".*"//g' | xml sel -t -m project -v groupId -o : -v artifactId -o : -v version
于 2013-05-22T19:29:17.470 回答
4

从 xmlstarlet 1.2 版开始,您可以这样做:

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

这里还有其他一些选项:http: //xmlstar.sourceforge.net/doc/UG/ch05.html

于 2021-11-02T16:50:19.023 回答