Generating simple XML from a Scala List[T] using XStream
I started working with XStream as a tool to quickly generate XML and/or JSON from Scala objects, it looks very powerful, but unfortunately needs some tweaking to produce simple and clean XML.
This code:
println(new XStream.toXML(List(1,2,3)))produces this XML:
<scala.coloncolon serialization="custom"> <unserializable-parents/> <scala.coloncolon> <int>1</int> <int>2</int> <int>3</int> <scala.ListSerializeEnd/> </scala.coloncolon> </scala.coloncolon>
Instead I wanted something like this:
<list> <int>1</int> <int>2</int> <int>3</int> </list>
Turns out this is possible, by writing your own custom converter:
Here's the code:
import com.thoughtworks.xstream.converters._
import com.thoughtworks.xstream.converters.collections._
import com.thoughtworks.xstream._
import com.thoughtworks.xstream.mapper._
import com.thoughtworks.xstream.io._
class ListConverter( _mapper : Mapper ) extends AbstractCollectionConverter(_mapper) {
def canConvert( clazz: Class[_]) = {
// "::" is the name of the list class, also handle nil
classOf[::[_]] == clazz || classOf[scala.Nil$] == clazz
}
def marshal( value: Any, writer: HierarchicalStreamWriter, context: MarshallingContext) = {
val list = value.asInstanceOf[List[_]]
for ( item <- list ) {
writeItem(item, context, writer)
}
}
def unmarshal( reader: HierarchicalStreamReader, context: UnmarshallingContext ) = {
var list : List[_] = Nil
while (reader.hasMoreChildren()) {
reader.moveDown();
val item = readItem(reader, context, list);
list = list ::: List(item) // be sure to build the list in the same order
reader.moveUp();
}
list
}
}
object ListConverter {
def configureXStream( stream: XStream ) = {
stream.alias("list", classOf[::[_]])
stream.alias("list", classOf[scala.Nil$])
stream.registerConverter( new ListConverter(stream.getMapper) )
}
}

