Limnic
Limnic

Reputation: 1876

Jaxb2Marshaller cvc-elt.1: Cannot find the declaration of element even though the class element is known

I have written two XSDs to generate a model and validate bodies when calling a web service.

The Maven plugin I used to generate the model is: org.codehaus.mojo:jaxb2-maven-plugin:2.3 which successfully generates the correct model from the following XSDs:

requests.xsd:

<?xml version="1.0"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:element name="SLIR" type="SLIRType"/>
    <!-- region ENUMS -->
    <xs:simpleType name="PriorityTypeType" final="restriction">
        <xs:restriction base="xs:token">
            <xs:enumeration value="NORMAL"/>
        </xs:restriction>
    </xs:simpleType>
    <xs:simpleType name="LocationTypeType" final="restriction">
        <xs:restriction base="xs:token">
            <xs:enumeration value="LAST"/>
        </xs:restriction>
    </xs:simpleType>
    <xs:simpleType name="WGSType" final="restriction">
        <xs:restriction base="xs:token">
            <xs:enumeration value="WGS-84"/>
        </xs:restriction>
    </xs:simpleType>
    <xs:simpleType name="CoordSystemType" final="restriction">
        <xs:restriction base="xs:token">
            <xs:enumeration value="LL"/>
        </xs:restriction>
    </xs:simpleType>
    <xs:simpleType name="MSIDEncType" final="restriction">
        <xs:restriction base="xs:token">
            <xs:enumeration value="ASC"/>
        </xs:restriction>
    </xs:simpleType>
    <xs:simpleType name="MSIDTypeType" final="restriction">
        <xs:restriction base="xs:token">
            <xs:enumeration value="MSISDN"/>
        </xs:restriction>
    </xs:simpleType>
    <!-- endregion -->

    <xs:complexType name="SLIRType">
        <xs:all>
            <xs:element type="ClientType" name="CLIENT"/>
            <xs:element type="MSIDListType" name="MSIDS"/>
            <xs:element type="GeoInfoType" name="GEO_INFO"/>
            <xs:element type="LocationType" name="LOC_TYPE"/>
            <xs:element type="PriorityType" name="PRIO"/>
            <xs:element type="EQoPType" name="EQoP" minOccurs="0"/>
        </xs:all>
        <xs:attribute type="xs:string" name="ver" default="1.0"/>
    </xs:complexType>

    <xs:complexType name="ClientType">
        <xs:sequence>
            <xs:element type="xs:string" name="ID"/>
            <xs:element type="xs:string" name="PWD"/>
        </xs:sequence>
    </xs:complexType>

    <xs:complexType name="MSIDType">
        <xs:simpleContent>
            <xs:extension base="xs:string">
                <xs:attribute type="MSIDEncType" name="msid_enc" use="required"/>
                <xs:attribute type="MSIDTypeType" name="msid_type" use="required"/>
            </xs:extension>
        </xs:simpleContent>
    </xs:complexType>

    <xs:complexType name="MSIDListType">
        <xs:sequence>
            <xs:element type="MSIDType" name="MSID" maxOccurs="unbounded"/>
        </xs:sequence>
    </xs:complexType>

    <xs:complexType name="GeoInfoType">
        <xs:attribute type="WGSType" name="datum" use="required"/>
        <xs:attribute type="CoordSystemType" name="coord_sys" use="required"/>
    </xs:complexType>

    <xs:complexType name="LocationType">
        <xs:attribute type="LocationTypeType" name="loc_type_type" use="required"/>
    </xs:complexType>

    <xs:complexType name="PriorityType">
        <xs:attribute type="PriorityTypeType" name="prio_type" use="required"/>
    </xs:complexType>
    <xs:complexType name="EQoPType">
        <!-- unknown -->
    </xs:complexType>


</xs:schema>

responses.xsd:

<?xml version="1.0"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="unqualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:element name="SLIA" type="SLIAType"/>
    <xs:complexType name="LL_POINTType">
        <xs:sequence>
            <xs:element type="xs:double" name="LAT"/>
            <xs:element type="xs:double" name="LONG"/>
        </xs:sequence>
    </xs:complexType>
    <xs:complexType name="POINTType">
        <xs:sequence>
            <xs:element type="LL_POINTType" name="LL_POINT"/>
        </xs:sequence>
    </xs:complexType>
    <xs:complexType name="CIRCLEType">
        <xs:sequence>
            <xs:element type="POINTType" name="POINT"/>
            <xs:element type="xs:integer" name="RAD"/>
        </xs:sequence>
    </xs:complexType>
    <xs:complexType name="SHAPEType">
        <xs:sequence>
            <xs:element type="CIRCLEType" name="CIRCLE"/>
        </xs:sequence>
    </xs:complexType>
    <xs:complexType name="PDType">
        <xs:sequence>
            <xs:element type="xs:integer" name="TIME"/>
            <xs:element type="SHAPEType" name="SHAPE"/>
        </xs:sequence>
    </xs:complexType>
    <xs:complexType name="POSERRResultType">
        <xs:simpleContent>
            <xs:extension base="xs:string">
                <xs:attribute type="xs:string" name="resid"/>
            </xs:extension>
        </xs:simpleContent>
    </xs:complexType>
    <xs:complexType name="POSERRType">
        <xs:sequence>
            <xs:element type="POSERRResultType" name="RESULT" />
            <xs:element type="xs:string" name="TIME" />
        </xs:sequence>
    </xs:complexType>
    <xs:complexType name="POSType">
        <xs:sequence>
            <xs:element type="xs:string" name="MSID"/>
            <xs:choice minOccurs="0">
                <xs:element type="PDType" name="PD"/>
                <xs:element type="POSERRType" name="POSERR"/>
            </xs:choice>
        </xs:sequence>
    </xs:complexType>
    <xs:complexType name="RESULTType">
        <xs:simpleContent>
            <xs:extension base="xs:string">
                <xs:attribute type="xs:string" name="resid"/>
            </xs:extension>
        </xs:simpleContent>
    </xs:complexType>
    <xs:complexType name="SLIAType">
        <xs:sequence>
            <xs:element type="POSType" name="POS" minOccurs="0"/>
            <xs:element type="xs:string" name="GMT_OFF"/>
            <xs:element type="RESULTType" name="RESULT"/>
            <xs:element type="xs:string" name="ADD_INFO" minOccurs="0"/>
        </xs:sequence>
        <xs:attribute type="xs:string" name="ver"/>
    </xs:complexType>
</xs:schema>

Now, marshalling objects created with the generated ObjectFactory works fine, but unmarshalling bodies I receive from the web service, such as:

<SLIA ver="1.0">
    <POS>
        <MSID>ah827cgs</MSID>
        <PD>
            <TIME>20191025112228</TIME>
            <SHAPE>
                <CIRCLE>
                    <POINT>
                        <LL_POINT>
                            <LAT></LAT>
                            <LONG></LONG>
                        </LL_POINT>
                    </POINT>
                    <RAD>500</RAD>
                </CIRCLE>
            </SHAPE>
        </PD>
    </POS>
    <GMT_OFF>+0000</GMT_OFF>
    <RESULT resid="0">OK</RESULT>
</SLIA>

give the error org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 17; cvc-elt.1: Cannot find the declaration of element 'SLIA'.. So far, I have come to the conclusion that this is because there is no defined namespace, but I cannot control that and I don't wish to control that, and surely it shouldn't matter when unmarshalling in such a confined context (limited amount of known elements and predefined XML).

I'm configuring the Jaxb2Marshaller like this:

@Bean
public Jaxb2Marshaller marshaller(
        @Value("classpath:/schemas/gmlc-requests.xsd") Resource reqSchema,
        @Value("classpath:/schemas/gmlc-responses-new.xsd") Resource resSchema
) {
    Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
    marshaller.setPackagesToScan("xml.gmlc.v1.request.**", "xml.gmlc.v1.response.**");
    marshaller.setSchemas(reqSchema, resSchema);
    return marshaller;
}

and using it like this:

Object sliaElement = marshaller.unmarshal(new StringSource(xmlResponse));

Is there a way to make Jaxb2Marshaller unmarshal this response message while also validating it using the response XSD? It should remain in the default namespace.

Using an external validator website providing it with the response XSD and body mentioned above, the result is valid, so I don't think the XSD is wrong, and looking into the source code of the Jaxb2Marshaller, this error comes from schema validation so something strange is happening there.

Upvotes: 2

Views: 807

Answers (1)

koenge
koenge

Reputation: 91

Why are the elements split over 2 XSDs? I believe the issue is in the setSchemas method. Jaxb will try to validate against the first matching schema (based on namespace); which will be the requestSchema.

Try with providing only a single schema and unmarshal the corresponding xml message or combining the schema into a single file.

Upvotes: 3

Related Questions