code

Its all just ones and zeroes isn't it? 
« Back to blog

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) )        
  }
}


Comments (0)

Leave a comment...

 
To leave a comment on this posterous, please login by clicking one of the following.
Posterous-login     twitter