6

I want to append the Jenkins build number in my pom.xml file. I can do this via the Maven Version plugin, but first I need the original version from the pom.xml file.

In order to do this, I am using the command xmllint --xpath '/project/version/text()' pom.xml command. However, I keep getting XPath set is empty

Here's the sample pom.xml file:

<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>

And here's my output:

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

However, if I change the xmlns element to fooxmlns, it works:

Here's the sample pom.xml file:

<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>

And here's my output:

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

I'm not too familiar with all the stuff xmllint can do. Can I get it to ignore the xmlns namespace attribute?

David W.
  • 105,218
  • 39
  • 216
  • 337
  • would [this](https://issues.apache.org/jira/browse/MNG-5576) feature of maven 3.2.1 help you out? – A_Di-Matteo Aug 17 '16 at 13:50
  • Interesting feature, but it means that your official version in the pom is `1.0.0.${revision}`. I'm not a big fan of that. It does allow me to do continuous integration, but then in your jar is embedded the pom with the `${revision}` version ID. – David W. Aug 17 '16 at 16:10

4 Answers4

5

Use local-name() function for each xml-node.

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

And now running in the bash shell you will get

$ xmllint --xpath '/*[local-name()="project"]/*[local-name()="version"]/text()' pom.xml
1.0.0-SNAPSHOT
Boris Brodski
  • 8,425
  • 4
  • 40
  • 55
3

There in general two solutions either you go the path which @A_Di-Matteo has suggested (but there I would suggest to use at least Maven 3.3.9 or 3.4.0 if released) or you can go via a build-helper-maven-plugin like the following:

 mvn build-helper:parse-version versions:set \
     -DnewVersion=\${parsedVersion.majorVersion}.\${parsedVersion.minorVersion}.\${parsedVersion.incrementalVersion}-WhatEverYouLikeToAdd \
     versions:commit
khmarbaise
  • 92,914
  • 28
  • 189
  • 235
  • 2
    A litte convoluted, but it does work. When I saw this, I wasn't sure how to access the properties set. I wish there was just a `${parseVersion}` property, so I don't have to worry about rebuilding ``. – David W. Aug 17 '16 at 16:22
1

Here's what I did:

<?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>

I created a profile arse-version (this is actually in my corporate pom.xml that's the parent to all of our projects) that adds both the build-helper-maven-plugin and the versions-maven-plugin plugins. I set them both to execute in the validate lifecycle.

Now, to set the version with the build number appended to it in Jenkins, I can execute this:

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

This works very nicely with the pipeline builds and in the Jenkinsfile. No need for a separate shell or Python script. No need to worry whether xpath or xmllint are installed and working in a particular way (It works differently on my Mac vs. Linux).

My main issue would be that the version number keeps getting rebuilt rather than taking what's there. If a developer puts the version as 1.0 and this is build #23, I get version 1.0.0-23. If the developer put 1.2-3, I get1.2.3-23`. So, I'll simply tell all developers that they now have to use the standard three part version numbering scheme.

It's clean and simple. Thanks khmarbaise for his answer.

NOTE: Edited to add commit goal. This removes the backup pom.xml from the workspace.

Community
  • 1
  • 1
David W.
  • 105,218
  • 39
  • 216
  • 337
1

To answer the actual question:

Based on a pragmatic comment by @djeikyb at xml - xmllint failing to properly query with xpath - Stack Overflow, this worked for me:

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

And I continue to be puzzled at why xml parsing like this with a tool I presume is designed for the task doesn't actually work without this kind of kludge.....

nealmcb
  • 12,479
  • 7
  • 66
  • 91