Java使用JDK1.8 javax.xml.validation API校验XML时如何捕获全部XSD校验错误
问题解决:XML与XSD校验遇到第一个错误就终止,无法收集所有违规错误
核心原因
JDK1.8内置的Xerces XML解析器默认开启「遇到致命校验错误立即终止」的特性,即便自定义ErrorHandler没有抛出任何异常,内置的快速失败逻辑仍会中断校验流程,无法收集后续所有违规错误。
修复方案
步骤1:给Validator添加继续校验的特性
在初始化Validator后,添加如下配置,开启致命错误后继续校验的能力:
// 开启校验遇到错误后继续执行的特性 validator.setFeature("http://apache.org/xml/features/continue-after-fatal-error", true);
步骤2:确认ErrorHandler回调逻辑符合要求
你当前的XMLSchemaValidationErrorHandler已经符合要求,三个回调方法(warning/error/fatalError)仅收集异常不抛出SAXException,可保证校验流程不被主动中断。另外你代码中构造方法传入的Validator没有被实际使用,可以按需删除冗余参数。
步骤3:校验完成后统一获取所有错误
校验执行完成后,直接调用errorHandler.getExceptions()即可拿到所有校验违规的异常列表,无需依赖validate方法的抛出异常判断结果。
注意:如果XML本身存在格式致命错误(比如标签未闭合、语法完全不符合XML规范),解析器仍可能提前终止,该场景下无法收集到后续所有错误,仅针对XSD规则校验类的错误可实现全量收集。
完整修改后的代码示例
主校验逻辑
import org.xml.sax.SAXException; import javax.xml.XMLConstants; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; import javax.xml.validation.Schema; import javax.xml.validation.SchemaFactory; import javax.xml.validation.Validator; import java.io.StringReader; import java.io.StringWriter; import java.util.Collections; import java.util.List; import org.xml.sax.SAXParseException; // 业务校验逻辑 String xsd = ""; // 替换为你的XSD内容 String xml = ""; // 替换为你的XML内容 List<SAXParseException> allErrors = Collections.emptyList(); try { SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); Schema schema = schemaFactory.newSchema(new StreamSource(new StringReader(xsd))); Validator validator = schema.newValidator(); // 关键配置:开启错误后继续校验 validator.setFeature("http://apache.org/xml/features/continue-after-fatal-error", true); XMLSchemaValidationErrorHandler errorHandler = new XMLSchemaValidationErrorHandler(); validator.setErrorHandler(errorHandler); StringWriter writer = new StringWriter(); StreamResult result = new StreamResult(writer); validator.validate(new StreamSource(new StringReader(xml)), result); // 获取所有校验错误 allErrors = errorHandler.getExceptions(); } catch (SAXException e) { // 捕获解析层面的异常,不影响已收集的错误 } catch (IllegalArgumentException i) { // 参数异常处理 } catch (IOException err) { // IO异常处理 } catch (Exception e) { // 其他异常处理 }
简化后的错误处理器
package com.xml.validation.utils; import java.util.LinkedList; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.xml.sax.ErrorHandler; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; public class XMLSchemaValidationErrorHandler implements ErrorHandler { private static final Logger LOGGER = LoggerFactory.getLogger(XMLSchemaValidationErrorHandler.class); private final List<SAXParseException> exceptions = new LinkedList<>(); @Override public void warning(SAXParseException exception) throws SAXException { LOGGER.error("warning SAXParseException :::{}", exception.getMessage()); exceptions.add(exception); } @Override public void error(SAXParseException exception) throws SAXException { LOGGER.error("error SAXParseException Message ::: {}", exception.getMessage()); exceptions.add(exception); } @Override public void fatalError(SAXParseException exception) throws SAXException { LOGGER.error("fatalError SAXParseException ::: {}", exception.getMessage()); exceptions.add(exception); } public List<SAXParseException> getExceptions() { return exceptions; } }
内容的提问来源于stack exchange,提问作者Rajashekhar
相关产品推荐
相关产品推荐

