简体   繁体   中英

JAXB : how to read the xsi:type value when unmarshalling

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.

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>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM