【问题标题】:XML validation against an XSD using javax.xml.validation.Validator使用 javax.xml.validation.Validator 针对 XSD 进行 XML 验证
【发布时间】:2013-10-30 05:32:34
【问题描述】:

xsd 包含如下声明:

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

xml 中有问题的行如下所示:

<HEADER IDENTIFIER="invalidId 01">

<HEADER IDENTIFIER="validId01">

xsd:ID 类型另见http://books.xmlschemata.org/relaxng/relax-CHP-19.html

定义、冒号、空格或以数字开头是不允许的。 如果生成的文件在 eclipse ide 中打开并针对 daclared xsd 进行验证,则会发现错误并正确发出信号。 但是,在 JUnit 测试期间,会加载相同的 xsd 并根据它验证生成的文件。此验证会找到任何格式错误的 xml,但不会找到无效的属性 IDENTIFIER。

验证码如下:

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;
}

有人知道告诉验证器考虑属性限制可能缺少什么吗?

我没有使用 DefaultHandler2,而是将自己的 ValidationErrorHandler 设置为:

public class ValidationErrorHandler extends DefaultHandler {

包括:

 @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;
}

警告和 FatalError 方法相同! 目前,我拥有我需要的一切!

【问题讨论】:

    标签: java xml validation xsd sax


    【解决方案1】:

    xsd:IDs 可能不包含空格是正确的。

    关于为什么您没有收到来自 Java 验证代码的错误,请注意 DefaultHandler2() 忽略所有解析事件。特别是关于error() 方法:

    默认实现什么都不做。应用程序编写者可以 在子类中覆盖此方法以对每个执行特定操作 错误,例如将消息插入日志文件或将其打印到 控制台。

    一般来说,事实上,org.xml.sax.ErrorHandler 的接口是这样记录的:

    警告:如果应用程序没有注册 ErrorHandler,XML 解析错误将不报告,除了 SAXParseExceptions 将 被抛出致命错误。为了检测有效性错误,一个 对 error() 调用执行某些操作的 ErrorHandler 必须是 已注册。

    SAX samples included with Xerces2-Jsource code 在这方面提供了很好的例子。特别是,Counter class 展示了如何扩展DefaultHandler

    【讨论】:

    • 很高兴知道。事实上,对于任何学科来说,我都是新手,我总是从默认设置开始。因此,我认为 DefaultHandler2() 可以完成这项工作。不是这样,我会实施必要的。
    • @juerg 如果您有任何跟进,请告诉我。如果我有帮助,如果您能accept 我的回答,我将不胜感激。谢谢。
    • 当然,您的提示正是我想要的。所以接下来我将扩展 DefaultHandler 以包含所需的测试。我还没有开始。看看 DefaultHandler,我必须说我不知道​​哪个方法最好重写。我将从 startElement 开始,其中提到了属性以查看我得到了什么。或者,我必须重写错误方法,或者两者兼而有之。文档真的很简洁。所以,如果你能告诉我,从哪里开始,或者存在相关有价值的信息,你的提示可以加快我的体验。
    • @juerg,我已经编辑了答案并添加了指向示例源的链接,其中显示了如何扩展 DefaultHandler 的示例。
    • 与此同时,我让自己了解了细节。我必须说这几乎是不费吹灰之力。事实上,DefaultHandler 的实现者可以轻松地完成我所做的事情,而不是什么都不做。其实最正常的异常处理,就是将异常信息转发给调用者!我为可能的问题添加了一个 sn-p。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-07-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多