it-swarm.com.de

Lassen Sie DocumentBuilder.parse DTD-Verweise ignorieren

Wenn ich meine XML-Datei (Variable f) in dieser Methode analysiere, erhalte ich eine Fehlermeldung

C:\Dokumente und Einstellungen\joe\Desktop\aicpcudev\OnlineModule\map.dtd (Das System kann den angegebenen Pfad nicht finden.)

Ich weiß, ich habe weder das dtd noch brauche ich es. Wie kann ich dieses File-Objekt in ein Document-Objekt zerlegen und dabei DTD-Referenzfehler ignorieren?

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;
}
76
joe

Ein ähnlicher Ansatz wie der von @ 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;
            }
        }
    });

Ich fand, dass die einfache Rückgabe einer leeren InputSource genauso gut funktioniert hat?

57
toolkit

Versuchen Sie, Funktionen in der DocumentBuilderFactory festzulegen:

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

Letztendlich denke ich, dass die Optionen spezifisch für die Parser-Implementierung sind. Hier ist eine Dokumentation für Xerces2 wenn das hilft.

125
jt.

Ich habe ein Problem gefunden, bei dem die DTD-Datei zusammen mit der XML-Datei in der JAR-Datei enthalten war. Ich habe das Problem anhand der folgenden Beispiele gelöst:

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;
         }
      }
});
5
Peter J

Quell-XML (mit 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-Implementierung zum Akzeptieren des obigen XML als String und zum Entfernen der DTD-Deklaration

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;

}

Ziel-XML (ohne DTD)

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

hier ist ein anderer Nutzer, der das gleiche Problem hat: http://forums.Sun.com/thread.jspa?threadID=284209&forumID=34

benutzer ddssot in diesem Beitrag sagt

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

Der Benutzer erwähnt weiter "Wie Sie sehen, wird der Entity Resolver aufgerufen, wenn der Parser auf die DTD trifft. Ich erkenne meine DTD mit ihrer spezifischen ID und gebe ein leeres XML-Dokument anstelle der echten DTD zurück, wodurch alle Überprüfungen gestoppt werden ..."

Hoffe das hilft.

2
anjanb

Ich weiß, ich habe weder das dtd noch brauche ich es.

Ich bin dieser Aussage misstrauisch; Enthält Ihr Dokument Entitätsreferenzen? Wenn ja, brauchen Sie definitiv die DTD.

Die übliche Möglichkeit, dies zu verhindern, ist die Verwendung eines XML-Katalogs, um einen lokalen Pfad für "map.dtd" zu definieren.

2
Edward Z. Yang