`
nowing
  • 浏览: 84810 次
  • 来自: ...
社区版块
存档分类
最新评论

jdom 或 dom4j读取xml文件时如何让dtd验证使用本地dtd文件或者不生效

阅读更多
jdom 或 dom4j读取xml文件时如何让dtd验证使用本地dtd文件或者不生效
http://www.blogjava.net/dreamstone/archive/2007/08/29/140993.html

一、写在所有之前:
因为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声明,但是一般情况下更改这个是不好的。更改后就不是标准的了。
方法二、验证期替换
看到上边FAQ讲的方法你是否有什么灵感呢?
看看下边这段代码

package dom;

import java.io.File;
import java.io.IOException;

import org.jdom.Document;
import org.jdom.input.SAXBuilder;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

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();
            builder.setValidation(false);
            builder.setEntityResolver(new EntityResolver() {
                public InputSource resolveEntity(String publicId,
                        String systemId) throws SAXException, IOException {
                    return new InputSource("./workflow_2_8.dtd");
                }
            });
            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());
        }
    }
}

对了,同样是自己实现一个EntityResolver(这里用了匿名类),不同的是在里边使用本地的dtd验证
另外,匿名类内部,似乎这样写起来更顺眼些

InputStream stream = new FileInputStream( "your dtd file path" );
                    InputSource is = new InputSource(stream);
                    is.setPublicId(publicId);
                    is.setSystemId(systemId);
                    return is;
分享到:
评论

相关推荐

    读取XML文件的四种方法

    在Java中,读取XML文件有多种方法,本文将介绍四种常见的方法:DOM、DOM4J、JDOM和SAX。 DOM(Document Object Model) DOM是W3C组织制定的XML文档对象模型,它提供了对XML文档的树形结构表示。使用DOM方法读取XML...

    java中四种操作(dom、sax、jdom、dom4j)xml方式详解与比较.txt )

    java中四种操作(dom、sax、jdom、dom4j)xml方式详解与

    jdom 读取XML 文件

    本篇文章将深入探讨如何使用JDOM来读取XML文件。 首先,我们需要了解JDOM的基本概念。JDOM通过构建一棵DOM(Document Object Model)树来表示XML文档,这棵树是由节点构成的,包括元素(Element)、属性(Attribute...

    SAX, DOM, JDOM, DOM4J解析XML文件

    本文将详细介绍四种在Java中解析XML文件的方法:SAX、DOM、JDOM以及DOM4J。 1. SAX(Simple API for XML) SAX是一种基于事件驱动的解析器,它在读取XML文档时会触发一系列事件,如开始元素、结束元素、字符数据等...

    \"java xml 四\"之JDOM、DOM4J解析XML总结

    在IT行业中,XML(eXtensible Markup Language)是一种用于存储和传输数据的标准化格式,尤其在...在开发过程中,也可以根据实际情况考虑结合使用,例如,使用SAX或StAX读取大型文件,然后用JDOM或DOM4J进行后续处理。

    DOM、SAX、JDOM、DOM4J读写xml文档

    2. **DOM4J写入XML**:创建`Document`,添加元素和属性,然后使用`dom4j.io.XMLWriter`或`dom4j.io.OutputFormat`将`Document`写入文件。 在选择XML处理方式时,需要根据实际需求考虑内存消耗、处理速度以及API的...

    dom4j解析xml文件的压缩包

    5. **事件驱动解析(SAX)**:除了传统的DOM解析外,DOM4J还支持SAX解析器,这种解析方式适用于处理大型XML文件,因为它不需要一次性加载整个文档到内存。 6. **Namespace支持**:DOM4J提供了对XML命名空间的全面...

    XML的四种解析器(dom,sax,jdom,dom4j)原理及性能比较,超详细

    常见的 XML 解析器有 DOM、SAX、JDOM 和 DOM4J 等。每种解析器都有其特点和优缺,选择合适的解析器对应用程序的性能和开发效率有很大影响。 1. DOM 解析器 DOM(Document Object Model)是 W3C 官方标准,用于表示...

    JDOM、Dom4j操作xml文档

    在Java开发中,处理XML文档时,JDOM和Dom4j是两个常用的库。本文将详细介绍如何使用JDOM和Dom4j进行XML文档的操作,包括创建、修改、遍历以及XPath查询。 XML(可扩展标记语言)是一种用于存储和传输结构化数据的...

    DOM4J读取XML

    在深入探讨如何使用DOM4J库来解析XML文件之前,我们先简要了解DOM4J的基本概念及其在Java开发环境中的重要性。DOM4J是一个轻量级、高性能且易于使用的Java库,用于处理XML文档。它提供了类似于DOM、SAX和JDOM的API,...

    DOM、JDOM、DOM4J解析XML实例.pdf

    ### DOM、JDOM、DOM4J解析XML实例详解 #### DOM 方式解析 XML 实例解析 ##### 一、DOM 概述与应用实例 DOM(Document Object Model)是一种树状结构的标准,用于表示 XML 文档的数据结构。它将 XML 文档视为节点...

    Jdom、Dom4j 、dom解析xml文件

    DOM4J提供了类似于JDOM的API,使得处理XML更加方便,同时支持事件驱动的解析方式,可以在读取XML时只处理需要的部分,降低内存需求。DOM4J还支持XPath,允许通过表达式快速定位XML节点,极大地提高了开发效率。 ...

    DOM、JDOM、DOM4J解析XML实例

    ### DOM、JDOM、DOM4J解析XML实例 #### DOM解析XML DOM(Document Object Model)是一种树形结构的数据模型,用于表示XML或HTML文档。它允许程序在内存中加载整个文档,并通过提供的API来访问和修改文档中的任何...

    使用DOM4j解析XML文件

    在使用DOM4j解析XML文件时,首先需要导入DOM4j的相关包,如`SAXReader`用于读取XML文件,`Document`表示整个XML文档,`Element`表示XML文档中的元素,以及`Attribute`表示元素的属性。以下是一个使用DOM4j解析XML...

    sax,dom,jdom,dom4j之xml解析大荟萃

    如果文件较大或者内存有限,SAX和DOM4J是更好的选择,特别是DOM4J,因为它在处理大型XML时既兼顾了效率又保留了灵活性。 在提供的"test02"压缩包中,可能包含的是使用这些解析方式的示例代码,通过运行这些示例,你...

    jdom+dom4j

    为了处理XML文件,Java开发者经常使用库如JDOM和DOM4J,这两个都是Java XML API的实现。本文将深入探讨JDOM和DOM4J,以及它们在解析XML时的应用。 **JDOM** JDOM,全称Java Document Object Model,是一个专为Java...

    用DOM SAX JDom dom4j 对xml文档解析实例

    本文将深入探讨DOM、SAX、JDom和dom4j四种流行的Java XML解析器,以及它们在处理XML文档时的特点和用法。 1. DOM(Document Object Model) DOM是W3C推荐的一种解析XML的标准方法。它将XML文档表示为一个树形结构,...

    JDOM_Dom4j.rarJDOM_Dom4j.rar

    在实际开发中,JDOM和Dom4j经常被用来解析XML配置文件、生成XML报告或者与XML格式的数据交换。例如,在Web服务、数据存储、日志记录等领域,XML作为一种标准的数据交换格式,经常需要通过这些库进行处理。理解并熟练...

    xml(jdom-dom4j).rar_DOM4J_dom4j xml java

    DOM4J提供了一种将XML对象模型转换为字符串的方法,可以使用`DocumentWriter`或者`XMLWriter`来实现XML的输出。通过设置适当的格式化选项,可以控制生成的XML是否带缩进、换行等。 3. **XML的修改**: 修改XML...

    jdom解析xml、dtd约束xml文件

    这是一个jdom解析xml的小例子、里面还有dtd文件的编写以及dtd文件约束xml文件。这是一个jdom解析xml的小例子、里面还有dtd文件的编写以及dtd文件约束xml文件。这是一个jdom解析xml的小例子、里面还有dtd文件的编写...

Global site tag (gtag.js) - Google Analytics