Lawrence Tierney
Lawrence Tierney

Reputation: 898

How do I validate XML using XSD?

I've made a mistake but I can't see what it is...

I'm trying to validate a piece of XML (a SOAP message) using Java, against an XSD. It's failing on what I think should be a valid piece of XML/message with the Exception:

org.xml.sax.SAXParseException: cvc-elt.1: Cannot find the declaration of element 'tns:Envelope'.
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:203).

Note 1: I've debugged xmlSource and xsdSource and they contain the expected Readers with the expected Strings.

Note 2: The content of the XML cannot be changed. I am a consumer only.

Note 3: As the XML is a SOAP message I grabbed the XSD from the Web. This therefore could be incorrect.

Note 4: I've simplified the incoming message for brevity but get the same error with the "actual" message.

Java

@Override
public boolean isMessageValid(final String xml) {
    try {
        final Source xmlSource = getStreamSource(xml);
        final Source xsdSource = getStreamSource(fileService.getResourceFileAsString("xsd/soap-envelope.xsd"));

        final SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
        final Schema schema = schemaFactory.newSchema(xsdSource);
        final Validator validator = schema.newValidator();
        validator.validate(xmlSource);
        return true;
    } catch (final Exception ex) {
        LOG.error("Exception whilst validating message", ex);
        return false;
    }
}

private StreamSource getStreamSource(final String xml) {
    return new StreamSource(new StringReader(xml));
}

XML

<?xml version="1.0" encoding="UTF-8"?>
<tns:Envelope xsi:schemaLocation="http://www.w3.org/2001/12/soap-envelope soap-envelope.xsd"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tns="http://www.w3.org/2001/12/soap-envelope">
    <tns:Body>
        <!-- snipped -->
        <someThing>else</someThing>
    </tns:Body>
</tns:Envelope>

XSD

<?xml version='1.0' encoding='UTF-8' ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns:tns="http://schemas.xmlsoap.org/soap/envelope/"
           targetNamespace="http://schemas.xmlsoap.org/soap/envelope/" >


    <!-- Envelope, header and body -->
    <xs:element name="Envelope" type="tns:Envelope" />
    <xs:complexType name="Envelope" >
        <xs:sequence>
            <xs:element ref="tns:Header" minOccurs="0" />
            <xs:element ref="tns:Body" minOccurs="1" />
            <xs:any namespace="##other" minOccurs="0" maxOccurs="unbounded" processContents="lax" />
        </xs:sequence>
        <xs:anyAttribute namespace="##other" processContents="lax" />
    </xs:complexType>

    <xs:element name="Header" type="tns:Header" />
    <xs:complexType name="Header" >
        <xs:sequence>
            <xs:any namespace="##other" minOccurs="0" maxOccurs="unbounded" processContents="lax" />
        </xs:sequence>
        <xs:anyAttribute namespace="##other" processContents="lax" />
    </xs:complexType>

    <xs:element name="Body" type="tns:Body" />
    <xs:complexType name="Body" >
        <xs:sequence>
            <xs:any namespace="##any" minOccurs="0" maxOccurs="unbounded" processContents="lax" />
        </xs:sequence>
        <xs:anyAttribute namespace="##any" processContents="lax" >
            <xs:annotation>
                <xs:documentation>
                    Prose in the spec does not specify that attributes are allowed on the Body element
                </xs:documentation>
            </xs:annotation>
        </xs:anyAttribute>
    </xs:complexType>


    <!-- Global Attributes.  The following attributes are intended to be usable via qualified attribute names on any complex type referencing them.  -->
    <xs:attribute name="mustUnderstand" >
        <xs:simpleType>
            <xs:restriction base='xs:boolean'>
                <xs:pattern value='0|1' />
            </xs:restriction>
        </xs:simpleType>
    </xs:attribute>
    <xs:attribute name="actor" type="xs:anyURI" />

    <xs:simpleType name="encodingStyle" >
        <xs:annotation>
            <xs:documentation>
                'encodingStyle' indicates any canonicalization conventions followed in the contents of the containing element.  For example, the value 'http://schemas.xmlsoap.org/soap/encoding/' indicates the pattern described in SOAP specification
            </xs:documentation>
        </xs:annotation>
        <xs:list itemType="xs:anyURI" />
    </xs:simpleType>

    <xs:attribute name="encodingStyle" type="tns:encodingStyle" />
    <xs:attributeGroup name="encodingStyle" >
        <xs:attribute ref="tns:encodingStyle" />
    </xs:attributeGroup>

    <xs:element name="Fault" type="tns:Fault" />
    <xs:complexType name="Fault" final="extension" >
        <xs:annotation>
            <xs:documentation>
                Fault reporting structure
            </xs:documentation>
        </xs:annotation>
        <xs:sequence>
            <xs:element name="faultcode" type="xs:QName" />
            <xs:element name="faultstring" type="xs:string" />
            <xs:element name="faultactor" type="xs:anyURI" minOccurs="0" />
            <xs:element name="detail" type="tns:detail" minOccurs="0" />
        </xs:sequence>
    </xs:complexType>

    <xs:complexType name="detail">
        <xs:sequence>
            <xs:any namespace="##any" minOccurs="0" maxOccurs="unbounded" processContents="lax" />
        </xs:sequence>
        <xs:anyAttribute namespace="##any" processContents="lax" />
    </xs:complexType>

</xs:schema>

I reckon I've done something noddy.

Thanks in advance

Upvotes: 0

Views: 137

Answers (1)

Michael Kay
Michael Kay

Reputation: 163595

The prefix "tns" is bound to different namespaces in the source and in the schema. So this is not a schema for the vocabulary of your source document.

Upvotes: 1

Related Questions