转:JAVA解析XML,DTD验证问题

JAVA解析XML,DTD验证问题

来自:http://blog.csdn.net/hailanzhijia/article/details/6004947

问题提出
解析ejb-jar.xml,出现在网络连不上的情况下,解析失败的情况。

问题分析:
我们使用的是DOM进行XML的解析的:
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            //位置点
            Document doc = builder.parse(file);
由于ejb-jar.xml中,有
<!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN" "http://java.sun.com/dtd/ejb-jar_2_0.dtd">
在解析的时候,会从网络http://java.sun.com/dtd/ejb-jar_2_0.dtd中抓紧DTD文件,进行验证,如果网络不通,那么就会出现解析失败。

首先,DocumentBuilderFactory.newInstance()创建DocumentBuilderFactory实现类的对象,它会通过一下方式来查找实现类:
1.在系统环境变量中(System.getProperties())中查找 key=javax.xml.parsers.DocumentBuilderFactory
2.如果1没有找到,则找java.home/lib/jaxp.properties 文件,如果文件存在,在文件中查找key=javax.xml.parsers.DocumentBuilderFactory
3.如果2没有找到,则在classpath中的所有的jar包中查找META-INF/services /javax.xml.parsers.DocumentBuilderFactory 文件
    全都没找到,则返回null
如果上面都没有找到,那么就使用JDK自带的实现类:
com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl
在创建DocumentBuilder实例的时候,是根据DocumentBuilderFactoryImpl的不同有不同的实现。

为了在网络不可用的情况下,正常解析XML文件,我们可以在使用builder之前,设置EntityResolver:
            builder.setEntityResolver(
                new EntityResolver(){
                   public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException
                   {
                       return new InputSource(new StringBufferInputStream(""));  
//                       return null;//这个的效果仍然是从网络来抓取DTD来验证
                       }
                }
            );
上面的设置就不会对XML文件进行验证。
如果一定要验证的话,我们也可以设置使用本地的DTD文件来做验证:
            builder.setEntityResolver(
                new EntityResolver(){
                   public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException
                   {
                      if(publicId.equals("-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN"))
                       {
                          String dtd_uri = "C:/TEMP/ejb-jar_2_0.dtd";
                           return new InputSource(dtd_uri);
                       }
                }
            );
注意:直接return null,仍然会从网络来抓取DTD来验证。

来自:http://blog.csdn.net/hailanzhijia/article/details/6004947


评论

此博客中的热门博文

XML, XSL, HTML

Input in element.eleme.io

Data URI是由RFC 2397 ACE