`
仅此而已
  • 浏览: 61440 次
  • 性别: Icon_minigender_1
  • 来自: 沈阳
社区版块
存档分类
最新评论

转载 dom4j校验dtd文件不生效

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


一、写在所有之前:
因为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;
 
分享到:
评论

相关推荐

    使用DOM4J验证DTD最简单的方法

    在本文中,我们将深入探讨如何使用DOM4J来验证XML文档对DTD(Document Type Definition)的符合性,这是一个确保XML文档结构正确的重要步骤。 首先,我们需要理解DTD的作用。DTD是XML文档类型定义,它定义了XML文档...

    DOM4J解析XML时DTD路径问题

    如果网络不可用或该URL无法访问,则DOM4J将无法获取DTD文件,从而导致解析失败,并抛出异常:“无法找到DTD文件”。 #### 解决方案 为了解决这个问题,可以通过自定义`EntityResolver`来提供一种机制,使得DOM4J...

    dom4j_dom4j1.6.1安装包_

    DOM4J 1.6.1版的API还包括对XML Schema和DTD的支持,可以处理命名空间,提供事件驱动的处理模型,以及XML文档的序列化功能。这些特性使得DOM4J成为Java开发中处理XML的强大工具。 在实际开发中,DOM4J常用于读取...

    Dom4j 1.6.1 JAVA API

    dom4j帮助文档 官方API ...org.dom4j.dtd org.dom4j.io org.dom4j.jaxb org.dom4j.rule org.dom4j.rule.pattern org.dom4j.swing org.dom4j.tree org.dom4j.util org.dom4j.xpath org.dom4j.xpp

    dom4j-1.6.1 与 dom4j-2.0.0-ALPHA

    DOM4J是一个强大的Java库,专门用于处理XML文档。它提供了灵活、高效的API,使得XML的解析、创建、修改和查询变得简单。这次我们有两个版本的DOM4J库:1.6.1和2.0.0-ALPHA。这两个版本在功能、性能和API设计上都有所...

    log4j中的dtd文件

    在Log4j的上下文中,`log4j.dtd`是Log4j配置文件(通常命名为`log4j.properties`或`log4j.xml`)的DTD,它定义了配置文件中可以使用的元素、属性及其结构,确保配置文件的合法性。 在Log4j的配置文件中,我们可以...

    DOM4J帮助文档及使用教程

    4. **解析XML**:讲解如何使用DOM4J解析XML文件,包括SAX和DOM两种解析方式,并对比两者的优缺点。 5. **创建XML**:演示如何使用DOM4J创建新的XML文档,包括动态生成和修改XML结构。 6. **遍历与操作**:介绍如何...

    dom4j api 参考手册

    org.dom4j.dtd Classes to represent the DTD declarations. org.dom4j.io Provides input and output via SAX and DOM together with writing dom4j objects to streams as XML text. org.dom4j.jaxb org.dom4j....

    dom4j解析xml详解

    - **配置文件解析**: 许多应用使用XML作为配置文件的格式,DOM4J可以方便地读取和更新这些配置信息。 - **Web服务**: 在SOAP等协议中,XML是常用的数据传输格式,DOM4J能够帮助构建和解析这些XML消息。 - **文档生成...

    dom4j-1.6.1.jar

    10. **IO操作**:DOM4J提供了一套简单的API来读写XML文件,支持流式处理,可以高效地处理大文件。 总结来说,DOM4J-1.6.1.jar是一个强大且易用的XML处理库,适合各种Java项目中对XML的读取、修改和创建需求。通过...

    dom4j(2.1.1+ 2.0.2+ 1.6.1).zip

    **DOM4J库详解** DOM4J是一款强大的Java XML处理库,它提供了全面而灵活的API,用于处理XML文档。这个压缩包包含了DOM4J的三个不同版本:2.1.1、2.0.2和1.6.1,分别对应不同的Java环境兼容性。 1. **DOM4J 2.1.1**...

    dtd定义xml dom4j解析xml小类

    DTD 定义 XML DOM4J 解析 XML 小类 XML 文档类型定义(DTD)是用来定义一段合法的 XML 文档块的。它用来验证你的 XML 文档是以一系列合法的元素构成的。DTD 可以在 XML 文档内部定义,也可以通过外部文件的方式引入...

    dom4J解析XML文件

    在这个场景中,我们将深入探讨DOM4J在解析XML文件方面的应用。 XML(Extensible Markup Language)是一种用于存储和传输数据的标记语言,广泛应用于Web服务、配置文件、数据交换等领域。DOM4J作为一个解析器,它的...

    dom4j1.1-1.6.1.rar

    DOM4J的名字来源于“Document Object Model for Java”,但它并不仅仅是一个DOM实现,它还包含了SAX和DOM接口的实现,以及一些额外的功能,如XPath支持和事件模型。 DOM4J1.1和DOM4J1.6.1是两个不同版本的发布。...

    dom4j.jar,dom,xml,dom4j

    此外,DOM4J还包含了XML Schema和DTD(Document Type Definition)的支持,可以用于验证XML文档是否符合定义的结构。这对于确保数据的准确性和一致性至关重要。 DOM4J-1.6.1.jar是DOM4J的一个版本,发布于2006年。...

    dom4j源代码,包含dom4j.jar

    这个压缩包包含了DOM4J的源代码和预编译的jar文件,对于开发者来说,这是一个宝贵的资源,可以深入理解DOM4J的工作原理,并在实际项目中方便地使用它。 首先,DOM4J的核心概念是Element,它代表了XML文档中的一个...

    IE浏览器校验dtd文件小插件(含使用说明)

    **IE浏览器校验dTD文件小插件:Iexmltls详解** 在信息化时代,XML(eXtensible Markup Language)作为一种数据交换和存储的标准,广泛应用于各种领域。XML文档通常需要遵循一定的结构规则,这就是所谓的DTD...

    解析xml文件dom4j

    此外,DOM4J还提供了对DTD(Document Type Definition)和XML Schema的支持,以验证XML文档的结构正确性。 DOM4J 2.0.3是更新的版本,它可能包含了更多的优化和新特性,比如对Java 8及更高版本的支持,以及性能上的...

    dom4j使用简介

    **DOM4J使用简介** DOM4J 是一个强大的 Java 库,专为处理 XML 文档而设计。它提供了丰富的 API,使得在 Java 中解析、创建、修改 XML 文件变得简单高效。DOM4J 不仅支持 DOM(文档对象模型)和 SAX(简单API for ...

Global site tag (gtag.js) - Google Analytics