不依赖第三方工具
核心代码
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
public class XmlValidateUtils {
private static final DocumentBuilderFactory FACTORY = DocumentBuilderFactory.newInstance();
/**
* 验证xml文档是否存在语法错误
* @param xmlInputStream
* @return true 通过校验, false xml有语法错误或未通过校验
* @throws ParserConfigurationException 严重的配置错误
*/
public static boolean isValid(InputStream xmlInputStream) throws ParserConfigurationException {
return isValid(xmlInputStream, (ErrorHandler) null);
}
/**
* 验证xml文档是否存在语法错误
* @param xml
* @return true 通过校验, false xml有语法错误或未通过校验
* @throws ParserConfigurationException 严重的配置错误
* @throws IOException 字符串转输入流错误
*/
public static boolean isValid(String xml) throws ParserConfigurationException, IOException {
return isValid(xml, (ErrorHandler) null);
}
/**
* 验证xml文档是否存在语法错误
* @param xmlInputStream
* @param errorHandler xml文档warning、error、fatalError的回调接口
* @return true 由errorHandler的方法实现决定,false xml校验未通过
* @throws ParserConfigurationException 严重的配置错误
*/
public static boolean isValid(InputStream xmlInputStream, ErrorHandler errorHandler) throws ParserConfigurationException {
DocumentBuilder builder = FACTORY.newDocumentBuilder();
if (errorHandler != null) {
builder.setErrorHandler(errorHandler);
}
try {
builder.parse(xmlInputStream);
return true;
} catch (Exception e) {
return false;
}
}
/**
* 验证xml文档是否存在语法错误
* @param xml
* @param errorHandler xml文档warning、error、fatalError的回调接口
* @return true 由errorHandler的方法实现决定,false xml校验未通过
* @throws ParserConfigurationException 严重的配置错误
* @throws IOException 字符串转输入流错误
*/
public static boolean isValid(String xml, ErrorHandler errorHandler) throws ParserConfigurationException, IOException {
try (
ByteArrayInputStream xmlInputStream = new ByteArrayInputStream(xml.getBytes());
) {
return isValid(xmlInputStream, errorHandler);
}
}
}
说明
- 如果传入自定义的 errorHandler 参数,则使用自定义的 ErrorHandler。
如:自定义的 XmlErrorHandler 类,当xml严重错误时执行 fatalError 方法,当xml内容不符合xsd规则时执行 error 方法,此时未抛出异常,而是将异常对象 SAXParseException 加入到对应的 List,由上面的 private static boolean isValid(InputStream xmlInputStream) throws ParserConfigurationException 方法捕获,返回false表示xml存在语法错误;当不存在语法错误时,不执行 error 方法和 fatalError 方法,不抛出 SAXParseException 异常,返回true。
package com.sun.org.apache.xerces.internal.jaxp.validation;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
/**
* {@link ErrorHandler} that throws all errors and fatal errors.
*
* @author Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
*/
final class DraconianErrorHandler implements ErrorHandler {
/**
* Singleton instance.
*/
private static final DraconianErrorHandler ERROR_HANDLER_INSTANCE
= new DraconianErrorHandler();
private DraconianErrorHandler() {}
/** Returns the one and only instance of this error handler. */
public static DraconianErrorHandler getInstance() {
return ERROR_HANDLER_INSTANCE;
}
/** Warning: Ignore. */
public void warning(SAXParseException e) throws SAXException {
// noop
}
/** Error: Throws back SAXParseException. */
public void error(SAXParseException e) throws SAXException {
throw e;
}
/** Fatal Error: Throws back SAXParseException. */
public void fatalError(SAXParseException e) throws SAXException {
throw e;
}
}
- 如果传入自定义的 errorHandler 参数,则使用自定义的 ErrorHandler。
如:自定义的 XmlErrorHandler 类,当xml严重错误时执行 fatalError 方法,当xml内容不符合xsd规则时执行 error 方法,此时未抛出异常,而是将异常对象 SAXParseException 加入到对应的 List,上面的 private static boolean isValid(InputStream xmlInputStream) throws ParserConfigurationException 方法不能捕获 SAXParseException 异常,返回true;当捕获到 SAXParseException 异常时,表示xml存在语法错误,返回false。
import java.util.ArrayList;
import java.util.List;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXParseException;
public class XmlErrorHandler implements ErrorHandler {
private List<SAXParseException> warningExceptions;
private List<SAXParseException> errorExceptions;
private List<SAXParseException> fatalErrorExceptions;
public XmlErrorHandler() {
this.warningExceptions = new ArrayList<>();
this.errorExceptions = new ArrayList<>();
this.fatalErrorExceptions = new ArrayList<>();
}
public List<SAXParseException> getWarningExceptions() {
return warningExceptions;
}
public List<SAXParseException> getErrorExceptions() {
return errorExceptions;
}
public List<SAXParseException> getFatalErrorExceptions() {
return fatalErrorExceptions;
}
@Override
public void warning(SAXParseException exception) {
warningExceptions.add(exception);
}
@Override
public void error(SAXParseException exception) {
errorExceptions.add(exception);
}
@Override
public void fatalError(SAXParseException exception) {
fatalErrorExceptions.add(exception);
}
}
使用JDK默认的 errorHandler
public static void main(String[] args) throws SAXException, IOException, ParserConfigurationException {
String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\r\n"
+ "<individual>\r\n"
+ " <name>student</name>\r\n"
+ " <address>\r\n"
+ " <zip>00001</zip>\r\n"
+ " <city>New <York</city>\r\n"
+ " </address>\r\n"
+ "</individual>";
boolean valid1 = isValid(xml);
System.out.println(valid1);
}
使用自定义的 errorHandler
/**
* 验证xml文档是否存在语法错误
* @param xml
* @throws RuntimeException 校验程序出错
* @throws IllegalArgumentException 校验未通过
*/
public static void validate(String xml) {
XmlErrorHandler errorHandler = new XmlErrorHandler();
try {
boolean valid = isValid(xml, errorHandler);
if (!valid) {
if (!errorHandler.getFatalErrorExceptions().isEmpty()) {
throw new IllegalArgumentException("xml:" + xml + "语法错误", errorHandler.getFatalErrorExceptions().get(0));
}
throw new RuntimeException("校验程序出错");
}
} catch (IllegalArgumentException e) {
throw e;
} catch (Exception e) {
throw new RuntimeException("校验程序出错", e);
}
if (!errorHandler.getErrorExceptions().isEmpty()) {
throw new IllegalArgumentException("xml:" + xml + "校验未通过", errorHandler.getErrorExceptions().get(0));
}
}
public static void main(String[] args) throws SAXException, IOException, ParserConfigurationException {
String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\r\n"
+ "<individual>\r\n"
+ " <name>student</name>\r\n"
+ " <address>\r\n"
+ " <zip>00001</zip>\r\n"
+ " <city>New <York</city>\r\n"
+ " </address>\r\n"
+ "</individual>";
validate(xml);
}