Issue
Assuming I have a pom.xml containing a parent dependency like this:
<?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>
<parent>
<groupId>com.example</groupId>
<artifactId>some-parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
</project>
Is there a way I can replace the 1.0.0-SNAPSHOT
version programmatically, maybe via a script?
My use case:
- I have lots of pom.xml files that I need to change the parent version of
- I'm using git-xargs to make changes across multiple repos, so I can apply a bash script to each pom.xml to change it.
For example, I can do the following, but this will update all occurrences of 1.0.0-SNAPSHOT
in the pom.xml, and I want to limit it to just the some-parent
artifact that has a version 1.0.0-SNAPSHOT
:
git-xargs \
--branch-name test-branch \
--github-org <your-github-org> \
--commit-message "Update pom.xml" \
sed -i 's/1.0.0-SNAPSHOT/2.0.1/g' pom.xml
As per the git-xargs docs, I can use any type of script to process the pom.xml, bash, python, ruby etc: https://github.com/gruntwork-io/git-xargs#how-to-supply-commands-or-scripts-to-run
UPDATE:
The following xmlstarlet approach works up to a point:
if [[ $(xmlstarlet sel -N my=http://maven.apache.org/POM/4.0.0 -t -v '//my:project/my:parent/my:artifactId' pom.xml) == "some-parent" && $(xmlstarlet sel -N my=http://maven.apache.org/POM/4.0.0 -t -v '//my:project/my:parent/my:version' pom.xml) == "1.0.0-SNAPSHOT" ]]; then xmlstarlet edit -L -N my=http://maven.apache.org/POM/4.0.0 --update '//my:project/my:parent/my:version' --value '2.0.6' pom.xml; fi
xmlstarlet is correctly updating the xml element I want, but its also reordering the xsi:schemaLocation
, xmlns
and xmlns:xsi
at the top of my file.
It's updating it from:
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
to:
<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">
which is no good for me.
Solution
You should avoid working with xml as plain text files, but if you have no other options you may give it a try. sed
ranges (/starting-regex/,/ending-regex/{commands}
) allows to restrict your replacement within specific context. I.e. this oneliner:
sed -e '/<parent/,/\/parent/{/artifactId>some-parent/,/parent/{s/1.0.0-SNAPSHOT/2.0.0-SNAPSHOT/g}}'
will replace only version strings, which are between <parent and /parent strings, and between some-parent and parent lines, thus should only match artifacts some-parent. Obviously, there are multiple cases when it will fail, but for simple files this could work. Your ranges may be further nested.
Answered By - Maciej Wrobel Answer Checked By - Katrina (WPSolving Volunteer)