DocumentBuilder.parse को DTD संदर्भों को अनदेखा करें


82

जब मैं इस विधि में अपनी xml फ़ाइल (चर f) को पार्स करता हूं, तो मुझे एक त्रुटि मिलती है

C: \ Documents and Settings \ joe \ Desktop \ aicpcudev \ OnlineModule \ map.dtd (सिस्टम निर्दिष्ट पथ नहीं ढूँढ सकता)

मुझे पता है कि मेरे पास डीडीटी नहीं है, न ही मुझे इसकी आवश्यकता है। 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;
}

1
मेरा मानना ​​है कि jt के पास इस सवाल का सबसे अच्छा जवाब है।
सामी

जवाबों:


59

@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 वापस करते हुए भी काम किया है?


4
DocumentBuilderFactory पर सुविधाओं को सेट करना मेरे लिए काम किया। इस पोस्ट में समाधान काम नहीं किया।
काई मचेल

4
इसने मेरे लिए भी पूरी तरह से काम किया, हालांकि मुझे लगा कि मैंने
devnull69

अफसोस की बात है कि यह मेरे लिए काम नहीं किया। मुझे अभी भी त्रुटि मिली है। @jt ने हालांकि मेरे लिए यह किया।
नेल्स-ओ-मैट

समाधान के लिए धन्यवाद, यह मुझे लगता है कि org.xml द्वारा अनुशंसित दृष्टिकोण है। ऐसा लगता है कि इस विषय पर बहुत सारी सामग्री है। देख xerces.apache.org/xml-commons/components/resolver/... , या en.wikipedia.org/wiki/XML_Catalog और जावाडोक saxproject.org/apidoc/org/xml/sax/EntityResolver.html और saxproject.org/ apidoc / org / xml / sax / ext / EntityResolver2.html
एलोपियो

135

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();
...

अंततः, मुझे लगता है कि विकल्प पार्सर कार्यान्वयन के लिए विशिष्ट हैं। यहाँ Xerces2 के लिए कुछ प्रलेखन है अगर यह मदद करता है।


21
पिछले एक ( load-external-dtd) ने मेरे लिए चाल चली - धन्यवाद।
अमरघोष

1
इसे आज़माते हुए , मुझे एक DOMException: NAMESPACE_ERR मिला है : ऑब्जेक्ट को नामस्थान के संबंध में गलत तरीके से बनाने या बदलने का प्रयास किया जाता है। । मैंने इसके साथ तय कियाdbf.setNamespaceAware(true);
टिम वान लेर

बस आपको बता दें, SAXParserFactory के साथ अंतिम फीचर सेटिंग (@Amarghosh द्वारा बताई गई) बहुत अच्छी है।
एलेक्सिस लेक्लर्क

1
मेरे लिए load-external-dtdसेटिंग काफी थी।
क्रिस

उपरोक्त सभी सुविधाओं का उपयोग करना भी कोड को विफल बनाता है। बस अंतिम दो फीचर (नॉनवैलिडिंग) का उपयोग करने से मेरा कोड काम करता है।
पुरू

5

मुझे एक समस्या मिली जहाँ DTD फ़ाइल XML के साथ जार फ़ाइल में थी। मैंने उदाहरण के आधार पर इस मुद्दे को हल किया, इस प्रकार है: -

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;
         }
      }
});

4

स्रोत 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>

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> 

2

मुझे पता है कि मेरे पास डीडीटी नहीं है, न ही मुझे इसकी आवश्यकता है।

मुझे इस कथन पर संदेह है; क्या आपके दस्तावेज़ में कोई इकाई संदर्भ है? यदि हां, तो आपको निश्चित रूप से डीटीडी की आवश्यकता है।

वैसे भी, ऐसा होने से रोकने का सामान्य तरीका "मैप.dtd" के लिए स्थानीय पथ को परिभाषित करने के लिए XML कैटलॉग का उपयोग करना है।


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;
          }
});

उपयोगकर्ता आगे उल्लेख करता है "जैसा कि आप देख सकते हैं, जब पार्सर डीटीडी को हिट करता है, तो यूनिट रिज़ॉल्वर को बुलाया जाता है। मैं अपने डीटीडी को इसकी विशिष्ट आईडी के साथ पहचानता हूं और वास्तविक डीटीडी के बजाय एक खाली एक्सएमएल डॉक्टर लौटाता हूं, जो सभी सत्यापन रोक देता है ..."

उम्मीद है की यह मदद करेगा।


0

मैं सोनारक्बी के साथ काम कर रहा हूं, और ग्रहण के लिए सोनारलिंट ने मुझे दिखाया कि बाहरी डेटा को हल किए बिना बिना एक्सएमएल को पार्स किया जाना चाहिए (स्क्विड: S2755)

मैं इसका उपयोग करके हल करने में कामयाब रहा:

    factory = DocumentBuilderFactory.newInstance();

    factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);

    // If you can't completely disable DTDs, then at least do the following:
    // Xerces 1 - http://xerces.apache.org/xerces-j/features.html#external-general-entities
    // Xerces 2 - http://xerces.apache.org/xerces2-j/features.html#external-general-entities
    // JDK7+ - http://xml.org/sax/features/external-general-entities
    factory.setFeature("http://xml.org/sax/features/external-general-entities", false);

    // Xerces 1 - http://xerces.apache.org/xerces-j/features.html#external-parameter-entities
    // Xerces 2 - http://xerces.apache.org/xerces2-j/features.html#external-parameter-entities
    // JDK7+ - http://xml.org/sax/features/external-parameter-entities
    factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);

    // Disable external DTDs as well
    factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);

    // and these as well, per Timothy Morgan's 2014 paper: "XML Schema, DTD, and Entity Attacks"
    factory.setXIncludeAware(false);
    factory.setExpandEntityReferences(false);
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.