CIからpom.xmlを自動で更新するような仕組みを入れようと思って、pom.xmlを書き換える方法を調べたのでメモ。
ポイントとしては、
- 名前空間付きのもののときは
*[local-name()='hoge']
を使う - 同名のタグが複数ある場合に特定のノードのものを選択するには
and
を使う
になる。
例題
以下のようなpom.xmlで、 maven-compiler-plugin
のバージョンを変えたい。
<?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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>junit5-jupiter-starter-maven</artifactId> <version>1.0-SNAPSHOT</version> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>${maven.compiler.source}</maven.compiler.target> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.junit</groupId> <artifactId>junit-bom</artifactId> <version>5.9.1</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> </plugin> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>3.0.0-M6</version> </plugin> </plugins> </build> </project>
対応方法
たとえば以下のように記述すればよい。
VERSION=3.9.0 xmllint --shell pom.xml << EOF cd /*[local-name()='project']/*[local-name()='build']/*[local-name()='plugins']/*[local-name()='plugin' and *[local-name()='artifactId']/text() = 'maven-compiler-plugin']/*[local-name()='version'] set $VERSION save EOF
名前空間付きのタグに対しては local-name()
を使う
タグ名は実際には名前空間付きなので、テキストファイル上の名前を使って /project/build/...
のように指定することはできない。local-name()
を使って対象のタグを指定する必要がある。
同名のタグが複数ある場合に特定のノードのものを選択するには and
を使う
書き換えたい要素は <plugins>
配下に複数ある <plugin>
のうちの特定のものなので、条件を追加して指定する必要がある。以下の部分。
*[local-name()='plugin' and *[local-name()='artifactId']/text() = 'maven-compiler-plugin']
<plugin>
で、かつ <artifactId>
の内容が maven-compiler-plugin
であるものを選択するためにこのような記述をしている。
local-name()
を何度も書きたくないときは
何回も local-name()
を書くのは見た目的にもわかりづらくなるので、ルートノードからの厳密なパスを指定せずに //
を使って指定することもできる。
VERSION=3.9.0 xmllint --shell pom.xml << EOF cd //*[local-name()='plugin' and *[local-name()='artifactId']/text() = 'maven-compiler-plugin']/*[local-name()='version'] set $VERSION save EOF