前段时间因项目需要和外部进行数据交换,采用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("@属性名")来取得。