10

在搜索了针对 XSD 验证我的 XML 的最佳方法之后,我遇到了 java.xml.validator。

我首先使用 API 中的示例代码并添加我自己的 ErrorHandler

// parse an XML document into a DOM tree
DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document document = parser.parse(new File("instance.xml"));

// create a SchemaFactory capable of understanding WXS schemas
SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);

// load a WXS schema, represented by a Schema instance
Source schemaFile = new StreamSource(new File("mySchema.xsd"));
Schema schema = factory.newSchema(schemaFile);

// create a Validator instance, which can be used to validate an instance document
Validator validator = schema.newValidator();

// Add a custom ErrorHandler
validator.setErrorHandler(new XsdValidationErrorHandler());

// validate the DOM tree
try {
    validator.validate(new DOMSource(document));
} catch (SAXException e) {
    // instance document is invalid!
}

...

private class XsdValidationErrorHandler implements ErrorHandler {
    @Override
    public void warning(SAXParseException exception) throws SAXException {
        throw new SAXException(exception.getMessage());
    }

    @Override
    public void error(SAXParseException exception) throws SAXException {
        throw new SAXException(exception.getMessage());
    }

    @Override
    public void fatalError(SAXParseException exception) throws SAXException {
        throw new SAXException(exception.getMessage());
    }
}

这工作正常,但是,传递给我的 XsdValidationErrorHandler 的消息并没有给我任何指示文档中有问题的 XML 的确切位置:

"org.xml.sax.SAXParseException: cvc-complex-type.2.4.a: Invalid content was found starting with element 'X'. One of '{Y}' is expected."

有没有办法让我覆盖或插入 Validator 的另一部分,以便我可以定义自己的错误消息发送到 ErrorHandler 而无需重写所有代码?

我应该使用不同的库吗?

4

5 回答 5

9

尝试捕获 SaxParseException,它是 SaxException 的后代。如果你得到其中之一,它有方法 getLineNumber()、getColumnNumber() 等。

于 2012-09-04T17:21:23.963 回答
3

在解析时验证。这将使位置信息可用,并且 ErrorHandler 将报告它。

只需在创建Schema之前创建DocumentBuilderFactory,然后像这样应用它:

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
dbf.setValidating(false);
dbf.setSchema(schema);

注意:该setValidating()方法告诉 DBF 是否使用 DTD 验证。设置架构告诉它使用架构验证。

于 2012-09-04T17:15:59.890 回答
3

您可以执行exception.getLineNumber()exception.getColumnNumber()获取错误的坐标。是一个类似的问题。

于 2012-09-05T12:50:51.233 回答
1

你看过SAXParseException吗?我假设您正在寻找行号之类的信息?正如@parcifel 提到的,您应该在解析时进行验证(更有效和更好的错误信息)。您可以通过在 DocumentBuilderFactory 上指定架构来做到这一点。

于 2012-09-04T17:14:39.520 回答
0
public class KitXsdErrorHandler implements ErrorHandler {

    @Override
    public void warning(SAXParseException exception) throws SAXException {
        handleMessage("Warning", exception);
    }

    @Override
    public void error(SAXParseException exception) throws SAXException {
        handleMessage("Error", exception);
    }

    @Override
    public void fatalError(SAXParseException exception) throws SAXException {
        handleMessage("Fatal", exception);
    }

    private String handleMessage(String level, SAXParseException exception) throws SAXException {
        int lineNumber = exception.getLineNumber();
        int columnNumber = exception.getColumnNumber();
        String message = exception.getMessage();
        throw new SAXException("[" + level + "] Sətr nömrə: " + lineNumber + " Sütun nömrə: " + columnNumber + " message: " + message);
    }
}

这个信息也很有帮助

如何使用 SAX XML Schema Validator 的验证消息进行内部化?

http://vijiprakash.blogspot.com/2008/05/custom-error-message-in-xml-xsd.html

于 2016-12-13T21:20:41.730 回答