Generated XSD does not unmarshall the XML

788 views Asked by At

I have an XML string, and I could not use the supplied XSD to unmarshal the object in java. So I tried to use an online tool (www.freeformatter.com/xsd-generator.html) to generate a valid xsd and got the same error. I don't understand what I'm seeing.

Here's the XML:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Message xmlns:ns1="http://www.domain.com/ws" xmlns="http://www.domain.com/ws/protocol">
    <HeaderMessage>
        <MSGTYPE>reply</MSGTYPE>
        <ORIGINATOR>XXXX</ORIGINATOR>
        <SENDER>XXXX</SENDER>
        <TIMESTAMP>2013-12-12 17:48:09.649</TIMESTAMP>
        <IDPROCESS>2013-12-12 17:48:09.649</IDPROCESS>
        <IDMESSAGE>AN-1386866889649</IDMESSAGE>
        <IDREQUEST>AN-1386866889649</IDREQUEST>
        <SERVICENAME>RESULT</SERVICENAME>
        <ERRORFLAG>OK</ERRORFLAG>
        <ERRORCODE>300</ERRORCODE>
        <ERRORMSG>Success</ERRORMSG>
    </HeaderMessage>
    <BodyMessage>
        <ns1:ServiceResultObject  isin="XX0000000000">
            <ns1:ResultObject value="true" codIsin="XX0000000000" />
        </ns1:ServiceResultObject>
    </BodyMessage>
</Message>

And here's the XSD I got from the tool:

<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://www.domain.com/ws" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:element name="ServiceResultObject">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="ResultObject">
          <xs:complexType>
            <xs:simpleContent>
              <xs:extension base="xs:string">
                <xs:attribute type="xs:string" name="value"/>
                <xs:attribute type="xs:string" name="codIsin"/>
              </xs:extension>
            </xs:simpleContent>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
      <xs:attribute type="xs:string" name="isin"/>
    </xs:complexType>
  </xs:element>
</xs:schema>

After I generate the classes, I get the error

javax.xml.bind.UnmarshalException: unexpected element (uri:"http://www.domain.com/ws/protocol", local:"Message"). Expected elements are <{http://www.domain.com/ws}ServiceResultObject>

Why do I lose all this header information? Why does the XSD not result in a schema that actually unmarshals the object? The XSD supplied by the service guys here also only defined the inner object.

1

There are 1 answers

0
bdoughan On BEST ANSWER

Since your XML document has 2 namespaces (http://www.domain.com/ws/protocol & http://www.domain.com/ws) you are going to need 2 XML schemas to represent it. One schema can reference another with an import element.

XML Schemas

Below I have started the XML Schemas that you will need for your XML.

ws.xsd (for http://www.domain.com/ws namespace)

This is part of the XML schema for the http://www.domain.com/ws. The whole one is what you have already generated.

<?xml version="1.0" encoding="UTF-8"?>
<schema 
    xmlns="http://www.w3.org/2001/XMLSchema" 
    targetNamespace="http://www.domain.com/ws" 
    xmlns:tns="http://www.domain.com/ws" 
    elementFormDefault="qualified">

    <element name="ServiceResultObject">
        <complexType>
            <sequence/>
            <attribute name="isin" type="string"/>
        </complexType>
    </element>

</schema>

ws_protocol.xsd (for http://www.domain.com/ws/protocol namespace)

Here is a partial version of the schema that you are missing for the http://www.domain.com/ws/protocol namespace. Note the import element that references the other XML Schema, and <element ref="ws:ServiceResultObject"/> which references an element from the other XML Schema.

<?xml version="1.0" encoding="UTF-8"?>
<schema 
    xmlns="http://www.w3.org/2001/XMLSchema" 
    targetNamespace="http://www.domain.com/ws/protocol" 
    xmlns:tns="http://www.domain.com/ws/protocol"
    xmlns:ws="http://www.domain.com/ws" 
    elementFormDefault="qualified">

    <import namespace="http://www.domain.com/ws" schemaLocation="ws.xsd"/>

    <element name="Message">
        <complexType>
            <sequence>
                <element name="HeaderMessage">
                    <complexType>
                        <sequence>
                            <element name="MSGTYPE" type="string"/>
                        </sequence>
                    </complexType>
                </element>
                <element name="BodyMessage">
                    <complexType>
                        <sequence>
                            <element ref="ws:ServiceResultObject"/>
                        </sequence>
                    </complexType>
                </element>
            </sequence>
        </complexType>
    </element>

</schema>

Creating the JAXBContext

Once you have the two XML Schemas the classes will generate to 2 different packages. Below is an example of how to bootstrap the JAXBContext. Note that the package names are delimited by the : character.

JAXBContext jc = JAXBContext.newInstance("com.domain.ws:com.domain.ws.protocol");