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

简介: 一、写在所有之前:因为dom4j和jdom在这个问题上处理的方法是一模一样的,只是一个是SAXBuilder 一个SAXReader,这里以jdom距离,至于dom4j只需要同理替换一下就可以了。

 

一、写在所有之前:
因为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

相关文章
|
16小时前
|
XML Web App开发 JavaScript
XML DOM 解析器
浏览器内置XML解析器将XML转换为JavaScript可操作的DOM对象。通过XMLHttpRequest或ActiveXObject加载XML文档,如&quot;books.xml&quot;,然后解析成DOM,便于JavaScript访问和操作。示例展示了如何使用XMLHttpRequest加载XML。
|
2天前
|
XML Web App开发 JavaScript
XML DOM 解析器
浏览器内置XML解析器,用于读取和操作XML。XML解析器将XML转换为JavaScript可访问的DOM对象,提供遍历、增删节点功能。要访问XML文档,需先加载到DOM。以下JS代码示例展示了如何使用XMLHttpRequest加载XML文档&quot;books.xml&quot;:创建XMLHTTP对象,打开并发送请求到服务器,然后将响应转换为DOM对象。
|
2天前
|
XML JavaScript 前端开发
属性和方法向 XML DOM 定义了编程接口
XML DOM 提供编程接口,通过属性和方法操作XML结构。使用JavaScript等语言,可访问和修改节点。属性如nodeName、nodeValue揭示节点信息,方法如getElementsByTagName、appendChild、removeChild实现查找、添加和删除节点功能。节点对象x的应用示例贯穿其中。
|
4天前
|
XML 存储 JavaScript
XML DOM - 访问节点
`getElementsByTagName()` 方法用于获取 XML 文档中指定标签名的所有节点,返回一个节点列表。可以遍历这个列表或利用节点间的关联在树中导航。例如,加载 &quot;books.xml&quot; 到 `xmlDoc`,然后存储为 `x`。
|
4天前
|
XML 存储 JavaScript
XML DOM - 访问节点
`getElementsByTagName()` 方法用于访问 XML 文档中的节点,返回一个节点列表(Node List),类似数组。可以遍历节点树或利用节点关系导航来访问。示例代码加载 &quot;books.xml&quot; 到 xmlDoc,将所有 &quot;book&quot; 节点存入变量 x。
|
5天前
|
XML JavaScript 数据格式
XML DOM 遍历节点树
该文介绍如何遍历XML文档的节点树。通过循环移动,提取每个元素的值。示例代码展示了一个实例,它加载XML字符串到`xmlDoc`,然后遍历根元素的所有子节点,打印出节点名称及文本值。输出包括:`title: Everyday Italian`, `author: Giada De Laurentiis`, `year: 2005`。
|
5天前
|
XML JavaScript 数据格式
XML DOM 浏览器差异
不同浏览器在解析XML DOM时存在差异,尤其是对待空白和换行的方式。W3C DOM规范被现代浏览器广泛支持,但例如,Internet Explorer不将空白或换行视为文本节点,而其他浏览器则会。在处理如记事本编辑的XML文件时,这些差异可能导致计数子节点时的结果不一致。一个示例显示,对于包含空格和换行的XML,IE会报告4个子节点,而其他浏览器可能报告9个。
|
6天前
|
XML JavaScript 数据格式
XML DOM 浏览器差异
不同浏览器在解析XML DOM时存在差异,尤其是对待空白和换行的方式。W3C DOM规范虽被广泛支持,但例如,Internet Explorer不将空格或换行视为文本节点,而其他浏览器则会。一个例子显示,在编辑器中添加的CR/LF和空格,可能导致IE计数为4个子节点,而其他浏览器计数为9个。
|
7天前
|
XML Web App开发 JavaScript
XML DOM 解析器
浏览器通常内置XML解析器,将XML转换为JavaScript可操作的DOM对象。XML DOM提供遍历、修改XML节点的函数。
|
7天前
|
XML Web App开发 JavaScript
XML DOM 解析器
浏览器内置的XML解析器将XML转换为JavaScript可操作的DOM对象,允许遍历、访问和修改XML节点。要加载XML文档,如&quot;books.xml&quot;,可以使用XMLHttpRequest。以下是示例代码:创建XMLHTTP对象,打开GET请求,发送请求到服务器,然后将响应解析为DOM对象。这个过程在不同版本的浏览器中可能略有差异。

推荐镜像

更多