JAVA解析XML,DTD验证问题

问题提出

解析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来验证。

 

你可能感兴趣的:(JAVA解析XML,DTD验证问题)