Search code examples
javaxmlvalidationxsdsax

XML validation against an XSD using javax.xml.validation.Validator


The xsd contains a declaration like:

<xsd:attribute name="IDENTIFIER" use="required" type="xsd:ID" />

The line in question within the xml looks like:

<HEADER IDENTIFIER="invalidId 01">

or

<HEADER IDENTIFIER="validId01">

The type xsd:ID see also http://books.xmlschemata.org/relaxng/relax-CHP-19.html

defines, colon, space or start with a number is not allowed. If the generated file is opened within the eclipse ide and validated against the daclared xsd the error is found and signaled correctly. However, during JUnit test, the same xsd is loaded and the generated file is validated against it. This validation finds any kind of malformed xml, but does not find the invalid attribute IDENTIFIER.

The validation code looks like:

static boolean validate(Source source) {
    boolean success = false;
    try {
        Validator validator = mySchema.newValidator();
        success = validate(validator, source);
    } catch (SAXException e) {
        logger.info(MSG_BASE + "SAXException: " + e.getMessage());
    } catch (IOException e) {
        logger.info(MSG_BASE + "IOException: " + e.getMessage());
    }
    return success;
}


private static boolean validate(Validator validator, Source source) 
                                                    throws SAXException, IOException {

    ErrorHandler erH = new DefaultHandler2();
    validator.setErrorHandler(erH);
    validator.validate(source);
    return true;
}

Does anybody know what is possibly missing to tell the validator to consider the restrictions on attributes?

Instead of using the DefaultHandler2, I setup my own ValidationErrorHandler as:

public class ValidationErrorHandler extends DefaultHandler {

including:

 @Override
public void error (SAXParseException e) throws SAXException {
throw new SAXParseException(e.getMessage(), buildLocator(e), e);

}

private Locator buildLocator(SAXParseException e) {
    Locator2Impl loc = new Locator2Impl();
    loc.setLineNumber(e.getLineNumber());
    loc.setColumnNumber(e.getColumnNumber());
    loc.setSystemId(e.getSystemId());
    loc.setPublicId(e.getPublicId());
    return loc;
}

The same for the warning and the FatalError method! For the moment I have all what I need!


Solution

  • You are correct that xsd:IDs may not contain spaces.

    As to why you're not receiving an error from your Java validation code, note that DefaultHandler2() ignores all parsing events. In particular, regarding the error() method:

    The default implementation does nothing. Application writers may override this method in a subclass to take specific actions for each error, such as inserting the message in a log file or printing it to the console.

    In general, in fact, the interface for org.xml.sax.ErrorHandler is thus documented:

    WARNING: If an application does not register an ErrorHandler, XML parsing errors will go unreported, except that SAXParseExceptions will be thrown for fatal errors. In order to detect validity errors, an ErrorHandler that does something with error() calls must be registered.

    The source code for the SAX samples included with Xerces2-J provide good examples in this area. In particular, the Counter class shows how to extend DefaultHandler.