10

I have some XML that I'm parsing with a SAX parser in Java. It starts with this preamble:

<!DOCTYPE math 
    PUBLIC "-//W3C//DTD MathML 3.0//EN"
           "http://www.w3.org/Math/DTD/mathml3/mathml3.dtd">

How do I change this to use a local DTD?

I suppose I could do something like this:

<!DOCTYPE math 
    PUBLIC "-//W3C//DTD MathML 3.0//EN"
           "file:///c:/MathML/mathml3.dtd">

Not exactly like that, but something like that. However, I need the path to be independent of the user's system.

How do I use a local DTD with a path relative to the class path?

Paul Reiners
  • 9,480
  • 31
  • 110
  • 189
  • 1
    Possibly useful to look at this question: http://stackoverflow.com/questions/243728/how-to-disable-dtd-at-runtime-in-javas-xpath –  Jun 13 '11 at 14:37
  • Another possibility is to use an XML Catalog that resolves the doctype to a local file without changing the XML. This pushes the change to a parameter to the parser invocation. – Jim Garrison Jun 13 '11 at 14:38

4 Answers4

6

When dealing with Web Apps, you can put the dtd in the lib folder and refer to it like:

<!DOCTYPE name PUBLIC 
    "-//CMP//DTD dtdName 1.0//EN"
        "/WEB-INF/lib/dtdName.dtd">
Sully
  • 14,198
  • 5
  • 50
  • 77
  • this is simpler than the first answer !! Thanks Hitham – mounaim Apr 23 '15 at 09:38
  • 1
    I posted the answer as a web app solution and not for simplicity – Sully Sep 05 '17 at 21:57
  • lib folder should contain "only" libraries. – Mehdi Oct 26 '18 at 17:43
  • @Mehdi, DTDs are usually inside JARs, which are in the lib folder. You just have to reference them differently as `jar:file: /log4j.jar!/org/apache/log4j/xml/log4j.dtd` – Sully Oct 28 '18 at 19:07
  • Didn't know you can reference a dtd inside a jar, but it's a file appart, why not to place it in a path like conf/dtd and keep the lib folder for jars as possible. – Mehdi Oct 29 '18 at 02:54
4

The solution is to provide the DTD file location in the system using classpath. So the DocType that worked offline would be:

<!DOCTYPE hibernate-configuration SYSTEM 
    "classpath://org/hibernate/hibernate-configuration-3.0.dtd">
alok
  • 2,588
  • 19
  • 17
  • This works only with special [org.hibernate.util.DTDEntityResolver](http://stackoverflow.com/questions/10886453/hibernate-issue-with-using-http-www-hibernate-org-dtd). – Vadzim Feb 28 '17 at 18:14
  • java.net.MalformedURLException: unknown protocol: classpath I am getting this exception – Jerry May 29 '18 at 09:10
4

Take a look at this article on using XML catalogs to resolve DTDs locally without having to modify your XML source. The basic steps are:

  1. create an XML file that maps system IDs to local DTDs
  2. modify your code to instantiate and configure a CatalogResolver
  3. provide the CatalogResolver to the XML Reader (obtained from the parser)
Jim Garrison
  • 83,534
  • 20
  • 149
  • 186
0

Also another way can be to keep the dtd at the localhost so that the final path becomes something like:

<!DOCTYPE hibernate-configuration SYSTEM 
          "http://localhost/hibernate-configuration-3.0.dtd">

Definitely not the most elegant solution but surely does work.