Reputation: 11723
I need to extract the Maven GAV (groupId, artifactId, version) from a large number of pom.xml
files. Not all of the POMs have a parent POM declaration, so the inheritance between parent GAV and project GAV needs to be taken into account.
I'd only like to use tools that can be easily scripted in a linux shell, e.g. bash.
Upvotes: 5
Views: 10253
Reputation: 2302
I use a groovy script called pom that I placed on PATH. It looks like this:
#!/usr/bin/env groovy
def cli = new CliBuilder(usage:'pom')
cli.h('print usage')
cli.n('do not auto-print output')
cli.p(args:1, argName:'pom', 'the POM file to use')
def options = cli.parse(args)
def arguments = options.arguments()
if (options.h || arguments.size() == 0 ) {
println cli.usage()
} else {
def fileName = options.p ? options.p : "pom.xml"
def script = arguments[0]
def output = Eval.x(new XmlSlurper().parse(new File(fileName)), "x.${script}")
if (!options.n) println output
}
Now you can extract values like this:
pom version
pom groupId
pom 'properties."project.build.sourceEncoding"'
pom -n 'modules.module.each { println it }'
pom -n 'dependencyManagement.dependencies.dependency.each { \
println "${it.groupId}:${it.artifactId}:${it.version}" \
}'
Upvotes: 1
Reputation: 13831
grep -v '\[' <( mvn help:evaluate -Dexpression="project.groupId" 2>/dev/null &&
mvn help:evaluate -Dexpression="project.artifactId" 2>/dev/null &&
mvn help:evaluate -Dexpression="project.version" 2>/dev/null )
Upvotes: 5
Reputation: 11723
The best solution I could find is using an XSL transformation. Create a file extract-gav.xsl
with the following content:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:pom="http://maven.apache.org/POM/4.0.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" omit-xml-declaration="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/pom:project">
<!-- this XML element just serves as a bracket and may be omitted -->
<xsl:element name="artifact">
<xsl:text> </xsl:text>
<!-- process coordinates declared at project and project/parent -->
<xsl:apply-templates select="pom:groupId|pom:parent/pom:groupId" mode="copy-coordinate"/>
<xsl:apply-templates select="pom:artifactId|pom:parent/pom:artifactId" mode="copy-coordinate"/>
<xsl:apply-templates select="pom:version|pom:parent/pom:version" mode="copy-coordinate"/>
</xsl:element>
</xsl:template>
<xsl:template match="*" mode="copy-coordinate">
<!-- omit parent coordinate if same coordinate is explicitly specified on project level -->
<xsl:if test="not(../../*[name(.)=name(current())])">
<!-- write coordinate as XML element without namespace declarations -->
<xsl:element name="{local-name()}">
<xsl:value-of select="."/>
</xsl:element>
<xsl:text> </xsl:text>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
This transformation can then be invoked in a shell (assuming that you have the libxslt installed) with th command xsltproc extract-gav.xsl pom.xml
This produces the output in the following format:
<artifact>
<groupId>org.example.group</groupId>
<artifactId>example-artifact</artifactId>
<version>1.2.0</version>
</artifact>
If you need a different format, the XSL transformation should be easy enough to adapt so that it suits your needs. E.g. the following transformation writes the GAV as tab-separated plain text:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:pom="http://maven.apache.org/POM/4.0.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/pom:project">
<!-- process coordinates declared at project and project/parent -->
<xsl:apply-templates select="pom:groupId|pom:parent/pom:groupId" mode="copy-coordinate"/>
<xsl:apply-templates select="pom:artifactId|pom:parent/pom:artifactId" mode="copy-coordinate"/>
<xsl:apply-templates select="pom:version|pom:parent/pom:version" mode="copy-coordinate"/>
<xsl:text> </xsl:text>
</xsl:template>
<xsl:template match="*" mode="copy-coordinate">
<xsl:if test="not(../../*[name(.)=name(current())])">
<xsl:value-of select="."/>
<xsl:text>	</xsl:text>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
Upvotes: 4