Using JAXP to transform XML with XSLT. Can't find DTD

boomerang061797
boomerang061797 used Ask the Experts™
on
Hi

I am trying to transform some xml using my xsl stylesheet. My java program uses the JAXP API and I'm using j2sdk 1.4.1_01 on Win2000. The xml, xsl, and dtd files are not in the same directory as the classes.

The xml file references a dtd file:

<!DOCTYPE nrs SYSTEM "my.dtd">

When trying to transform the xml I get the following error: "Relative URI "my.dtd"; can not be resolved without a base URI."

When I comment out the DOCTYPE line in the xml file, everything works.

What's the solution? How do I get it to find the dtd file?
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Top Expert 2016

Commented:
There are two things you could try:

1. Use a file url, e.g. SYSTEM "file:///x/y/z/my.dtd"
2. Resolve the entity yourself, i.e. call setEntityResolver() on the InputSource and handle "my.dtd" in a custom entity-resolving class

Author

Commented:
It will have to be alternative 2 since I cannot change the xml file. However, I don't see where this method is to be called. My code is only using classes from the javax.xml.transform and javax.xml.transform.stream packages. The setEntityResolver method only seems to apply to javax.xml.parsers.DocumentBuilder or objects in the org.xml.sax.helpers package. Can you give an example of what you mean?

This is my code:

import java.io.*;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;

public class TransformXML {
  private Transformer transformer;
 
  public TransformXML(Reader xslt) throws TransformerException {
    Source source = new StreamSource(xslt);
    TransformerFactory factory = TransformerFactory.newInstance();
    transformer = factory.newTransformer(source);
  }
   
  public void transform(Reader xml, Writer writer) throws TransformerException {
    Source source = new StreamSource(xml);
    StreamResult result = new StreamResult(writer);
    transformer.transform(source, result);
  }
}
Top Expert 2016
Commented:
Looks like you could use setSystemId(String systemId) on the StreamSource, e.g. source.setSystemId("..\my.dtd");

Author

Commented:
I used source.setSystemId("my.dtd"); which seemed to do the trick. However, i'm not sure I know what I'm doing. What do I do if the dtd isn't in the same directory as the xml file (and not in a parent or subdirecoty)? Do I have to feed it a absolute URI of the form file://c:/.... etc. ?
Top Expert 2016

Commented:
That's what i'd try, yes.

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial