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