2011-01-18 3 views
10

Ho il seguente codice Java:il parsing di un file XML con uno schema DTD su un percorso relativo

 

DocumentBuilder db=DocumentBuilderFactory.newInstance().newDocumentBuilder(); 
Document doc=db.parse(new File("/opt/myfile")); 
 

E /opt/myfile contiene qualcosa di simile:

 
<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE archive SYSTEM "../../schema/xml/schema.dtd"> 
... 

ottengo il seguente errore:

 
java.io.FileNotFoundException: /../schema/xml/schema.dtd (No such file or directory) 

Questo è un grande framework java che consuma un file XML prodotto altrove. Penso che il percorso relativo sia il problema. Non penso che sia accettabile cambiare il cwd prima dell'avvio della JVM (il percorso proviene da un file di configurazione che viene letto dalla stessa JVM) e non ho trovato un modo per cambiare la cwd mentre la JVM è in esecuzione. Come analizzo questo file XML con il DTD appropriato?

risposta

17

È necessario utilizzare un numero personalizzato EntityResolver per modificare il percorso del DTD in modo che possa essere trovato. Per esempio:

db.setEntityResolver(new EntityResolver() { 
    @Override 
    public InputSource resolveEntity(String publicId, String systemId) 
      throws SAXException, IOException { 
     if (systemId.contains("schema.dtd")) { 
      return new InputSource(new FileReader("/path/to/schema.dtd")); 
     } else { 
      return null; 
     } 
    } 
}); 

Se schema.dtd è in classpath, si può semplicemente utilizzare getResourceAsStream per caricarlo, senza specificare il percorso completo:

return new InputSource(Foo.class.getResourceAsStream("schema.dtd")); 
+1

oppure potrebbe utilizzare un risolutore basato su catalogo. –

+0

Esempio di risolutore pronto all'uso: [org.hibernate.util.DTDEntityResolver] (http://stackoverflow.com/questions/10886453/hibernate-issue-with-using-http-www-hibernate-org-dtd) – Vadzim

0

Ho usato l'EntityResolver personalizzato come nell'esempio sopra ma ha ancora cercato il file DTD in un'altra directory di base. Quindi ho eseguito il debug e ho scoperto che ho bisogno di modificare la proprietà del sistema user.dir. Così ho aggiunto questa linea al mio metodo di inizializzazione dell'applicazione e ora funziona.

System.setProperty("user.dir")