Question

Lorsque j'analyse mon fichier xml (variable f) dans cette méthode, j'obtiens une erreur

  

C: \ Documents and Settings \ joe \ Desktop \ aicpcudev \ OnlineModule \ map.dtd (le système ne peut pas trouver le chemin spécifié)

Je sais que je n’ai pas le dtd, et n’en ai pas besoin. Comment analyser cet objet File dans un objet Document en ignorant les erreurs de référence 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;
}
Était-ce utile?

La solution

Une approche similaire à celle suggérée par @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;
            }
        }
    });

J'ai trouvé que renvoyer simplement un InputSource vide fonctionnait aussi bien?

Autres conseils

Essayez de définir des fonctionnalités sur 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();
...

En définitive, je pense que les options sont spécifiques à la mise en œuvre de l’analyseur. Voici une documentation pour Xerces2 si cela vous aide.

J'ai trouvé un problème où le fichier DTD était dans le fichier jar avec le fichier XML. J'ai résolu le problème en me basant sur les exemples ci-dessous:

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

Je sais que je n'ai pas le dtd, et j'en ai pas besoin.

Je me méfie de cette déclaration; votre document contient-il des références d'entités? Si tel est le cas, vous avez certainement besoin de la DTD.

Quoi qu'il en soit, le moyen habituel d'éviter ce problème consiste à utiliser un catalogue XML pour définir un chemin d'accès local pour "map.dtd".

voici un autre utilisateur qui a le même problème: http: // forums. sun.com/thread.jspa?threadID=284209&forumID=34

l'utilisateur ddssot sur cet article dit

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

L'utilisateur mentionne ensuite "Comme vous pouvez le constater, lorsque l'analyseur frappe la DTD, le résolveur d'entité est appelé. Je reconnais ma DTD avec son ID spécifique et renvoie un document XML vide à la place de la DTD réelle, en interrompant toute validation ... "

J'espère que cela vous aidera.

XML source (avec 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>

Implémentation DOM Java pour accepter le XML ci-dessus en tant que chaîne et supprimer la déclaration 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 de destination (sans DTD)

<MYACCSERVICE>
   <REQ_PAYLOAD>
      <ACCOUNT>1234567890</ACCOUNT>
      <BRANCH>001</BRANCH>
      <CURRENCY>USD</CURRENCY>
      <TRANS_REFERENCE>201611100000777</TRANS_REFERENCE>
   </REQ_PAYLOAD>
</MYACCSERVICE> 
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top