我正在处理XML转换。例如,
<a>
替换为<b>
<c x = "xxx">
替换为<d y="xxx">
等。我使用的是标准scala.xml
RewriteRule和RuleTransformer
。我扩展RewriteRule
并将其传递给RuleTransformer
实例,该实例将规则应用于XML。
我知道该工作还有其他工具:lenses
,zippers
等。他们可以根据需要转换XML吗?与我目前的方法相比,它们有什么优势?
答案 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也可以让你做这种事情,但它要复杂得多。