我正在编写一个工具来使用scala更新一些xml文件(在本例中为pom.xml),因为它在java中的工作量明显高于(理论上)scala。我可以很好地解析xml文件,但我需要替换现有xml中的节点并重写结果。例如:
<dependency>
<groupId>foo</groupId>
<artifactId>bar</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
所以我想找到这样的所有节点并用以下代码替换它们:
<dependency>
<groupId>foo</groupId>
<artifactId>bar</artifactId>
<version>1.0</version> <!-- notice the lack of -SNAPSHOT here -->
</dependency>
所以,我可以简单地获得所有版本节点,但是如何用我想要的节点替换它们?
// document is already defined as the head of the xml file
nodes = for (node <- document \\ "version"; if (node.text.contains("SNAPSHOT"))) yeild node
然后我想做类似的事情:
for (node <- nodes) {
node.text = node.text.split("-")(0)
}
不起作用,因为节点是不可变的。我查看了Node的复制方法,但它不包含text
作为参数。
答案 0 :(得分:12)
你真的应该看一下有关修改XML的Stack Overflow的其他问题。查看右侧的“相关”链接。
下面:
scala> <dependency>
| <groupId>foo</groupId>
| <artifactId>bar</artifactId>
| <version>1.0-SNAPSHOT</version>
| </dependency>
res0: scala.xml.Elem =
<dependency>
<groupId>foo</groupId>
<artifactId>bar</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
scala> new scala.xml.transform.RewriteRule {
| override def transform(n: Node): Seq[Node] = n match {
| case <version>{v}</version> if v.text contains "SNAPSHOT" => <version>{v.text.split("-")(0)}</version>
| case elem: Elem => elem copy (child = elem.child flatMap (this transform))
| case other => other
| }
| } transform res0
res9: Seq[scala.xml.Node] =
<dependency>
<groupId>foo</groupId>
<artifactId>bar</artifactId>
<version>1.0</version>
</dependency>
答案 1 :(得分:2)
文本在Node
节点内表示为Element
。因此,一些功能递归将让你做一个深层复制&amp;过滤器:
def deepCopy(node:Node) : Node = node match {
case e : Elem => e.copy(child = this.child.toSeq.map(deepCopy))
case t : Text => new Text(t.text.split("-").head)
case x => x
}
免责声明:此代码未针对错误进行测试
答案 2 :(得分:0)
使用Scalate's Scuery CSS3 transforms和scala.xml.Elem#copy
:
val xml =
<dependency>
<version>1.0-SNAPSHOT</version>
<version>2.0</version>
</dependency>
new Transformer {
$("dependency > version") { node =>
node.asInstanceOf[Elem].copy(child = Text(node.text.stripSuffix("-SNAPSHOT")))
}
}.apply(xml)
产量
NodeSeq(<dependency><version>1.0</version><version>2.0</version></dependency>)