Reputation: 27286
I am using JAXB in the XSD / XML to Java direction. My XSD contains derived types and the XML I have to unmarshall contain xsi:type attributes. Looking at the code JAXB (the default Sun implementation) has generated (for the unmarshalling) there seems to appear no methods to get these attributes.
Is it because I can always do a getClass()
on the unmarshalled Java object and find the actual class?
Still, would it not be the case that depending on the packages or classes I provide to the JAXBContext.newInstance
some base class may be instantiated instead? (one that is a superclass of the class corresponding to the actual value of the xsi:type attribute). In such a case being able to read the value of the actual attribute as it appears in the XML instance could be needed.
Upvotes: 4
Views: 8281
Reputation: 149007
The JAXB (JSR-222) implementation will take care of everything for you. JAXB considers that each class corresponds to a complex type. It has an algorithm for figuring out the type name, but you can override this using the @XmlType
annotation. When an element is unmarshalled if it contains an xsi:type
attribute then JAXB will look to see if there is a class associated with that type. If there is it will instantiate a class of that type, if not it will instantiate the type that corresponds to that element based on the mapping metadata supplied via annotations.
For More Information
UPDATE
Below is an example that may help:
schema.xsd
In the XML schema below the complex type canadianAddress
extends the complexType address
.
<?xml version="1.0" encoding="UTF-8"?>
<schema
xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.example.org/customer"
xmlns:tns="http://www.example.org/customer"
elementFormDefault="qualified">
<element name="customer">
<complexType>
<sequence>
<element name="address" type="tns:address"/>
</sequence>
</complexType>
</element>
<complexType name="address">
<sequence>
<element name="street" type="string"/>
</sequence>
</complexType>
<complexType name="canadianAddress">
<complexContent>
<extension base="tns:address">
<sequence>
<element name="postalCode" type="string"/>
</sequence>
</extension>
</complexContent>
</complexType>
</schema>
Demo
In the demo code below the XML will be converted to the JAXB model generated from the above XML schema, and then converted back to XML.
import java.io.File;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance("org.example.customer");
Unmarshaller unmarshaller = jc.createUnmarshaller();
File xml = new File("src/org/example/customer/input.xml");
Customer customer = (Customer) unmarshaller.unmarshal(xml);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(customer, System.out);
}
}
input.xml/Output
Below is the XML. The address
element is qualified with xsi:type
to indicate that it holds an instance of canadianAddress
instead of just an address
.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<customer xmlns="http://www.example.org/customer">
<address xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="canadianAddress">
<street>1 A Street</street>
<postalCode>Ontario</postalCode>
</address>
</customer>
Upvotes: 3