XMLStarlet不会选择任何内容

uk4*_*4sx 16 command-line-interface pom.xml xmlstarlet

我有一个典型的pom.xml,并希望打印groupId,artifactId和版本,用冒号分隔.我认为XMLStarlet是适合它的工具.我尝试了几种方法,但我总是得到一个空行.

xml sel -t -m project -v groupId -o : -v artifactId -o : -v version pom.xml
Run Code Online (Sandbox Code Playgroud)

预期产量:

org.something.apps:app-acct:5.4
Run Code Online (Sandbox Code Playgroud)

实际输出:空行

即使我尝试只打印groupId我什么也得不到:

xml sel -t -v project/groupId pom.xml
Run Code Online (Sandbox Code Playgroud)

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

xml el pom.xml
Run Code Online (Sandbox Code Playgroud)

打印以下(正确):

project
project/modelVersion
project/parent
project/parent/groupId
project/parent/artifactId
project/parent/version
project/groupId
project/artifactId
project/version
project/packaging
Run Code Online (Sandbox Code Playgroud)

怎么了?

这是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>
Run Code Online (Sandbox Code Playgroud)

uk4*_*4sx 38

不幸的是,XMLStarlet对默认命名空间非常挑剔.如果文档声明了(xmlns=),则必须为XMLStarlet声明它,并在元素前面加上您选择的名称(参见此处):

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
Run Code Online (Sandbox Code Playgroud)

但是,如果文档没有声明默认名称空间(或名称空间的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:未定义项目上schemaLocation的命名空间前缀xsi

摆脱投诉的另一种方法是删除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


Pet*_*uck 8

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

sed -e 's/ xmlns.*=".*"//g'
Run Code Online (Sandbox Code Playgroud)

那很有效.对于原始问题,语法将是:

cat pom.xml | sed -e 's/ xmlns.*=".*"//g' | xml sel -t -m project -v groupId -o : -v artifactId -o : -v version
Run Code Online (Sandbox Code Playgroud)