JDK-6529766 : XML Schema validation broken in JDK 6
  • Type: Bug
  • Component: xml
  • Sub-Component: javax.xml.validation
  • Affected Version: 6
  • Priority: P3
  • Status: Closed
  • Resolution: Duplicate
  • OS: linux
  • CPU: x86
  • Submitted: 2007-03-01
  • Updated: 2012-04-25
  • Resolved: 2007-03-08
Related Reports
Duplicate :  
Description
Run this program:

---%<---
import java.io.StringReader;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilderFactory;
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.Element;
import org.xml.sax.InputSource;
public class SchemaValidation {
    public static void main(String[] args) throws Exception {
        SchemaFactory f = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
        String schema = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
            "<xsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"" +
            "            targetNamespace=\"uri:foo\"" +
            "            xmlns=\"uri:foo\"" +
            "            elementFormDefault=\"qualified\">" +
            "    <xsd:element name=\"root\">" +
            "        <xsd:complexType>" +
            "            <xsd:sequence>" +
            "            </xsd:sequence>" +
            "        </xsd:complexType>" +
            "    </xsd:element>" +
            "</xsd:schema>";
        Schema s = f.newSchema(new StreamSource(new StringReader(schema)));
        Validator v = s.newValidator();
        String xml = "<root xmlns=\"uri:foo\">" +
            "</root>";
        Element el = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new InputSource(new StringReader(xml))).getDocumentElement();
        v.validate(new DOMSource(el));
        System.out.println("OK");
    }
}
---%<---

I get, on JDK 5 and 6:

---%<---
java version "1.5.0_11"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_11-b03)
Java HotSpot(TM) Client VM (build 1.5.0_11-b03, mixed mode, sharing)

OK
---%<---
java version "1.6.0"
Java(TM) SE Runtime Environment (build 1.6.0-b105)
Java HotSpot(TM) Client VM (build 1.6.0-b105, mixed mode, sharing)

Exception in thread "main" org.xml.sax.SAXParseException: cvc-elt.1: Cannot find the declaration of element 'root'.
	at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:195)
	at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.error(ErrorHandlerWrapper.java:131)
	at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:384)
	at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:318)
	at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.handleStartElement(XMLSchemaValidator.java:1887)
	at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.startElement(XMLSchemaValidator.java:685)
	at com.sun.org.apache.xerces.internal.jaxp.validation.DOMValidatorHelper.beginNode(DOMValidatorHelper.java:273)
	at com.sun.org.apache.xerces.internal.jaxp.validation.DOMValidatorHelper.validate(DOMValidatorHelper.java:240)
	at com.sun.org.apache.xerces.internal.jaxp.validation.DOMValidatorHelper.validate(DOMValidatorHelper.java:186)
	at com.sun.org.apache.xerces.internal.jaxp.validation.ValidatorImpl.validate(ValidatorImpl.java:100)
	at javax.xml.validation.Validator.validate(Validator.java:127)
	at SchemaValidation.main(SchemaValidation.java:31)
---%<---

JDK 7 is similar to JDK 6.

I was originally trying to reproduce a somewhat different problem. I was running validation of some NetBeans project files against e.g.

http://www.netbeans.org/nonav/source/browse/ant/freeform/src/org/netbeans/modules/ant/freeform/resources/freeform-project-general-2.xsd

Under JDK 5, validation went as expected (passes and failures). Under JDK 6, I get validation failures for inexplicable reasons:

1. In some cases, the validator complains that a required attribute is missing from an element. The schema does indeed mark the attribute as required, but the element did have the attribute.

2. In other cases, the validator complains that an attribute is not permitted on an element. The attribute was really on the element, but the schema permitted (in fact required) it.

However, in the course of trying to reproduce these more subtle problems I found that I could not get even a hello-world schema validation to run in JDK 6, so that is what I am reporting for now.
OK, with the namespaceAware issue out of the way (sort of), I can focus on the actual problem I was having. (My real code in which I observed the bug does set namespaceAware=true, so that was just an artifact of my trying to come up with a small test case.)

Run this with a boolean arg:

---%<---
import java.io.StringReader;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilderFactory;
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.w3c.dom.Element;
public class SchemaValidation {
    public static void main(String[] args) throws Exception {
        SchemaFactory f = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
        String schema = "<?xml version='1.0' encoding='UTF-8'?>" +
            "<xsd:schema xmlns:xsd='http://www.w3.org/2001/XMLSchema'" +
            "            targetNamespace='uri:foo' xmlns='uri:foo'" +
            "            elementFormDefault='qualified'>" +
            "  <xsd:element name='root'>" +
            "    <xsd:complexType>" +
            "      <xsd:sequence>" +
            "        <xsd:element name='inner'>" +
            "          <xsd:complexType>" +
            "            <xsd:sequence/>" +
            "            <xsd:attribute name='attr' use='required'/>" +
            "          </xsd:complexType>" +
            "        </xsd:element>" +
            "      </xsd:sequence>" +
            "    </xsd:complexType>" +
            "  </xsd:element>" +
            "</xsd:schema>";
        Schema s = f.newSchema(new StreamSource(new StringReader(schema)));
        Validator v = s.newValidator();
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        dbf.setNamespaceAware(true);
        Document doc = dbf.newDocumentBuilder().getDOMImplementation().createDocument("uri:foo", "root", null);
        Element inner = doc.createElementNS("uri:foo", "inner");
        doc.getDocumentElement().appendChild(inner);
        if (Boolean.parseBoolean(args[0])) {
            System.out.println("setting attribute");
            inner.setAttribute("attr", "whatever");
        }
        v.validate(new DOMSource(doc));
        System.out.println("OK");
    }
}
---%<---

I get, with JDK 5 and 6 (again 7 is similar to 6) and arg true and false:

---%<---
setattr=true
java version "1.5.0_11"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_11-b03)
Java HotSpot(TM) Client VM (build 1.5.0_11-b03, mixed mode, sharing)

setting attribute
OK

setattr=false
java version "1.5.0_11"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_11-b03)
Java HotSpot(TM) Client VM (build 1.5.0_11-b03, mixed mode, sharing)

ERROR:  'cvc-complex-type.4: Attribute 'attr' must appear on element 'inner'.'
Exception in thread "main" org.xml.sax.SAXParseException: cvc-complex-type.4: Attribute 'attr' must appear on element 'inner'.
	at com.sun.org.apache.xerces.internal.jaxp.validation.Util.toSAXParseException(Util.java:109)
	at com.sun.org.apache.xerces.internal.jaxp.validation.ErrorHandlerAdaptor.error(ErrorHandlerAdaptor.java:104)
	at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:382)
	at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:316)
	at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator$XSIErrorReporter.reportError(XMLSchemaValidator.java:429)
	at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.reportSchemaError(XMLSchemaValidator.java:3185)
	at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.addDefaultAttributes(XMLSchemaValidator.java:2910)
	at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.handleStartElement(XMLSchemaValidator.java:2098)
	at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.startElement(XMLSchemaValidator.java:705)
	at com.sun.org.apache.xerces.internal.jaxp.validation.ValidatorHandlerImpl.startElement(ValidatorHandlerImpl.java:335)
	at com.sun.org.apache.xml.internal.serializer.ToXMLSAXHandler.closeStartTag(ToXMLSAXHandler.java:205)
	at com.sun.org.apache.xml.internal.serializer.ToSAXHandler.flushPending(ToSAXHandler.java:291)
	at com.sun.org.apache.xml.internal.serializer.ToXMLSAXHandler.endElement(ToXMLSAXHandler.java:244)
	at com.sun.org.apache.xml.internal.serializer.ToXMLSAXHandler.endElement(ToXMLSAXHandler.java:555)
	at com.sun.org.apache.xalan.internal.xsltc.trax.DOM2TO.parse(DOM2TO.java:220)
	at com.sun.org.apache.xalan.internal.xsltc.trax.DOM2TO.parse(DOM2TO.java:215)
	at com.sun.org.apache.xalan.internal.xsltc.trax.DOM2TO.parse(DOM2TO.java:121)
	at com.sun.org.apache.xalan.internal.xsltc.trax.DOM2TO.parse(DOM2TO.java:85)
	at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transformIdentity(TransformerImpl.java:596)
	at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:642)
	at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:281)
	at com.sun.org.apache.xerces.internal.jaxp.validation.ValidatorImpl.process(ValidatorImpl.java:220)
	at com.sun.org.apache.xerces.internal.jaxp.validation.ValidatorImpl.validate(ValidatorImpl.java:141)
	at javax.xml.validation.Validator.validate(Validator.java:82)
	at SchemaValidation.main(SchemaValidation.java:42)

setattr=true
java version "1.6.0"
Java(TM) SE Runtime Environment (build 1.6.0-b105)
Java HotSpot(TM) Client VM (build 1.6.0-b105, mixed mode, sharing)

setting attribute
Exception in thread "main" org.xml.sax.SAXParseException: cvc-complex-type.3.2.2: Attribute 'attr' is not allowed to appear in element 'inner'.
	at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:195)
	at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.error(ErrorHandlerWrapper.java:131)
	at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:384)
	at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:318)
	at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator$XSIErrorReporter.reportError(XMLSchemaValidator.java:410)
	at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.reportSchemaError(XMLSchemaValidator.java:3165)
	at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.processAttributes(XMLSchemaValidator.java:2630)
	at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.handleStartElement(XMLSchemaValidator.java:2037)
	at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.startElement(XMLSchemaValidator.java:685)
	at com.sun.org.apache.xerces.internal.jaxp.validation.DOMValidatorHelper.beginNode(DOMValidatorHelper.java:273)
	at com.sun.org.apache.xerces.internal.jaxp.validation.DOMValidatorHelper.validate(DOMValidatorHelper.java:240)
	at com.sun.org.apache.xerces.internal.jaxp.validation.DOMValidatorHelper.validate(DOMValidatorHelper.java:186)
	at com.sun.org.apache.xerces.internal.jaxp.validation.ValidatorImpl.validate(ValidatorImpl.java:100)
	at javax.xml.validation.Validator.validate(Validator.java:127)
	at SchemaValidation.main(SchemaValidation.java:42)

setattr=false
java version "1.6.0"
Java(TM) SE Runtime Environment (build 1.6.0-b105)
Java HotSpot(TM) Client VM (build 1.6.0-b105, mixed mode, sharing)

Exception in thread "main" org.xml.sax.SAXParseException: cvc-complex-type.4: Attribute 'attr' must appear on element 'inner'.
	at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:195)
	at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.error(ErrorHandlerWrapper.java:131)
	at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:384)
	at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:318)
	at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator$XSIErrorReporter.reportError(XMLSchemaValidator.java:410)
	at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.reportSchemaError(XMLSchemaValidator.java:3165)
	at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.addDefaultAttributes(XMLSchemaValidator.java:2859)
	at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.handleStartElement(XMLSchemaValidator.java:2041)
	at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.startElement(XMLSchemaValidator.java:685)
	at com.sun.org.apache.xerces.internal.jaxp.validation.DOMValidatorHelper.beginNode(DOMValidatorHelper.java:273)
	at com.sun.org.apache.xerces.internal.jaxp.validation.DOMValidatorHelper.validate(DOMValidatorHelper.java:240)
	at com.sun.org.apache.xerces.internal.jaxp.validation.DOMValidatorHelper.validate(DOMValidatorHelper.java:186)
	at com.sun.org.apache.xerces.internal.jaxp.validation.ValidatorImpl.validate(ValidatorImpl.java:100)
	at javax.xml.validation.Validator.validate(Validator.java:127)
	at SchemaValidation.main(SchemaValidation.java:42)
---%<---

As you can see, with any JDK version, if the attribute is missing, the schema validator correctly reports that it must be there. On JDK 5, adding the attribute satisfies the schema validator, as expected. But on JDK 6, adding the attribute makes the validator report that it cannot be there!

As mentioned previously, in my real program I had a problem with some other data (same schema) whereby JDK 6 would incorrectly report that a required attribute was not present on an element when in fact it was. If you need a test case for this too, I can try to come up with one.

In summary, it looks like the schema validator implementation in JDK 6 is quite confused about the presence vs. absence of attributes.

Comments
EVALUATION Appears fixed in JDK 6u6 (also JDK 7).
03-07-2008

WORK AROUND Based on evaluation, found what seems to work as a workaround. Before validating, process as follows: private static void fixupNoNamespaceAttrs(Element root) { NodeList nl = root.getElementsByTagName("*"); for (int i = 0; i < nl.getLength(); i++) { Element e = (Element) nl.item(i); Map<String,String> replace = new HashMap<String,String>(); NamedNodeMap attrs = e.getAttributes(); for (int j = 0; j < attrs.getLength(); j++) { Attr attr = (Attr) attrs.item(j); if (attr.getNamespaceURI() == null) { replace.put(attr.getName(), attr.getValue()); } } for (Map.Entry<String,String> entry : replace.entrySet()) { e.removeAttribute(entry.getKey()); e.setAttributeNS(null, entry.getKey(), entry.getValue()); } } }
16-03-2007

EVALUATION The problem with 'attr' attribute is essentially the same. To be namespace aware, you should call setAttributeNS(String, String, String) instead of setAttribute(String, String). That should fix the problem with JDK 6. Having said that, I have checked in a fix in JAXP 1.4 to remain backward compatible with JDK 5.0. With this fix, your code will work even if namespaces are not enabled (and even if DOM level 1 methods like setAttribute(String, String) are called). This fix is available from the JAXP builds at Java.net. See comments in blog entry on where to get the nighly build for JAXP.
08-03-2007

EVALUATION This is a known issue in JDK 6.0, but technically it isn't a bug. The code must turn on namespace awareness on the DocumentBuilderFactory. Please see this blog entry, http://weblogs.java.net/blog/spericas/archive/2007/03/xml_schema_vali.html for further details. As the blog says, we don't know how this worked before.
01-03-2007

WORK AROUND None known at this time.
01-03-2007