【问题标题】:Setting ErrorHandler on XML Validator causes incorrect validation在 XML Validator 上设置 ErrorHandler 会导致验证不正确
【发布时间】:2012-09-01 19:15:31
【问题描述】:

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

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

我做了一些测试,发现简单地将ValidatorErrorHandler 设置为任何值都会导致这种行为,如下所示。

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

validator.setErrorHandler(new DefaultHandler());
validator.validate(invalidXmlSource); // XML incorrectly identified as VALID

我认为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();
        }       
    }
}

【问题讨论】:

  • 验证器当然不正确。试试你自己的验证器。
  • 我认为问题出在您的自定义 ErrorHandler 上;我也确信您对使用 DefaultHandler 的假设有一个扭曲(要么不正确,要么配置不正确)。如果您可以显示处理错误的代码 sn-p(您要重新抛出吗?)它会更容易提供帮助。
  • 此时我什至没有使用我自己的ErrorHandler 实现。我只是将验证器的处理程序设置为DefaultHandler,如上所述并观察此行为。我已将验证码添加到问题中。

标签: java xml xsd sax xerces


【解决方案1】:

DefaultHandler 不会对 errorwarning 执行任何操作。但是,它会为fatalError 抛出异常。在ValidatorDefaultHandler 的文档之间,你会看到,无论好坏,你得到的正是你所要求的。 :)

编辑:Validator 文档中要注意的主要事项可能是默认(空)错误处理程序将为 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;
    }
}

它可以像这样使用:

LoggingErrorHandler errorHandler = new LoggingErrorHandler();
validator.setErrorHandler(errorHandler);
validator.validate(invalidXmlSource);
if (!errorHandler.isValid()) {
    //...
}

【讨论】:

  • 很有趣,所以基本上Validator 依赖于ErrorHandler 抛出的SAXException 来确定文档是否无效。由于DefaultHandler 不会抛出任何异常,因此Validator 将不会抛出任何SAXException,如果它使用一个,则不管传递给它的文档如何。
  • 如果您想处理验证错误,您可能需要将它们收集到一个列表中。
猜你喜欢
  • 1970-01-01
  • 2013-08-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-15
  • 1970-01-01
  • 2014-01-26
  • 2011-07-13
相关资源
最近更新 更多