XML : xerces-j incorrectly fails lax validation

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.java:2152 actually checks processContents before raising an error:

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

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

  fCurrentType = getAndCheckXsiType(element, xsiType, attributes);    

To me, it looks like a bug in xerces-j. Also, this problem exists in Java 8. Any help, or confirmation that this is indeed a bug is appreciated.

  package com.example.xmlvalidate;    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.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>";        private static final String SOAP_1_1_ENVELOPE =              "http://schemas.xmlsoap.org/soap/envelope";      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.validate(domSource);      }  }    

No comments:

Post a Comment