spring源码附录(1)java实现对XML格式的验证

来源:互联网 发布:淘宝品牌调性分怎么查 编辑:程序博客网 时间:2024/05/22 16:05

最近在看spring源码,涉及到xml文档的解析、xml文档的格式验证,发现自己对xml解析的基础较为薄弱,本篇博客复习下DOM方式解析xml(即spring解析xml的方式)。

DOM解析XML是将整个XML作为一个对象,占用内存较多。另外一个java官方的XML解析方式SAX是边扫描边解析,自顶向下依次解析,占用内存较少。

一、java实现对XML格式的验证

可以使用两种验证模式(DTD、XSD)保证XML文件格式正确,DTD和XSD均是XML约束描述语言,是XML文件的验证机制。本文以DTD为例。
DTD文件格式请参考:http://www.cnblogs.com/zhengcheng/p/4278899.html
看下面student.xml:

<?xml version="1.0"?><!DOCTYPE 学生名册 SYSTEM "student.dtd"><学生名册>    <学生 学号="t1">        <姓名>张三</姓名>        <性别>男</性别>        <年龄>20</年龄>    </学生>    <学生 学号="t2">        <姓名>李四</姓名>        <性别>女</性别>        <年龄>19</年龄>    </学生></学生名册>

我们看到上面这个XML指定的DTD验证文件为student.dtd:

<?xml version="1.0" encoding="UTF-8"?><!ELEMENT 学生名册  (学生*)><!ELEMENT 学生 (姓名,性别,年龄)><!ELEMENT 姓名 (#PCDATA)><!ELEMENT 性别 (#PCDATA)><!ELEMENT 年龄 (#PCDATA)><!ATTLIST 学生 学号 ID #REQUIRED>

那么java DOM解析XML如何实现验证?

下面使用DOM解析student.xml:

public class test {    public static void main(String[] args) {        DocumentBuilderFactory buildFactory = DocumentBuilderFactory.newInstance();        //开启XML格式验证        buildFactory.setValidating(true);        try {            DocumentBuilder build = buildFactory.newDocumentBuilder();            //指定验证出错处理类MyErrorHandle            build.setErrorHandler(new MyErrorHandler());            //自定义解析方式,如果不设置,则使用默认实现            build.setEntityResolver(new MyResolveEntity());            Document doc = build.parse("student.xml");            getStudents(doc);        } catch (ParserConfigurationException e) {            e.printStackTrace();        } catch (SAXException e) {            e.printStackTrace();        } catch (IOException e) {            e.printStackTrace();        }    }    private static void getStudents(Document doc) {        Element root = doc.getDocumentElement();        NodeList nodeList = root.getElementsByTagName("学生");        for(int i=0;i<nodeList.getLength();i++){            Node node = nodeList.item(i);            NamedNodeMap map = node.getAttributes();            System.out.println(map.item(0).getTextContent());            //子节点            NodeList childList = node.getChildNodes();            for(int j=0;j<childList.getLength();j++){                Node childNode = childList.item(j);                System.out.println(childNode.getTextContent());            }        }    }}public class MyErrorHandler implements ErrorHandler{    @Override    public void warning(SAXParseException exception) throws SAXException {        // TODO Auto-generated method stub    }    @Override    public void error(SAXParseException exception) throws SAXException {        System.out.println("发生了错误!"+exception.getMessage());    }    @Override    public void fatalError(SAXParseException exception) throws SAXException {        // TODO Auto-generated method stub    }}public class MyResolveEntity implements EntityResolver{    @Override    public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {        return new InputSource("student.dtd");        //return null;    }}

如果不设置setEntityResolver,则会使用XML中指定位置的DTD文件进行验证,

<!DOCTYPE 学生名册 SYSTEM "student.dtd">

student.dtd即指定了验证文件的位置。

二、spring源码中对XML文件的验证的处理

在spring中,为网络地址:

<!DOCTYPE beans PUBLIC  "-//SPRING//DTD BEAN//EN"  "http://www.springframework.org/dtd/spring-beans.dtd">

publicId:-//SPRING//DTD BEAN//EN
systemId:http://www.springframework.org/dtd/spring-beans.dtd

如果设置了setEntityResolver,则会按照EntityResolver进行XML验证:先去项目中寻找spring-beans.xsd,如果未获取到则按照网络地址寻找。

以spring中 Spring-beans.dtd为例:
public class BeansDtdResolver implements EntityResolver {

    private static final String DTD_EXTENSION = ".dtd";    private static final String DTD_NAME = "spring-beans";    private static final Log logger = LogFactory.getLog(BeansDtdResolver.class);    @Override    public InputSource resolveEntity(String publicId, String systemId) throws IOException {        if (logger.isTraceEnabled()) {            logger.trace("Trying to resolve XML entity with public ID [" + publicId +                    "] and system ID [" + systemId + "]");        }        if (systemId != null && systemId.endsWith(DTD_EXTENSION)) {            int lastPathSeparator = systemId.lastIndexOf("/");            int dtdNameStart = systemId.indexOf(DTD_NAME, lastPathSeparator);            if (dtdNameStart != -1) {                String dtdFile = DTD_NAME + DTD_EXTENSION;                if (logger.isTraceEnabled()) {                    logger.trace("Trying to locate [" + dtdFile + "] in Spring jar on classpath");                }                try {                    Resource resource = new ClassPathResource(dtdFile, getClass());                    InputSource source = new InputSource(resource.getInputStream());                    source.setPublicId(publicId);                    source.setSystemId(systemId);                    if (logger.isDebugEnabled()) {                        logger.debug("Found beans DTD [" + systemId + "] in classpath: " + dtdFile);                    }                    return source;                }                catch (IOException ex) {                    if (logger.isDebugEnabled()) {                        logger.debug("Could not resolve beans DTD [" + systemId + "]: not found in classpath", ex);                    }                }            }        }        // Use the default behavior -> download from website or wherever.        return null;    }}
阅读全文
0 0
原创粉丝点击