XStream provides a TraxSource (extends SAXSource) that can be used as an input to XSLT transformation. The TraxSource uses a java Object and the corresponding XStream Object. The java object can then be directly converted to XSLT target without actually converting to XML. Lets look at an example
package com.studytrails.xml.xstream;
import java.util.ArrayList;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.TraxSource;
public class XStreamTransformationExample {
public static void main(String[] args) throws TransformerFactoryConfigurationError, TransformerException {
XStreamTransformationExample transformationExample = new XStreamTransformationExample();
transformationExample.runTransformation();
}
private void runTransformation() throws TransformerFactoryConfigurationError, TransformerException {
XStream xstream = new XStream();
xstream.alias("rss", Rss2.class);
xstream.alias("item", Item2.class);
Rss2 rss = new Rss2();
Channel2 channel = new Channel2();
rss.channel = channel;
channel.title = "Title";
channel.link = "link";
channel.image = new Image2();
channel.image.link = "image link";
Item2 item1 = new Item2();
item1.link = "item link";
item1.title = "Item Title";
channel.items = new ArrayList<Item2>();
channel.items.add(item1);
System.out.println(xstream.toXML(rss));
Transformer transformer = TransformerFactory.newInstance().newTransformer(new StreamSource("bbc.xsl"));
TraxSource traxSource = new TraxSource(rss, xstream);
StreamResult result = new StreamResult(System.out);
transformer.transform(traxSource, result);
// prints the html on console
}
}
XStream can also be used with JSON. XStream provides two drivers : a JsonHierarchicalStreamDriver and a JettisonMappedXmlDriver. The JsonHierarchicalStreamDriver can be used to write a JSON string but cannot deserialize a JSON. JettisonMappedXmlDriver can be used to deserialize a JSON but it introduces an additional dependency. In this example we deserialize a json string into a java object.
Note: The mapping from Java to JSON (and back) is limited, since not anything can be expressed in JSON as with XML. It works quite well for simple objects, but one should not expect wonders. Additionally XStream supports only Jettison 1.0.1. Any other version will not work correctly (even newer ones).
In the earlier tutorials we saw how to convert a Java object to XML and back, custom converter and basic converters. In this tutorial we look at how XStream converts array and collections from java to xml and vice versa. We will convert the following types :
- String[]
- char[]
- List
- java.util.Properties
- List
- Map<String, String>
- TreeMap<String, String> treeMap
- TreeSet treeSet
- enum
- EnumMap<testEnum, String> testEnum is an enum
- EnumSet testEnum is an enum
In the previous tutorials we saw an example of how to convert java object to XML and back. That tutorial also explained the concept of aliases and implicit collection.In the last tutorial we show how to write a custom converter. In this tutorial, lets see some of the basic built in converters of XStream and how the resultant XML from those converters look like. We will look at how the following types are converted. XStream has converters for each of these. These are just a sample of the converters that XStream has. These converters only exist for a better and faster handling of a type compared to the generic converters.
In the previous tutorials we saw an example of how to convert a java object to XML and back. That tutorial also explained the concept of aliases and implicit collection. While serializing a Java object to XML XStream uses custom converters. These converters specify how to create XML from a Java Object or how to create a Java Object from XML elements. In most cases the provided converters should suffice, however, in certain cases you may want to create your own converters. To do so create a class that implements com.thoughtworks.xstream.converters.Converter and implement the void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context); and Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context); The example below demonstrates a CustomConverter. To make the example more interesting we will write a converter to serialize a BufferedImage. The image for the example can be downloaded from here
XStream allows you to store references while converting a java object to XML. Consider a case where you have an Artist Object. The object contains albums that the artist has released, but you also want to store a reference to a ‘similar artist’. People listening to an artist might be interested in listening to a similar artist. When you convert this object to XML, XStream preserves the reference to the similar artist. It also manages circular references, so if there are no similar artist then the ‘similar artist’ field could store a reference to the Owner Artist.
XStream has multiple ways to store references. you need to use the setMode(int mode) method to set the mode. XStream allows following modes:
- NO_REFERENCES
- ID_REFERENCES
- XPATH_RELATIVE_REFERENCES
- XPATH_ABSOLUTE_REFERENCES
- SINGLE_NODE_XPATH_RELATIVE_REFERENCES
- SINGLE_NODE_XPATH_ABSOLUTE_REFERENCES
In the previous tutorial we saw how to convert Java to XML and back. In this tutorial we look at different ways to handle XML attributes using XStream. However note that the attributes are only safe if you know that the written String values are not affected by the XML parser’s white space normalization. The XML specification requires that a parser does this and it means that an attribute value of:
<element attr=" foo\t\n bar ">
</element>
will always be normalized and passed this assertion:
assertEquals("foo bar", element.getAttr());
XStream has no influence about this behavior.
In the previous tutorials we saw an example of how to create a java object from XML. That tutorial also explained the concept of aliases and implicit collection. In this tutorial we continue with that but use annotation on the java class. The advantage with annotation is that it is faster to code and develop. the disadvantage is that you bind the java class to XStream.
In the example below we convert an object of type JazzArtist to XML. JazzArtist contains fields name, isAlive, a url and a list of albums. This example uses the following annotations
- @XStreamAlias - Used on the type, field or attribute. To understand ‘aliases’ look at this tutorial
- @XStreamImplicit - Used on Collections or array. To understand ‘Implicit Collections/Arrays’ look at the this tutorial.
- @XStreamAsAttribute - Used to mark a field as an attribute.
- @XStreamConverter - Use a specific converter for this field. We will look at Converters in detail in a later tutorial. In this example we use a Boolean converter for ‘isAlive’ field, we want the XML to have values yes or no instead of true or false.
In the previous example we saw how to convert a Java Object to XML and back. In this example we look at another example of Java Object to XML Conversion. The example uses an object called a ‘JazzArtist’. This object has a list of ‘Album’ objects besides some other properties. We see here another example of Alias and implicit collection. (To understand alias and implicit collections look at this tutorial) We divide the example in three parts. In the first part we do not use aliases or implicit collections. In the second part we use aliases and in the third part we use an implicit Collection. Note the output from the three parts and observe how aliases and implicit collection change the way the output xml looks.
package com.studytrails.xml.xstream;
import java.util.ArrayList;
import java.util.List;
import com.thoughtworks.xstream.XStream;
public class CreateXMLFromMusicArtistObject {
public static void main(String[] args) {
CreateXMLFromMusicArtistObject marshaller = new CreateXMLFromMusicArtistObject();
marshaller.createXMlFromObject();
marshaller.createXMLFromObjectUsingAlias();
marshaller.createXMLFromObjectUsingAliasAndImplicitCollection();
}
In the earlier tutorial we looked at a way to convert Java to XML and back. In this tutorial we look at some more examples of XML To Java Conversion. XStream can convert XML elements to multiple types depending on the type specified in the Java class. For example a series for similarly named elements can be converted to an array of String, a List of String or an enum. XStream uses an appropriate Converter based on type specified in the java class. Lets look at some examples.
In this first example we have an XML that has a parent element called ‘Music’. It has a child element called type. We populate a Music object that has a ’type’ field which is an enum.
package com.studytrails.xml.xstream;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.annotations.XStreamAlias;
public class ConverterExample3 {
static String xml1 = "<Music><type>rock</type></Music>";
public static void main(String[] args) {
XStream xStream = new XStream();
xStream.processAnnotations(Music.class);
Music musicObject = (Music) xStream.fromXML(xml1);
System.out.println(musicObject);
// prints Music [type=ROCK]
}
}
@XStreamAlias("Music")
class Music {
public enum genre {
ROCK, JAZZ
};
genre type;
@Override
public String toString() {
return "Music [type=" + type + "]";
}
}