Scala中的XML转换

时间:2014-06-12 16:59:49

标签: xml scala zipper

我正在处理XML转换。例如,

  • 将所有节点<a>替换为<b>
  • 将所有节点<c x = "xxx">替换为<d y="xxx">等。

我使用的是标准scala.xml RewriteRuleRuleTransformer。我扩展RewriteRule并将其传递给RuleTransformer实例,该实例将规则应用于XML。

我知道该工作还有其他工具:lenseszippers等。他们可以根据需要转换XML吗?与我目前的方法相比,它们有什么优势?

1 个答案:

答案 0 :(得分:2)

首先是旁注:Scala XML场景非常难过。 Anti-XML很有希望,但现在大多被放弃了(Arktekk got it working on 2.10,但我不确定这种发展是多么活跃)。但是,反XML确实有a really neat zipper implementation,这样你就可以编写这样的东西:

import com.codecommit.antixml._

val myDoc = <foo><a/><c x="xxx"/><a bar="baz"><b/></a></foo>.convert

def replaceA(e: Elem) = (e \\ "a").map(_.copy(name = "AAA")).unselect

def replaceXxxC(e: Elem) = (e \\ "c").filter(
  _.attrs.get("x").exists(_ == "xxx")
).map(_ => <d y="xxx"/>.convert).unselect

然后:

scala> println(replaceA(myDoc))
<foo><AAA/><c x="xxx"/><AAA bar="baz"><b/></AAA></foo>

scala> println(replaceXxxC(myDoc))
<foo><a/><d y="xxx"/><a bar="baz"><b/></a></foo>

基本思路是使用\\等选择器导航到XML,使用map在本地进行“更改”等,然后使用{{1}退出拉链}。这是使用拉链(或镜头)进行XML转换的关键优势 - 您可以获得非常强制性的编辑语法(它看起来或多或少就像导航和本地更改一样),但也具有不变性的所有好处。

Scales XML也可以让你做这种事情,但它要复杂得多。