2008-09-30 3 views
68

Quand je parse mon fichier xml (variable f) dans cette méthode, je reçois une erreurFaire DocumentBuilder.parse ignorer DTD références

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

Je sais que je n'ai pas le dtd, ni j'en ai besoin. Comment puis-je analyser cet objet File dans un objet Document tout 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; 
} 
+0

Je crois que jt a la meilleure réponse à cette question. – simgineer

Répondre

52

Une approche similaire à celle proposé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 le simple fait de retourner un vide InputSource fonctionnait tout aussi bien?

+3

La définition des fonctionnalités de DocumentBuilderFactory a fonctionné pour moi. La solution dans ce post n'a pas fonctionné. –

+3

Cela a également fonctionné parfaitement pour moi, même si je pensais que je n'ai pas utilisé SAX – devnull69

+0

Malheureusement, cela n'a pas fonctionné pour moi. J'ai toujours l'erreur. @jt l'a fait pour moi cependant. –

2

Je sais que je n'ai pas dtd, ni ai-je besoin.

Je me méfie de cette déclaration; votre document contient-il des références d'entité? Si oui, vous avez certainement besoin de la DTD. Quoi qu'il en soit, la manière habituelle d'empêcher cela est d'utiliser un catalogue XML pour définir un chemin local pour "map.dtd".

+0

Mon code est entièrement fonctionnel si je commente la ligne dtd. – joe

2

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

utilisateur ddssot sur ce poste 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 plus loin « Comme vous pouvez le voir, lorsque l'analyseur frappe la DTD, l'entité resolver est appelé, je reconnais ma DTD avec son identifiant spécifique et renvoie un document XML vide au lieu de la vraie DTD, arrêtant toute validation ... "

Espérons que cela aide.

111

fonctions sur le réglage Essayez 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 fin de compte, je pense que les options sont spécifiques à la mise en œuvre de l'analyseur. Here is some documentation for Xerces2 si cela aide.

+17

le dernier ('load-external-dtd') fait le tour pour moi - merci. – Amarghosh

+1

En essayant cela, j'ai obtenu une _DOMException: NAMESPACE_ERR: Une tentative est faite pour créer ou modifier un objet d'une manière qui est incorrecte en ce qui concerne les espaces de noms. J'ai corrigé ceci avec 'dbf.setNamespaceAware (true);' – Esk

+0

Merci @Esk, j'ai mis à jour ma réponse pour inclure cette option. –

4

J'ai trouvé un problème où le fichier DTD se trouvait dans le fichier jar avec le fichier XML. J'ai résolu la question en se fondant sur les exemples ici, comme suit: -

 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 Source (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 Java DOM pour accepter ci-dessus XML sous forme de chaîne et la suppression 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>