I am having a problem validating this SOAP Envelope using this snippet of code 
(below).

The error that I get is:
org.xml.sax.SAXParseException; cvc-elt.4.2: Cannot resolve 'ipo:UKAddress' to a 
type definition for element 'shipTo'.

SOAP XSD defines the Body as:

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

My expectation is that "lax" should validate if it has a definition, but ignore 
if it does not.  However, that is not the case with respect to the 
xsi:type="ipo:UKAddress".  I am only validating the SOAP Envelope - not the 
Body.

It looks like a bug in xerces-j.  In the same chunk of code, 
XMLSchemaValidator:2152 actually checks processContents before raising an error:

    else if (wildcard != null && wildcard.fProcessContents == 
XSWildcardDecl.PC_STRICT) {

Whereas, XMLSchemaValidator:2178 makes no such check and will throw no matter 
what.

    fCurrentType = getAndCheckXsiType(element, xsiType, attributes);

Any help, or confirmation that this is indeed a bug is appreciated.

Thanks,
Jamie


import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.security.CodeSource;

import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;

import org.apache.xerces.impl.Constants;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;

public class Validate {
    private static final String envelope =
            "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
            "<soapenv:Envelope \n" +
            "  xmlns=\"http://www.w3.org/2001/XMLSchema\""; +
            "  xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"; +
            "  xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\"\n"; +
            "  >\n" +
            "  <soapenv:Body>\n" +
            "    <ipo:purchaseOrder 
xmlns:ipo=\"http://www.example.com/IPO\";>\n" +
            "      <shipTo exportCode=\"1\" xsi:type=\"ipo:UKAddress\">\n" +
            "        <name>Helen Zoe</name>\n" +
            "        <street>47 Eden Street</street>\n" +
            "        <city>Cambridge</city>\n" +
            "        <postcode>CB1 1JR</postcode>\n" +
            "      </shipTo>\n" +
            "    </ipo:purchaseOrder>\n" +
            "  </soapenv:Body>\n" +
            "</soapenv:Envelope>";

    protected static final String HONOUR_ALL_SCHEMALOCATIONS =
            Constants.XERCES_FEATURE_PREFIX + 
Constants.HONOUR_ALL_SCHEMALOCATIONS_FEATURE;
    protected static final String IGNORE_XSI_TYPE_FEATURE =
    Constants.XERCES_FEATURE_PREFIX + Constants.IGNORE_XSI_TYPE_FEATURE;
    private static final String SOAP_1_1_ENVELOPE =
    "http://schemas.xmlsoap.org/soap/envelope";;
    protected static final String JAXP_SCHEMA_LANGUAGE =
    "http://java.sun.com/xml/jaxp/properties/schemaLanguage";;
    protected static final String W3C_XML_SCHEMA =
    "http://www.w3.org/2001/XMLSchema";;

    public static void validate() throws ParserConfigurationException, 
SAXException, IOException, TransformerException {
        final DocumentBuilderFactory documentBuilderFactory = 
DocumentBuilderFactory.newInstance();

        documentBuilderFactory.setNamespaceAware(true);
        documentBuilderFactory.setValidating(false);

        final Class<?> clazz = documentBuilderFactory.getClass();
        final CodeSource source = clazz.getProtectionDomain().getCodeSource();
        System.out.println("Document builder implementation: " + 
clazz.getName() + " from : " + (source == null ? "JRE" : source));

        final DocumentBuilder documentBuilder = 
documentBuilderFactory.newDocumentBuilder();
        final InputStream is = new 
ByteArrayInputStream(envelope.getBytes(StandardCharsets.UTF_8));
        final Document document = documentBuilder.parse(is);
        final DOMSource domSource = new DOMSource(document);

        final StreamSource streamSource = new StreamSource(new 
URL(SOAP_1_1_ENVELOPE).openStream());
        final SchemaFactory schemaFactory = 
SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
        final Schema schema = schemaFactory.newSchema(streamSource);

        final Validator validator = schema.newValidator();
        
validator.setFeature("http://apache.org/xml/features/validation/schema/ignore-xsi-type-until-elemdecl";,
 true);
        
validator.setFeature("http://apache.org/xml/features/honour-all-schemaLocations";,
 true);
        
validator.setFeature("http://apache.org/xml/features/validation/schema-full-checking";,
 false);
        validator.validate(domSource);
    }
}

Reply via email to