在XML Validator上设置ErrorHandler会导致验证不正确

Tyl*_*eat 2 java xml xsd sax xerces

在使用Java的XML Validator(我相信使用Apache Xerces实现)时,我遇到了一些非常奇怪的行为.

我正在尝试针对XSD验证一些XML文档,并且我想记录导致文档无效的任何内容.我认为实施我自己ErrorHandler会允许我这样做.我很快发现这导致XML文档被错误地验证(即无效的XML被识别为对我的XSD有效).

我做了一些测试,发现简单地将Validator's 设置ErrorHandler为任何东西都会导致这种行为,如下所示.

validator.validate(invalidXmlSource); // XML correctly identified as INVALID

validator.setErrorHandler(new DefaultHandler());
validator.validate(invalidXmlSource); // XML incorrectly identified as VALID
Run Code Online (Sandbox Code Playgroud)

我会假设当没有指定一个时Validator使用DefaultHandler,所以我不明白为什么行为正在改变.

这里发生了什么?

编辑

public void validate(File dir, String xsdPath) {
    File schemaFile = new File(xsdPath);
    SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
    Schema schema = schemaFactory.newSchema(schemaFile);
    Validator validator = schema.newValidator();
    //validator.setErrorHandler(new DefaultHandler()); <-- this line causes incorrect validation
    for (File xmlFile: dir.listFiles()) {
        try {
            validator.validate(new StreamSource(xmlFile));
            System.out.println("File '" + xmlFile.getName() + "' is valid.");
        } catch (SAXException e) {
            System.out.println("File '" + xmlFile.getName() + "' is NOT valid.");
            System.out.println("Reason: " + e.getLocalizedMessage());
        } catch (IOException e) {
            e.printStackTrace();
        }       
    }
}
Run Code Online (Sandbox Code Playgroud)

ksc*_*eid 5

DefaultHandler对于将什么也不做errorwarning.但是,它会抛出异常fatalError.该文档的之间的ValidatorDefaultHandler,你会看到,是好还是坏,你得到你问什么了.:)

编辑:可能在Validator文档中要注意的主要事情是默认(null)错误处理程序将抛出异​​常error...

Edit2:这是一个可能的错误处理程序的概述,可以执行您想要的操作:

import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXParseException;

public class LoggingErrorHandler implements ErrorHandler {

    private boolean isValid = true;

    public boolean isValid() {
        return this.isValid;
    }

    @Override
    public void warning(SAXParseException exc) {
        // log info
        // valid or not?
    }

    @Override
    public void error(SAXParseException exc) {
        // log info
        this.isValid = false;
    }

    @Override
    public void fatalError(SAXParseException exc) throws SAXParseException {
        // log info
        this.isValid = false;
        throw exc;
    }
}
Run Code Online (Sandbox Code Playgroud)

它可以像这样使用:

LoggingErrorHandler errorHandler = new LoggingErrorHandler();
validator.setErrorHandler(errorHandler);
validator.validate(invalidXmlSource);
if (!errorHandler.isValid()) {
    //...
}
Run Code Online (Sandbox Code Playgroud)