Skip to content

Instantly share code, notes, and snippets.

@shishkin
Created March 30, 2015 16:56
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shishkin/5c804286625aee958a83 to your computer and use it in GitHub Desktop.
Save shishkin/5c804286625aee958a83 to your computer and use it in GitHub Desktop.
Combinatorial XML Transformations in Scala
import org.scalatest.{Matchers, Spec}
import scala.xml._
class XmlTest extends Spec with Matchers {
def `Set text inside XML element`() = {
val doc =
<root>
<el1>
<el15>
<el2>foo</el2>
</el15>
</el1>
<el3>
<el2>bar</el2>
</el3>
</root>
val expected = "new"
import XmlTransform._
val t = transform(
insideElement("el1")(
insideElement("el2")(
setText(expected))))
val transformed = t(doc)
(transformed \ "el1" \\ "el2").text should equal(expected)
(transformed \ "el3" \ "el2").text should not equal expected
}
}
import scala.xml._
object XmlTransform {
type RewriteRule = PartialFunction[Node, Seq[Node]]
def transform(rule: RewriteRule): Node => Seq[Node] = {
case el: Elem if rule.isDefinedAt(el) =>
rule(el)
case el: Elem =>
val replaced =
el.child.flatMap(transform(rule))
if (replaced == el.child) el
else el.copy(child = replaced)
case other => other
}
def insideElement(label: String)(rule: RewriteRule): RewriteRule = {
case el: Elem if el.label == label =>
transform(rule)(el)
}
def setText(text: String): RewriteRule = {
case el: Elem => el.copy(child = Text(text))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment