Bug #4239
closedWhen using a JAXP SchemaFactory, an error in the schema goes unreported
100%
Description
Junit test case testValidator/testByteCodeJaxp
If there is an error in the schema (such as Cannot reference schema components in namespace http://myexample/family\ as it has not been imported
) this goes unreported. All we get is an exception at the end of processing saying one error was reported.
The error finds its way to the fatalError() method of the (so-called) DRACONIAN_ERROR_HANDLER
in SchemaFactoryImpl
-- which for some reason ignores it.
Updated by Michael Kay almost 5 years ago
The spec for SchemaFactory.setErrorHandler()
says:
When the ErrorHandler
is null, the implementation will behave as if the following ErrorHandler
is set:
class DraconianErrorHandler implements ErrorHandler {
public void fatalError( SAXParseException e ) throws SAXException {
throw e;
}
public void error( SAXParseException e ) throws SAXException {
throw e;
}
public void warning( SAXParseException e ) throws SAXException {
// noop
}
}
We seem to have mis-implemented this.
Updated by Michael Kay almost 5 years ago
Unfortunately, fixing fatalError() to throw the exception doesn't solve the problem, because DelegatingErrorListener
promptly ignores it.
It's not actually clear why we're calling fatalError()
here rather than error()
in the first place. But ignoring the exception thrown by the fatalError() callback seems wrong,
Updated by Michael Kay almost 5 years ago
Although the JAXP SchemaFactory
uses an ErrorHandler
for reporting schema errors, the SchemaFactory
spec says nothing about whether they should be reported using the error()
or fatalError()
callback; meanwhile the spec for ErrorHandler itself is wrtten as if the class is only used for XML parsing, and it has nothing to say about its use during schema processing.
Updated by Michael Kay almost 5 years ago
As a rare departure from my usual principles, I decided that the spec here was so outrageously defective that the only sensible thing is to find out what Xerces does and do the same. Xerces reports static errors in the schema to the ErrorListener's error() method, rather than to fatalError(), and I think it makes sense to do the same.
This still leaves open the question of how we handle the "draconian" case where the error reporter throws an error.
Updated by Michael Kay almost 5 years ago
Looking now at a schema that contains a couple of "unresolved reference" errors. Saxon reports these to ErrorHandler.warning(), on the basis of the rule in XSD 1.0 (clarified in 1.1) that an unresolved reference is not in itself a hard error. But Xerces reports these to ErrorHandler.error().
Contrariwise, at the end of schema processing, Saxon exits from the newSchema() call with a SAXException, whereas Xerces does a normal exit.
JAXP says "If the parsed set of schemas includes error(s) as specified in the section 5.1 of the XML Schema spec, then the error must be reported to the ErrorHandler."
JAXP also says " after an error is reported to a handler, the callee is allowed to abort the further processing by throwing it." So it seems that throwing a final exception is optional if there have been errors.
But a dangling component reference, according to ยง5.3, is NOT such an error, and Xerces appears to be out-of-line in reporting it as such. So once again, blindly following Xerces doesn't seem the right approach. Equally, if we're reporting it as a warning, then it's not clear why we're throwing an exception at the end.
The problem seems to be that Saxon is reporting a warning for ALL dangling-component errors, but some of these are in fact fatal. For example, we can't cope with declaring a type whose base type is unknown. We're slowly digging ourselves deeper into this hole...
Updated by Michael Kay almost 5 years ago
I'm making three changes:
(a) SchemaFactoryImpl.DRACONIAN_ERROR_HANDLER is aligned with the JAXP spec of the error handler used when no other is provided; specifically, the fatalError() method always throws an exception.
(b) The DelegatingErrorListener is changed so that if the underlying ErrorListener throws an exception P from its error() or fatalError() methods, an unchecked exception (wrapping exception P) is thrown; in the case of EnterpriseConfiguration.addSchemaSource() this unchecked exception is caught and turned into an checked exception from the addSchemaSource() method.
(c) SchemaElement.error() notifies the error to the ErrorListener's error() method rather than fatalError().
Updated by Michael Kay almost 5 years ago
- Category set to Diagnostics
- Status changed from New to Resolved
- Priority changed from Low to Normal
- Fix Committed on Branch 9.9, trunk added
Updated by O'Neil Delpratt almost 5 years ago
- Status changed from Resolved to Closed
- % Done changed from 0 to 100
- Fixed in Maintenance Release 9.9.1.4 added
Bug fix applied in the Saxon 9.9.1.4 maintenance release
Please register to edit this issue