首先附注:Scala XML 场景非常可悲。Anti-XML很有希望,但现在大部分都被放弃了(Arktekk 让它在 2.10 上工作,但我不确定这种开发有多活跃)。不过, Anti-XML 确实有一个非常简洁的 zipper 实现,它允许您编写如下内容:
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
等在本地进行“更改”,然后使用unselect
. 这是使用 zippers(或镜头)进行 XML 转换的主要好处——您可以获得非常类似于命令式的编辑语法(它看起来或多或少有点像导航和本地更改),而且还具有不变性的所有好处。
Scales XML也允许您做这种事情,但它相当复杂。