views:

52

answers:

2

I need to map an XML, constrained by an XSD to Java object using XStream. The XSD has 4 complex type elements, which are "choice" elements, that is either one of those 4 can be present in the XML under a root tag.

I have been looking at XStream but it seems to me that, to map such an XML, I would require 8 classes. How? here it is...

Say for example my root element is VEHICLE and each of the complex types in the XML are a) CAR b) BIKE c) TRUCK d) TRACTOR. Each of them have differing properties within them. To map this to Xstream and make the XML (generated by XStream) XSD compliant, we would need 8 classes viz. VehicleCarWrapper -> (has a) Car, VehicleTruckWrapper -> (has a) Truck, VehicleBikeWrapper -> (has a) Bike and VehicleTractorWrapper -> (has a) Tractor.

Does anyone have a suggestion apart from the shabby solution? Is there a way in Xstream to map such a "choice"d element of the XML root? So as that, All the 4 (viz. Truck, Car, Bike, Tractor) can go into the Wrapper as associated entities, but XStream ignores all but one association at all times and hence creates an XSD compliant XML.

Hope my question is clear.

Many thanks!

A: 

Here is the solution:

Vehicle class:

public class Vehicle { @XStreamAlias("vehicleAttribute") String vehicleAttribute;

}

Car class:

@XStreamAlias("car")
public class Car extends Vehicle {
    @XStreamAlias("carattribute")
    String carAttribute;
}

Bike class:

@XStreamAlias("bike")
public class Bike extends Vehicle {
    @XStreamAlias("vehicleattribute")
    String bikeAttribute;
}

Then some XStream configuration:

    XStream xstream = new XStream();
    xstream.processAnnotations(Car.class);
    xstream.processAnnotations(Bike.class);
    xstream.processAnnotations(Vehicle.class);

Create some vehicles and tell XStream to XML'em.

    System.out.println(xstream.toXML(v1));
    System.out.println(xstream.toXML(v2));

Here is the output you want:

<car>
  <carattribute>my car</carattribute>
</car>
<bike>
  <vehicleattribute>my bike</vehicleattribute>
</bike>
pablosaraiva
A: 

Why not use JAXB instead:

@XmlRootElement
public class Foo {
    @XmlElements(
        @XmlElement(name="car", type=Car.class),
        @XmlElement(name="bike", type=Bike.class),
        @XmlElement(name="truck", type=Truct.class),
        @XmlElement(name="tractor", type=Tractor.class)
    )
    public Vehicle vehicle;
}

For a comparison of JAXB & XStream see:

Blaise Doughan
For a detailed example of mapping choice structures with JAXB see: http://bdoughan.blogspot.com/2010/10/jaxb-and-xsd-choice-xmlelements.html
Blaise Doughan