About XStream
XStream is a simple library to serialize objects to XML and back again.
1 Requirement
xstream.jar
2.example
xml:
<Function>
<description>this is a simple test></descripion>
<cases>
<case type="single">single value check</case>
<case type="duplicate">duplicate value check</case>
<cases>
</Function>
Analysis:
according to the xml structure, we should define a class named Function (no need the same name whatever, but it is better to use the same one to identify).
Class Function{
private String description;
private List cases; // since cases node include a case list
getter and setter method...
}
The following question is how we fetch the case info. if we define it as a string, we could only get the text value, we couldn't get the attribute type. So let's define a Type to manage it.
Class FunctionCase{
private String typedescriptor;
private String value;
getter and setter method...
}
so, what to do next, parse it directly? ok, let's try:
Xstream stream = new Xstream(new DomDriver());
stream.alias("Function", Function.class);
stream.alias("case", FunctionCase.class);
stream.aliasAttribute(FunctionCase.class, "typedescriptor", "type"); // since type is defined as an attribute in class FunctionCase.
Function fun = stream.fromXML(new InputStream(...));
then we can get description by fun.getDescription(); get the cases by iterate list fun.getCases();
we can get type but we can't get value. the xstream can't parse the text value directly into value fields.
As mentioned above, if we do stream.alias("case", String.class); then we can only get the text.
The problem can be resovled by ading a converter:
public class FunctionCaseConverter implements Converter{
public void marshal(Object object, HierarchicalStreamWriter writer, MarshallingContext context) {
FunctionCase io = (FunctionCase) object;
writer.startNode("case");
writer.setValue(io.getValue());
writer.addAttribute("type", io.getType());
writer.endNode();
}
public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
FunctionCase entryIO = new FunctionCase();
entryIO.setValue(reader.getValue());
entryIO.setType(reader.getAttribute("type"));
return entryIO;
}
public boolean canConvert(Class type) {
return type.equals(FunctionCase.class);
}
}
Then we should tell the xstream when it meets FunctionCase, it should convert it to our defined way:
stream.registerConverter(new FunctionCaseConverter());
OK, everything get done. Test it:)
3 Above is example from xml to object, the reverse opration works the same way.