Dom4J通过schema校验XML
????? 前段时间因项目需要和外部进行数据交换,采用XML为数据交换载体。这样就需要在数据交换前调用schema进行数据合法性校验,先通过XMLSpy工具制定好XSD验证文件(XMLSpy确实很方便),然后通过dom4j进行校验。废话不多说,关键代码贴下
???? 校验器:
import java.io.IOException;import org.dom4j.io.SAXReader;import org.springframework.core.io.ClassPathResource;import org.springframework.core.io.Resource;import org.xml.sax.EntityResolver;import org.xml.sax.InputSource;import org.xml.sax.SAXException;public class Validateor {public static SAXReader reader;private static EntityResolver aresolve;//校验器private static Validateor validateor=Validateor.getInstance();static{if(aresolve==null){aresolve=new EntityResolver(){public InputSource resolveEntity(String arg0, String arg1)throws SAXException, IOException {Resource resource =new ClassPathResource("com/***/***/***/***/a.xsd");return new InputSource(resource.getInputStream());}};}if(reader==null){reader=new SAXReader(true);}try {//符合的标准reader.setFeature("http://apache.org/xml/features/validation/schema", true); reader.setFeature("http://apache.org/xml/features/validation/schema-full-checking",true); reader.setProperty("http://java.sun.com/xml/jaxp/properties/schemaLanguage","http://www.w3.org/2001/XMLSchema"); } catch (SAXException e1) {System.err.println("设置校验参数错误");;} }private Validateor(){}public static SAXReader valid(String type){//根据不同的类型读取相应的校验文件,此处删除了一些业务代码if("01".equals(type)) reader.setEntityResolver(aresolve);return reader;}synchronized public static Validateor getInstance(){if(validateor==null){validateor=new Validateor();}return validByXsd;}}
?
? 校验方法
?
??
public Object validXmlData(String filePath, String type) {InputStreamReader streamReader=null;try {FileInputStream in = new FileInputStream(new File(filePath));//编码格式统一处理,支持非utf-8格式的声明文件streamReader= new InputStreamReader(in,"UTF-8");} catch (Exception e) {return "读取文件出现异常:"+e.getLocalizedMessage();}try {Document dateXml=Validateor.valid(type).read(streamReader);dateXml.setXMLEncoding("UTF-8");return dateXml;} catch (DocumentException e) {return "文件校验失败:"+e.getLocalizedMessage();}}
?
? Schema
?用XMLSpy生成,只把需要注意的命名空间贴上
?
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://www.xxx.com" targetNamespace="http://www.xxx.com" elementFormDefault="qualified">
?验证的XML
??
<account-data xmlns="http://www.xxx.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.xxx.com a.xsd">
?
注意在XML的声明处: xsi:schemaLocation="http://www.xxx.com a.xsd"> 后面的a.xsd就是前面的schema名字,与前面的中间http://www.xxx.com 之间有空格。
?
?PS:加上命名空间的XML不能直接用dom4j的selectNodes之类的API得到节点,需要对XPATH进行设置,用dom4j的elements方法比较简单些,具体API可以翻阅dom4j的文档(如无特别要求还是不加命名空间的比较简便,校验方法都是一样的,但取值比较方便)。得到节点的属性值可以用:node.valueOf("@属性名")来取得。
?