Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Transforming XML using RewriteRule and RuleTransformer
// Import the magic libraries
import scala.xml._
import scala.xml.transform._
// Source xml. In Scala, xml is literal.
val xml =
<user>
<email>joe@example.com</email>
<password>secret</password>
<features>
<feature id="one"/>
<feature id="two"/>
<feature id="three"/>
</features>
<foo>
<bar id="qux" name="caddr"/>
<bar id="baz" name="cdddr"/>
</foo>
</user>
// The problem: replace the "features" list in the above XML
// with a new features list: ["a", "b", "c", "d"]
// Define a function to take a dom and replace the existing
// list of features with a new list of features.
def replaceFeatures(dom: Node, features: List[String]): Node = {
// You can define objects (or classes) inside functions.
object replaceFeatures extends RewriteRule {
// The rule replaces any "features" element with a new
// features element we build for the occasion.
override def transform(n: Node): Seq[Node] = n match {
// match on the "features" element
case Elem(prefix, "features", attribs, scope, _*) =>
// XML literals again...
// Can embed scala inside an XML literal: In this case,
// apply an anonymous function over the list of features
// in the original parameter list of the replaceFeatures
// function. The func turns a feature name into a feature
// node.
<features>
{ features map { d => <feature id={d}/> } }
</features>
// That which we cannot speak of, we must pass over
// in silence....
case other =>
other
}
}
// Subclass a RuleTransformer (because it's abstract), handing
// it a vararg list of rules to use (in this case, just one).
object transform extends RuleTransformer(replaceFeatures)
// Do the transform. (A scala function's return value is the
// value of the last expression (and everything's an expression).
transform(xml)
}
// Transform the xml, replacing the existing feature list
// with a new list constructed from our feature list.
val newXml = replaceFeatures(xml, List("a", "b", "c", "d"))
// Just for fun...
//
// Create a partial function pp so we don't have to have a nasty object
// floating around. pp(xml) is much better than printer.format(xml),
// eh? The underscore stands for the expected value.
val pp = new PrettyPrinter(123, 2).format(_:Node)
// Print before and after
println("before = \n" + pp(xml))
println("after = \n" + pp(newXml))
@zentrope

This comment has been minimized.

Copy link
Owner Author

zentrope commented Dec 4, 2010

I had a problem similar to the above at work. Basically, I need to take an existing XML doc and alter some values so that I could then save it back to a data store. If you've ever had to work with DOM manipulation, you know it's pretty painful. I really like the Scala solution. Also, I love the "partial function" thing at the end. I really need to do more of that in my own code.

@zentrope

This comment has been minimized.

Copy link
Owner Author

zentrope commented Dec 4, 2010

Output

before =

joe@example.com
secret









after =

<user>
  <email>joe@example.com</email>
  <password>secret</password>
  <features>
    <feature id="a"></feature>
    <feature id="b"></feature>
    <feature id="c"></feature>
    <feature id="d"></feature>
  </features>
  <foo>
    <bar name="caddr" id="qux"></bar>
    <bar name="cdddr" id="baz"></bar>
  </foo>
</user>
@christoph-neumann

This comment has been minimized.

Copy link

christoph-neumann commented Jan 8, 2014

I love that when I search for Scala examples, your gists keep popping up! Thanks again!

@baallezx

This comment has been minimized.

Copy link

baallezx commented Jun 6, 2014

Hey I am interested in your code for doing xml transformations, but I am completely new to scala can you help explain the process of running this file?

@zebaslam

This comment has been minimized.

Copy link

zebaslam commented Aug 5, 2015

Does this work if there iare XML entities present in the file?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.