Change dependency version number in pom.xml using scala-xml

87 views Asked by At

I want to use scala-xml to change the version number of one dependency in a bunch of pom.xml files. I know this is normally not the best way to approach such a task but in my use case I think it is.

Here is an example pom.xml

<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.mycompany.app</groupId>
    <artifactId>theArtifactId</artifactId>
    <packaging>jar</packaging>
    <version>1.0</version>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>3.6.3.Final</version>
        </dependency>
    </dependencies>
</project>

I want to change the version of hibernate-core to MY-SNAPSHOT. This is my attempt to do this and I think it is close to a solution:

import scala.xml.transform.{RewriteRule, RuleTransformer}
import scala.xml.{Node, Elem, XML}

val newVersion = "MY-SNAPSHOT"

val rewriteRule = new RewriteRule {
  override def transform(node: Node): Seq[Node] =
    node match {
      case e @ Elem(_, "dependency", _, _, _*) if (e \ "artifactId").text == "hibernate-core" => {
        val content = e.child.collect {
          case e @ Elem(_, "version", _, _, _*) => <version>{newVersion}</version>
          case e: Elem                          => e
        }
        <dependency>{content}</dependency>
      }
      case _ => node
    }
}

val pom = XML.loadFile("example-pom.xml")
val transform = new RuleTransformer(rewriteRule)
println(transform(pom).toString())

The problem is this somehow pulls the project attributes into the groupId and artifactId xml tags and duplicates them in the project tag, and it doesn't apply the correct formatting. How do I solve this?

I have seen various similar questions in this site but I'm not able to apply them to my problem.

EDIT: I simplified the transform method a bit and was able to fix the formatting but I do not understand how this attribute ends up in the wrong tags.

override def transform(node: Node): Seq[Node] =
    node match {
      case e: Elem if e.label == "dependency" && (e \ "artifactId").text == "hibernate-core" => {
        val content = e.child.map(child =>
          child.label match {
            case "version" => <version>{newVersion}</version>
            case _         => child
          }
        )
        <dependency>{content}</dependency>
      }
      case _ => node
    }
0

There are 0 answers