拉出 pom.xml 中的版本

Pulling out the version in the pom.xml

我想在我的 pom.xml 文件中附加 Jenkins 内部版本号。我可以通过 Maven Version plugin 执行此操作,但首先我需要 pom.xml 文件中的原始版本。

为了做到这一点,我正在使用命令 xmllint --xpath '/project/version/text()' pom.xml 命令。但是,我不断收到 XPath set is empty

这是示例 pom.xml 文件:

<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/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <artifactId>das-artifact</artifactId>
  <name>das-name</name>
  <version>4.2</version>
</project>

这是我的输出:

$ xmllint --nsclean --xpath '/project/version/text()' pom.xml
XPath set is empty
$

但是,如果我将 xmlns 元素更改为 fooxmlns,它会起作用:

这是示例 pom.xml 文件:

<project fooxmlns="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/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <artifactId>das-artifact</artifactId>
  <name>das-name</name>
  <version>4.2</version>
</project>

这是我的输出:

$ xmllint --nsclean --xpath '/project/version/text()' pom.xml
4.2$

我不太熟悉 xmllint 可以做的所有事情。我可以让它忽略 xmlns 命名空间属性吗?

通常有两种解决方案,要么按照@A_Di-Matteo建议的路径(但我建议至少使用 Maven 3.3.9 或 3.4.0,如果已发布),或者你可以通过build-helper-maven-plugin 如下所示:

 mvn build-helper:parse-version versions:set \
     -DnewVersion=${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}-WhatEverYouLikeToAdd \
     versions:commit

这是我所做的:

<?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>
    <groupId>com.das-group</groupId>
    <artifactId>das-artifact</artifactId>
    <version>1.1.0-123</version>
    <profiles>
        <profile>
            <id>arse-version</id>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.codehaus.mojo</groupId>
                        <artifactId>build-helper-maven-plugin</artifactId>
                        <version>1.12</version>
                        <executions>
                            <execution>
                                <id>parse-version</id>
                                <goals>
                                    <goal>parse-version</goal>
                                </goals>
                            </execution>
                        </executions>
                    </plugin>
                    <plugin>
                        <groupId>org.codehaus.mojo</groupId>
                        <artifactId>versions-maven-plugin</artifactId>
                        <version>2.3</version>
                        <executions>
                            <execution>
                                <phase>validate</phase>
                                <id>set-version</id>
                                <goals>
                                    <goal>set</goal>
                                    <goal>commit</goal>
                                </goals>
                            </execution>
                        </executions>
                        <configuration>
                            <newVersion>${parsedVersion.osgiVersion}-${BUILD_NUMBER}</newVersion>
                        </configuration>
                    </plugin>
                </plugins>
            </build>
        </profile>
    </profiles>
</project>

我创建了一个配置文件 arse-version(这实际上是在我的公司 pom.xml 中,它是我们所有项目的父级),它添加了 build-helper-maven-pluginversions-maven-plugin 插件。我将它们都设置为在 validate 生命周期中执行。

现在,要在 Jenkins 中设置附加了内部版本号的版本,我可以执行这个:

$ mvn -Parse-version -DBUILD_NUMBER=$BUILD_NUMBER validate

这在管道构建和 Jenkinsfile 中非常有效。不需要单独的 shell 或 Python 脚本。无需担心 xpathxmllint 是否以特定方式安装和工作(它在我的 Mac 和 Linux 上的工作方式不同)。

我的主要问题是版本号一直在重建,而不是拿走那里的东西。如果开发人员将版本设置为 1.0 而这是构建 #23,我将获得版本 1.0.0-23。如果开发者放 1.2-3, I get1.2.3-23`。因此,我将简单地告诉所有开发人员,他们现在必须使用标准的三部分版本编号方案。

简洁明了。感谢 的回答。

注意:编辑以添加 commit 目标。这将从工作区中删除 backup pom.xml。

回答实际问题:

基于@djeikyb 在 xml - xmllint failing to properly query with xpath - Stack Overflow 的务实评论,这对我有用:

sed < pom.xml '2 s/xmlns=".*"//g' | xmllint --xpath '/project/version/text()' - 2>/dev/null

而且我仍然感到困惑,为什么 xml 使用我认为是为该任务设计的工具进行这样的解析,如果没有这种混乱,实际上就无法工作......

对每个 xml 节点使用 local-name() 函数。

Old-XPath: /project/version/text()
New-XPath: /*[local-name()="project"]/*[local-name()="version"]/text()

现在 运行 在 bash shell 你会得到

$ xmllint --xpath '/*[local-name()="project"]/*[local-name()="version"]/text()' pom.xml
1.0.0-SNAPSHOT