2008-09-30 140 views
68

當我在這個方法分析我的xml文件(變量f),我得到一個錯誤讓DocumentBuilder.parse忽略DTD引用

C:\ Documents和Settings \喬\桌面\ aicpcudev \ OnlineModule \圖.dtd(系統找不到指定的路徑)

我知道我沒有dtd,也不需要它。我該如何解析這個File對象到一個Document對象中而忽略DTD引用錯誤?

private static Document getDoc(File f, String docId) throws Exception{ 
    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 
    DocumentBuilder db = dbf.newDocumentBuilder(); 
    Document doc = db.parse(f); 


    return doc; 
} 
+0

我相信jt對這個問題有最好的答案。 – simgineer 2017-12-14 17:43:50

回答

52

類似的方法向一個由@anjanb

builder.setEntityResolver(new EntityResolver() { 
     @Override 
     public InputSource resolveEntity(String publicId, String systemId) 
       throws SAXException, IOException { 
      if (systemId.contains("foo.dtd")) { 
       return new InputSource(new StringReader("")); 
      } else { 
       return null; 
      } 
     } 
    }); 

我發現,簡單地返回一個空的InputSource工作一樣好建議?

+3

設置DocumentBuilderFactory上的功能爲我工作。這篇文章中的解決方案不起作用。 – 2011-05-25 14:22:53

+3

這也適用於我,儘管我以爲我沒有使用SAX – devnull69 2013-03-13 14:44:19

2

我知道我沒有DTD,我也不需要它。

我對此表示懷疑;你的文檔是否包含任何實體引用?如果是這樣,你一定需要DTD。

無論如何,防止這種情況發生的常用方法是使用XML目錄來定義「map.dtd」的本地路徑。

+0

如果我註釋掉dtd行,我的代碼就可以完全正常工作。 – joe 2008-09-30 21:26:44

2

這裏是誰得到了同樣的問題,其他用戶:該帖子http://forums.sun.com/thread.jspa?threadID=284209&forumID=34

用戶ddssot說

myDocumentBuilder.setEntityResolver(new EntityResolver() { 
      public InputSource resolveEntity(java.lang.String publicId, java.lang.String systemId) 
       throws SAXException, java.io.IOException 
      { 
      if (publicId.equals("--myDTDpublicID--")) 
       // this deactivates the open office DTD 
       return new InputSource(new ByteArrayInputStream("<?xml version='1.0' encoding='UTF-8'?>".getBytes())); 
      else return null; 
      } 
}); 

用戶進一步提到「正如你所看到的,當分析器碰到DTD,實體我使用它的特定ID識別我的DTD,並返回一個空的XML文檔,而不是真正的DTD,停止所有驗證...「

希望這有助於解決問題。

111

試穿的DocumentBuilderFactory設置功能:

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 

dbf.setValidating(false); 
dbf.setNamespaceAware(true); 
dbf.setFeature("http://xml.org/sax/features/namespaces", false); 
dbf.setFeature("http://xml.org/sax/features/validation", false); 
dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-dtd-grammar", false); 
dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); 

DocumentBuilder db = dbf.newDocumentBuilder(); 
... 

最後,我想選擇特定的解析器實現。 Here is some documentation for Xerces2如果有幫助。

4

我發現DTD文件與XML一起存在於jar文件中的問題。我解決了這個問題,根據這裏的例子如下: -

 DocumentBuilder db = dbf.newDocumentBuilder(); 
     db.setEntityResolver(new EntityResolver() 
     { 
      public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException 
      { 
       if (systemId.contains("doc.dtd")) 
       { 
        InputStream dtdStream = MyClass.class 
          .getResourceAsStream("/my/package/doc.dtd"); 
        return new InputSource(dtdStream); 
       } 
       else 
       { 
        return null; 
       } 
      } 
     }); 
1

源XML(帶DTD)

<!DOCTYPE MYSERVICE SYSTEM "./MYSERVICE.DTD"> 
<MYACCSERVICE> 
    <REQ_PAYLOAD> 
     <ACCOUNT>1234567890</ACCOUNT> 
     <BRANCH>001</BRANCH> 
     <CURRENCY>USD</CURRENCY> 
     <TRANS_REFERENCE>201611100000777</TRANS_REFERENCE> 
    </REQ_PAYLOAD> 
</MYACCSERVICE> 

Java的DOM實現接受上述XML作爲字符串和刪除DTD聲明

public Document removeDTDFromXML(String payload) throws Exception { 

    System.out.println("### Payload received in XMlDTDRemover: " + payload); 

    Document doc = null; 
    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 
    try { 

     dbf.setValidating(false); 
     dbf.setNamespaceAware(true); 
     dbf.setFeature("http://xml.org/sax/features/namespaces", false); 
     dbf.setFeature("http://xml.org/sax/features/validation", false); 
     dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-dtd-grammar", false); 
     dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); 

     DocumentBuilder db = dbf.newDocumentBuilder(); 

     InputSource is = new InputSource(); 
     is.setCharacterStream(new StringReader(payload)); 
     doc = db.parse(is); 

    } catch (ParserConfigurationException e) { 
     System.out.println("Parse Error: " + e.getMessage()); 
     return null; 
    } catch (SAXException e) { 
     System.out.println("SAX Error: " + e.getMessage()); 
     return null; 
    } catch (IOException e) { 
     System.out.println("IO Error: " + e.getMessage()); 
     return null; 
    } 
    return doc; 

} 

目標XML(無DTD)

<MYACCSERVICE> 
    <REQ_PAYLOAD> 
     <ACCOUNT>1234567890</ACCOUNT> 
     <BRANCH>001</BRANCH> 
     <CURRENCY>USD</CURRENCY> 
     <TRANS_REFERENCE>201611100000777</TRANS_REFERENCE> 
    </REQ_PAYLOAD> 
</MYACCSERVICE>