如何在使用java.XML.validator针对XSD验证XML时获得更具体的错误

如何在使用java.XML.validator针对XSD验证XML时获得更具体的错误,java,xml,validation,xsd,Java,Xml,Validation,Xsd,在寻找针对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("instan

在寻找针对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."
是否有一种方法可以覆盖或插入验证器的另一部分,这样我就可以定义自己发送给ErrorHandler的错误消息,而不必重写所有代码


我应该使用另一个库吗?

你看了吗?我想你是在寻找类似的信息?正如@parcifel提到的,您应该在解析时进行验证(更有效、更好的错误信息)。您可以在解析时进行验证。这将使位置信息可用,并且ErrorHandler将报告它

在创建
DocumentBuilderFactory
之前,只需创建
模式
,并按如下方式应用它:

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

注意:
setValidating()
方法告诉DBF是否使用DTD验证。设置模式会告诉它使用模式验证。

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

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

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);
    }
}
这些信息也很有用


你说得对,它确实有一个getLineNumber()方法-我错过了这个。行号也是有意义的-如果我无法从数据本身获得稍微更具体的信息,那么我可以使用它。这是一个很好的答案,因为
getLineNumber()
getColumnNumber
调用
SAXParseException
将返回-1,给定问题中的场景。但是,我希望答案扩展为解析器需要错误处理程序的信息。我花了一段时间才弄明白怎么做才对。有没有办法得到出错的标签名