xs:extension
element<xs:complexType name="vehicle" abstract="true">
<xs:sequence>
<xs:element name="name" type="xs:string" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="car">
<xs:complexContent>
<xs:extension base="tns:vehicle">
<xs:sequence>
<xs:element name="horsepower" type="xs:string" />
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="bicycle">
<xs:complexContent>
<xs:extension base="tns:vehicle">
<xs:sequence>
<xs:element name="color" type="xs:string" />
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
The JAXB compiler generates classes like:
@XmlType(name = "vehicle"...)
@XmlSeeAlso({Bicycle.class,Car.class})
public class Vehicle {
...
}
@XmlType(name = "car"...)
public class Car {
...
}
The @XmlSeeAlso
: “Instructs JAXB to also bind other classes when binding this class.” (from javadoc)
The XmlSeeAlso
annotations results in a cyclic dependency between super-class and sub-class.
Start with Java classes and add JAXB annotaions:
@XmlRootElement(name = "vehicles")
class Vehicle { ... }
@XmlRootElement(name = "car")
class Car extends Vehicle { ... }
@XmlRootElement(name = "bicycle")
class Bicycle extends Vehicle { ... }
In this case without an annotation XmlSeeAlso
, the JAXBContext
has to be initialized with the relevant classes:
JAXBContext jaxbContext = JAXBContext.newInstance(Vehicle.class, Bicycle.class, Car.class);
With the help of org.springframework.oxm.jaxb.Jaxb2Marshaller
(which uses a org.springframework.oxm.jaxb.ClassPathJaxb2TypeScanner
),
it is possible to scan multiple packages (with their subpackages) for JAXB relevant classes and setup a JAXBContext
:
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setPackagesToScan(<package names>);
marshaller.afterPropertiesSet();
class Wrapper {
@XmlElementWrapper(name = "vehicles")
@XmlElementRef
public Vehicle[] vehicles;
}
Result:
<vehicles>
<car>
<name>myCar</name>
<horsePower>99</horsePower>
</car>
<bicycle>
<name>myBicycle</name>
<color>red</color>
</bicycle>
</vehicles>
xsi:type
Without the @XmlElementRef
the resulting xml looks like:
<vehicles>
<vehicles xsi:type="car">
<name>myCar</name>
<horsePower>99</horsePower>
</vehicles>
<vehicles xsi:type="bicycle">
<name>myBicycle</name>
<color>red</color>
</vehicles>
</vehicles>