0

I have the following 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/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.qburst.app</groupId>
  <artifactId>main-app</artifactId>
  <packaging>jar</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>main-app</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>com.mycompany.app</groupId>
        <artifactId>my-app</artifactId>
        <version>1.1</version>
    </dependency>
 </dependencies>
<repositories>
 <repository>
    <id>maven</id>
    <url>http://nexus:8081/repository/maven-group/</url>
  </repository>
</repositories>
<distributionManagement>
  <snapshotRepository>
    <id>nexus</id>
    <url>http://nexus:8081/repository/maven-snapshots/</url>
  </snapshotRepository>
  <repository>
    <id>nexus</id>
    <url>http://nexus:8081/repository/maven-releases/</url>
  </repository>
</distributionManagement>
<build>
    <pluginManagement>
      <plugins>
        <plugin>
          <groupId>org.codehaus.mojo</groupId>
          <artifactId>versions-maven-plugin</artifactId>
          <version>2.5</version>
        </plugin>
      </plugins>
    </pluginManagement>
    <!-- To use the plugin goals in your POM or parent POM -->
    <plugins>
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>versions-maven-plugin</artifactId>
        <version>2.5</version>
      </plugin>
    </plugins>
</build>
</project>

I want to change a version of a particular dependency using sed command in terminal. However the following command doesnot seem to work:

sed -n -E 's/\(<dependency>[.\n\t ]*<groupId>com.mycompany.app<\/groupId>[.\S\w\n\t ]*<version>\)[0-9.]*\(<\/version>[.\n\t ]*<\/dependency>\)/\14.3\2/' pom.xml

I found out using online that the following regular expression is True However:

(<dependency>[.\n\t ]*<groupId>com.mycompany.app<\/groupId>[.\S\w\n\t ]*<version>)[0-9.]*(<\/version>[.\n\t ]*<\/dependency>)

However in sed it doesnot work. Someone please help

7
  • First of all welcome to Stack Overflow. We understand that your are excited about parsing XML with regex, but just do not do it! Tools such as sed and AWK are extremely powerful for handling text files, but when it boils down to parsing complex-structured data — such as XML, HTML, JSON, ... — they are nothing more than a sledgehammer. Yes, you can get the job done, but sometimes at a tremendous cost. For handling such delicate files, you need a bit more finesse by using a more targetted set of tools. Commented Jul 20, 2018 at 10:53
  • Not helpful. I could identify the element with the regular expression. However, in sed there was some problem. Commented Jul 20, 2018 at 10:58
  • @ABEL sed operates one line at a time, but you are trying to match multiple lines... and regex varies from tool to tool, the online tool you used probably is from a programming language like perl/python/javascript which is completely different than what is available for sed.. see unix.stackexchange.com/questions/119905/… Commented Jul 20, 2018 at 11:08
  • @ABELKURUVILLA you definetively shold not parse xml with regex, unless you also put in screws with hammer. Commented Jul 20, 2018 at 11:11
  • while you might be able to use advanced features of sed to get it working for your current problem, it is better to use a tool like xmlstarlet which was built to work with xml files.. or use a programming language like python/perl + xml modules offered by them Commented Jul 20, 2018 at 11:11

1 Answer 1

4

An excellent shell tool that can be used to do this job is . It is a bit a tough one to learn because it seems to go against everything that regex learned us as it makes use of XPath. But in the end, this is the way forward.

As you want to edit an XML file, the first thing you need to do is figure out the XPath you want to use. This is the most difficult task at hand here

Step 1: find the XPath you need

First you need to find the XPath that selects the right node. This can be done using the select option of . For this, you need to know

  1. your namespace. Your entire XML file is in the namespace: xmlns="http://maven.apache.org/POM/4.0.0", so every node needs to be referenced with this namespace.

  2. You are searching for a node named dependency who has a child groupId with a value com.mycompany.app. The XPath for this is:

    //N:dependency[N:groupId = "com.mycompany.app"]
    

    where N: is the namespace shorthand which we will define later.

  3. The value you want to change is the value of the child version, thus you have to add /N:version to the XPath expression.

So to see what you selected you can type:

$ xmlstarlet sel -N N="http://maven.apache.org/POM/4.0.0" \
                 -t -m '//N:dependency[N:groupId="com.mycompany.app"]' \
                 -c . -n pom.xml

and

$ xmlstarlet sel -N N="http://maven.apache.org/POM/4.0.0" \
                 -t -m '//N:dependency[N:groupId="com.mycompany.app"]/N:version' \
                 -c . -n pom.xml

Step 2: edit your file using the XPath you just created

Now it is time to perform the edit using the edit function in . Using the XPath earlier defined, we can easily update (-u) this one value (-v):

$ xmlstarlet ed -N N="http://maven.apache.org/POM/4.0.0" \
                -u '//N:dependency[N:groupId="com.mycompany.app"]/N:version' \
                -v "14.3" pom.xml > pom.new.xml

Step 3: verify and apply.

Verify the changes with diff or meld to check.

note: make your XPath knowledge as good as your Regex knowledge, this way you can skip step 1.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.