<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    DANCE WITH JAVA

    開發(fā)出高質(zhì)量的系統(tǒng)

    常用鏈接

    統(tǒng)計

    積分與排名

    好友之家

    最新評論

    jdom 或 dom4j讀取xml文件時如何讓dtd驗證使用本地dtd文件或者不生效

    一、寫在所有之前:
    因為dom4j和jdom在這個問題上處理的方法是一模一樣的,只是一個是SAXBuilder 一個SAXReader,這里以jdom距離,至于dom4j只需要同理替換一下就可以了。
    二、問題發(fā)生的情況
    當你用jdom讀取一個有dtd驗證的xml文件,同時你的網(wǎng)絡是不通的情況下。會出現(xiàn)以下錯誤:
    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)

    三、分析原因
    當執(zhí)行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文件來驗證,但是因為網(wǎng)絡是不通的所以就會報socket錯誤。

    四、解決辦法
    1,最開始查看jdom api發(fā)現(xiàn)了這樣一個方法
    builder.setValidation(false);
    這樣可以讓jdom不做驗證,但是結(jié)果依然出問題,查了一下原因,說雖然不驗證但是還是會下載
    2,參照jdom網(wǎng)站的FAQ  http://www.jdom.org/docs/faq.html#a0100
    這是原文內(nèi)容
    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());
            }

        }

    }

    對了,同樣是自己實現(xiàn)一個EntityResolver(這里用了匿名類),不同的是在里邊使用本地的dtd驗證
    另外,匿名類內(nèi)部,似乎這樣寫起來更順眼些

    InputStream stream = new FileInputStream( "your dtd file path" );
                        InputSource is 
    = new InputSource(stream);
                        is.setPublicId(publicId);
                        is.setSystemId(systemId);
                        
    return is;

    posted on 2007-08-29 17:05 dreamstone 閱讀(8346) 評論(6)  編輯  收藏 所屬分類: 利器其它開源框架

    評論

    # re: jdom 或 dom4j讀取xml文件時如何讓dtd驗證使用本地dtd文件或者不生效 2007-09-07 17:19 楊愛友

    終于被我找到了。原來deeamstone就是你,慚愧啊。  回復  更多評論   

    # re: jdom 或 dom4j讀取xml文件時如何讓dtd驗證使用本地dtd文件或者不生效 2007-09-07 21:25 dreamstone

    你是 ?  回復  更多評論   

    # re: jdom 或 dom4j讀取xml文件時如何讓dtd驗證使用本地dtd文件或者不生效[未登錄] 2008-03-11 22:15 java初學者

    要的就是你1!
    謝謝了樓主!!  回復  更多評論   

    # re: jdom 或 dom4j讀取xml文件時如何讓dtd驗證使用本地dtd文件或者不生效 2008-03-18 11:14 thx

    thanks a lot.  回復  更多評論   

    # re: jdom 或 dom4j讀取xml文件時如何讓dtd驗證使用本地dtd文件或者不生效 2008-07-05 21:17 Velar

    Wow, that rocks!
    really appreciated it!  回復  更多評論   

    # re: jdom 或 dom4j讀取xml文件時如何讓dtd驗證使用本地dtd文件或者不生效[未登錄] 2010-06-03 18:27 gongmingwind

    真是豁然開朗啊  回復  更多評論   

    主站蜘蛛池模板: 免费国产黄网站在线观看可以下载| 亚洲精品国产美女久久久| 精品一区二区三区免费毛片爱| 美景之屋4在线未删减免费| 亚洲三级视频在线| 亚洲AV日韩AV永久无码免下载| 亚洲国产主播精品极品网红| 午夜爱爱免费视频| 一色屋成人免费精品网站| 在线播放免费人成毛片乱码| 手机永久免费的AV在线电影网| 亚洲成AV人片高潮喷水| 亚洲av一本岛在线播放| 亚洲福利视频网址| 亚洲αv在线精品糸列| 精品国产香蕉伊思人在线在线亚洲一区二区 | 黄色一级毛片免费看| 日本亚洲免费无线码 | 国产免费女女脚奴视频网| 久久久久久国产精品免费免费男同| eeuss免费天堂影院| 一级毛片免费一级直接观看| 美女被吸屁股免费网站| 特级无码毛片免费视频 | 亚洲无码日韩精品第一页| 亚洲av日韩片在线观看| 亚洲 综合 国产 欧洲 丝袜| 免费看的一级毛片| 日本成人在线免费观看| 日本免费v片一二三区| 国产一区二区三区免费看| 国产精品无码免费视频二三区| 精品免费国产一区二区| 国产精品99久久免费| 又黄又爽无遮挡免费视频| 九月婷婷亚洲综合在线| 亚洲男人第一无码aⅴ网站| 国产成人麻豆亚洲综合无码精品| 亚洲综合国产一区二区三区| 精品久久久久久亚洲| 亚洲一本综合久久|