I have been provided with an xsd of a response message and am trying to parse the xml response into the jaxb generated classes. I first had a problem where the root xml element was called "response" but there was also a nested class called "response" and so was getting compile errors. To fix this I found that in the xsd I could use jaxb:class annotation to change the name of the nested java class that is created as below the nested classes were now generated as "callReport7Response" instead of "response".
<xs:element name="callReport7" minOccurs="0">
<xs:complexType>
<xs:sequence>
<xs:element name="request">
<xs:annotation><xs:appinfo><jaxb:class name="callReport7Request"/></xs:appinfo></xs:annotation>
<xs:complexType>
<xs:complexContent>
<xs:extension base="xs:anyType">
<xs:attribute name="time" type="xs:string"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>
<xs:element name="response">
<xs:annotation><xs:appinfo><jaxb:class name="callReport7Response"/></xs:appinfo></xs:annotation>
<xs:complexType>
<xs:complexContent>
<xs:extension base="xs:anyType">
<xs:attribute name="time" type="xs:string"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
Unfortunately when I try to unmarshal the response I get the error saying it cannot parse "callReport7Response" into "response"
The java looks like this:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {"any"})
@XmlRootElement(name = "response")
public static class CallReport7Response {
@XmlAnyElement
protected List<Element> any;
@XmlAttribute
protected String time;
It seems thats its trying to cast my nested object into the top level object.
09:28:34,608 ERROR [STDERR] java.lang.ClassCastException: uk.co.test.dashboard.dal.Response$Insurer$Subject$CallReport7$CallReport7Response cannot be cast to uk.co.test.dashboard.dal.Response
I am using this code to unmarshal:
Response response = new Response();
StringReader reader = new StringReader(resp);
try {
JAXBContext context = JAXBContext.newInstance(response.getClass());
Unmarshaller unmarshaller = context.createUnmarshaller();
Object o = unmarshaller.unmarshal(reader);
response = (Response) o;
} catch (JAXBException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
schema.xsd
You should move the JAXB schema annotation from the nested response element to its corresponding complex type. Below is a simplified XML schema based on what you described in your question.
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="forum14582017"
xmlns="forum14582017"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
elementFormDefault="qualified"
jaxb:version="2.1">
<xs:element name="response">
<xs:complexType>
<xs:sequence>
<xs:element name="callReport7">
<xs:complexType>
<xs:sequence>
<xs:element name="response">
<xs:complexType>
<xs:annotation>
<xs:appinfo>
<jaxb:class name="callReport7Response" />
</xs:appinfo>
</xs:annotation>
<xs:complexContent>
<xs:extension base="xs:anyType">
<xs:attribute name="time" type="xs:string" />
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Response
A class like the following will be generated (comments and accessors have been removed to save space).
package forum14582017;
import java.util.*;
import javax.xml.bind.annotation.*;
import javax.xml.namespace.QName;
import org.w3c.dom.Element;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {"callReport7"})
@XmlRootElement(name = "response")
public class Response {
@XmlElement(required = true)
protected Response.CallReport7 callReport7;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {"response"})
public static class CallReport7 {
@XmlElement(required = true)
protected Response.CallReport7 .CallReport7Response response;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {"any"})
public static class CallReport7Response {
@XmlAnyElement
protected List<Element> any;
@XmlAttribute(name = "time")
protected String time;
@XmlAnyAttribute
private Map<QName, String> otherAttributes = new HashMap<QName, String>();
}
}
}
Demo
Using the demo code below with the JAXB model generated from the XML schema above.
package forum14582017;
import java.io.File;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance("forum14582017");
Unmarshaller unmarshaller = jc.createUnmarshaller();
File xml = new File("src/forum14582017/input.xml");
Response response = (Response) unmarshaller.unmarshal(xml);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(response, System.out);
}
}
input.xml/Output
The following XML can be produced/consumed.
<?xml version="1.0" encoding="UTF-8"?>
<response xmlns="forum14582017">
<callReport7>
<response time="07:47"/>
</callReport7>
</response>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With