Reputation: 42050
I am dealing with XML transformations right now. For example,
<a>
with <b>
<c x = "xxx">
with <d y="xxx">
etc.I am using standard scala.xml
RewriteRule and RuleTransformer
. I extend RewriteRule
and pass it to a RuleTransformer
instance, which applies the rule to XML.
I know there are other tools for that job: lenses
, zippers
, etc. Can they transform XMLs as I need? What are their advantages in comparison to my current approach?
Upvotes: 1
Views: 427
Reputation: 139028
First for a side note: the Scala XML scene is pretty sad. Anti-XML was promising, but is now mostly abandoned (Arktekk got it working on 2.10, but I'm not sure how active that development is). Anti-XML did have a really neat zipper implementation, though, that would allow you to write stuff like this:
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
And then:
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>
The basic idea is that you use selectors like \\
to navigate into the XML, make "changes" locally with map
, etc., and then back out of the zipper with unselect
. This is the key benefit of using zippers (or lenses) for XML transformation—you get very imperative-like syntax for editing (it looks more or less just like navigation plus local changes) but also all the benefits of immutability.
Scales XML also lets you do this kind of thing, but it's quite a bit more complex.
Upvotes: 1