In most respects Scala makes it very easy to handle XML, but there are a few things that are hard to do. One is changing the value of an existing attribute on an element, or adding a new attribute to an element.
The simplest way I found to add new attributes c="CCC" d="DDD"
is to do:
val modified = elem %
new UnprefixedAttribute("c","CCC",Null) %
new UnprefixedAttribute("d","DDD",Null)
This is a bit verbose. What if instead you could do
val modified = elem % Map( "c"->"CCC", "d"->"DDD" )
Well you can, if you add the following implicit somewhere in scope:
implicit def pimp(elem:Elem) = new {
def %(attrs:Map[String,String]) = {
val seq = for( (n,v) <- attrs ) yield new UnprefixedAttribute(n,v,Null)
(elem /: seq) ( _ % _ )
}
}
This uses the library pimping pattern discussed elsewhere to effectively add a new version of the %
operator to Elem that takes a Map of attributes.
The new %
operator uses a for-yield construct to convert the attrs Map into a sequence of UnprefixedAttribute objects. It then uses the /:
fold operator to repeatedly apply the built-in %
operator, reducing down to an element with all the attributes added.