jdom dom4j解析xml不对dtd doctype进行验证(转)

 

一、写在所有之前:
因为dom4j和jdom在这个问题上处理的方法是一模一样的,只是一个是SAXBuilder 一个SAXReader,这里以jdom距离,至于dom4j只需要同理替换一下就可以了。
二、问题发生的情况
当你用jdom读取一个有dtd验证的xml文件,同时你的网络是不通的情况下。会出现以下错误:
1,代码如下

package dom;

import java.io.File;

import org.jdom.Document;
import org.jdom.input.SAXBuilder;

public class TestJdom {
    public static void main(String[] args) {
        File file = new File("./src/dom/aiwf_aiService.xml");
        if (file.exists()) {
            SAXBuilder builder = new SAXBuilder();
            try {
                Document doc = builder.build(file);
                System.out.println(doc);
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            System.out.println("can not find xml file:"
                    + file.getAbsolutePath());
        }
    }
}

2,xml文件

<?xml version="1.0" encoding="GBK"?>
<!DOCTYPE workflow PUBLIC "-//OpenSymphony Group//DTD OSWorkflow 2.8//EN" "http://www.opensymphony.com/osworkflow/workflow_2_8.dtd">
<workflow>
                ...............
</workflow>

3,错误如下

java.net.SocketException: Permission denied: connect
    at java.net.PlainSocketImpl.socketConnect(Native Method)
    at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:333)
    at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:195)
    at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:182)
    at java.net.Socket.connect(Socket.java:507)
    at java.net.Socket.connect(Socket.java:457)
    at sun.net.NetworkClient.doConnect(NetworkClient.java:157)
    at sun.net.www.http.HttpClient.openServer(HttpClient.java:365)
    at sun.net.www.http.HttpClient.openServer(HttpClient.java:477)
    at sun.net.www.http.HttpClient.<init>(HttpClient.java:214)
    at sun.net.www.http.HttpClient.New(HttpClient.java:287)
    at sun.net.www.http.HttpClient.New(HttpClient.java:299)
    at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(HttpURLConnection.java:792)
    at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:744)
    at sun.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:669)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:913)
    at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.setupCurrentEntity(XMLEntityManager.java:973)
    at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.startEntity(XMLEntityManager.java:905)
    at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.startDTDEntity(XMLEntityManager.java:872)
    at com.sun.org.apache.xerces.internal.impl.XMLDTDScannerImpl.setInputSource(XMLDTDScannerImpl.java:282)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$DTDDispatcher.dispatch(XMLDocumentScannerImpl.java:1021)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:368)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:834)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:764)
    at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:148)
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1242)
    at org.jdom.input.SAXBuilder.build(SAXBuilder.java:453)
    at org.jdom.input.SAXBuilder.build(SAXBuilder.java:810)
    at org.jdom.input.SAXBuilder.build(SAXBuilder.java:789)
    at dom.TestJdom.main(TestJdom.java:26)

三、分析原因
当执行build的时候jdom分析到
DOCTYPE workflow PUBLIC "-/OpenSymphony Group//DTD OSWorkflow 2.8//EN" "http://www.opensymphony.com/osworkflow/workflow_2_8.dtd 
就会去读取http://www.opensymphony.com/osworkflow/workflow_2_8.dtd 这里的dtd文件来验证,但是因为网络是不通的所以就会报socket错误。

四、解决办法
1,最开始查看jdom api发现了这样一个方法
builder.setValidation(false);
这样可以让jdom不做验证,但是结果依然出问题,查了一下原因,说虽然不验证但是还是会下载
2,参照jdom网站的FAQ  http://www.jdom.org/docs/faq.html#a0100这是原文内容

How do I keep the DTD from loading? Even when I turn off validation the parser tries to load the DTD file.

Even when validation is turned off, an XML parser will by default load the external DTD file in order to parse the DTD for external entity declarations. Xerces has a feature to turn off this behavior named "http://apache.org/xml/features/nonvalidating/load-external-dtd" and if you know you're using Xerces you can set this feature on the builder.

builder.setFeature(
  "http://apache.org/xml/features/nonvalidating/load-external-dtd", false);

If you're using another parser like Crimson, your best bet is to set up an EntityResolver that resolves the DTD without actually reading the separate file.

import org.xml.sax.*;
import java.io.*;

public class NoOpEntityResolver implements EntityResolver {
  public InputSource resolveEntity(String publicId, String systemId) {
    return new InputSource(new StringBufferInputStream(""));
  }
}

Then in the builder


builder.setEntityResolver(new NoOpEntityResolver());

There is a downside to this approach. Any entities in the document will be resolved to the empty string, and will effectively disappear. If your document has entities, you need to setExpandEntities(false) code and ensure the EntityResolver only suppresses the DocType.

里边教我们定义个类

public class NoOpEntityResolver implements EntityResolver {
  public InputSource resolveEntity(String publicId, String systemId) {
             return new InputSource(new StringBufferInputStream(""));
  }
}

通过builder.setEntityResolver(new NoOpEntityResolver())方法来隐蔽起dtd验证器。这样就不会出错了。试了一下确实没问题了。但要知道xml没有dtd验证是不好的,我们是否能让它使用本地dtd验证呢。例如本文的oswork
我把验证文件workflow_2_8.dtd拷贝到本地,能否验证的时候用本地的呢? 
3,用本地dtd验证
方法有两种
方法一、更改xml中的doctype声明,但是一般情况下更改这个是不好的。更改后就不是标准的了。
方法二、验证期替换
public Document load(String file) throws JDOMException, IOException {
       try {
  SAXBuilder sax = new SAXBuilder();
        sax.setValidation(false);
        sax.setEntityResolver(new EntityResolver() {
            public InputSource resolveEntity(String publicId,String systemId) throws SAXException, IOException {
                    /*InputSource is = new InputSource(new FileInputStream(System.getProperty("user.dir")+"//web-app_2_3.dtd"));
                    is.setPublicId(publicId);
                    is.setSystemId(systemId);
                    return is;

                 */
                 return new InputSource(new FileInputStream(""));
            }
        });
  return sax.build(file);
       } catch ( Exception e )  {
           e.printStackTrace();
           return null;           
       }
 }

 

 

http://blog.csdn.net/youlianying/article/details/5908335

时间: 2024-11-03 21:13:10

jdom dom4j解析xml不对dtd doctype进行验证(转)的相关文章

[Java开发之路](12)JDOM和DOM4J解析XML文档

1. JDOM解析XML文档 1.1 简介 JDOM是一个开源项目,它基于树型结构,利用纯JAVA的技术对XML文档实现解析.生成.序列化以及多种操作.JDOM 直接为JAVA编程服务.它利用更为强有力的JAVA语言的诸多特性(方法重载.集合概念以及映射),把SAX和DOM的功能有效地结合起来.在使用设计上尽可能地隐藏原来使用XML过程中的复杂性.利用JDOM处理XML文档将是一件轻松.简单的事. JDOM帮助文档 : http://www.jdom.org/docs/apidocs/ Jar包

Dom4j解析xml文件

时间:2003.12.15   版权声明: 本文由冰云完成,首发于CSDN,未经许可,不得使用于任何商业用途. 文中代码部分引用自DOM4J文档. 欢迎转载,但请保持文章及版权声明完整. 如需联络请发邮件:icecloud(AT)sina.com       DOM4J是dom4j.org出品的一个开源XML解析包,它的网站中这样定义: Dom4j is an easy to use, open source library for working with XML, XPath and XSL

用dom4j解析XML的时候[Document: name null]

问题描述 用dom4j解析XML的时候[Document: name null] 补充: StringXML = "<?xml version="1.0" encoding="UTF-8"?>10019807752138114538203547650510236870>"; Document document = null; try { //这个StringXML 是一个 document = DocumentHelper.pa

Dom4j解析xml内容为空

问题描述 Dom4j解析xml内容为空 Document doc1 = saxR.read(xmlfile);Element rootElt1 = doc1.getRootElement();Element name = rootElt1.element(""Name""); String text=name.getText(); NameBean nameBean = new NameBean();nameBean.setName(name.getStringVa

dom4j解析xml文件实例

dom4j解析xml文件实例     package com.yanek.demo.xml.test; import java.io.File;import java.util.List; import org.dom4j.Document;import org.dom4j.DocumentException;import org.dom4j.Element;import org.dom4j.io.SAXReader; public class Dm4jReadXml {  /**  * @pa

dom4j解析xml具体步骤怎么写(链接数据库)

问题描述 dom4j解析xml具体步骤怎么写(链接数据库) 这个不会写 求教 QQ77389405 给发个项目参考参考也行 解决方案 Dom4j解析XML文档DOm4J 读写解析xml分享自己写的一个简单的IOC...通过dom4j对XML解析和反射 解决方案二: 百度一下,答案挺多的,模板也有现成的.

java dom4j解析xml,用的是dom4g解析

问题描述 java dom4j解析xml,用的是dom4g解析 下面数据格式 需要获取标签值 解决方案 Java Dom4j解析 xmlJava -- XML解析工具dom4jJava中解析XML的四种常用方法(4)_DOM4J解析---------------------- 解决方案二: 你怎么传图片呢?传文字上去我们可以直接粘贴复制测试

Java 使用 Dom4j 解析 XML 指南

Java 使用 Dom4j 解析 XML 指南 太阳火神的美丽人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致"创作公用协议 转载请保留此句:太阳火神的美丽人生 -  本博客专注于 敏捷开发及移动和物联设备研究:iOS.Android.Html5.Arduino.pcDuino,否则,出自本博客的文章拒绝转载或再转载,谢谢合作. 解析 XMLParsing XML 首先要做的事情之一就是,可能要解析某种类型的一个 XML 文档

在java中使用dom4j解析xml(示例代码)_java

虽然Java中已经有了Dom和Sax这两种标准解析方式 但其操作起来并不轻松,对于我这么一个初学者来说,其中部分代码是活生生的恶心 为此,伟大的第三方开发组开发出了Jdom和Dom4j等工具 鉴于目前的趋势,我们这里来讲讲Dom4j的基本用法,不涉及递归等复杂操作 Dom4j的用法很多,官网上的示例有那么点儿晦涩,这里就不写了 首先我们需要出创建一个xml文档,然后才能对其解析 xml文档: 复制代码 代码如下: <?xml version="1.0" encoding=&quo