0

I am trying to set the dtd path dynamically. When I use the EntityResolver class, it works for org.xml.sax.XMLReader. But I don't know how to set the EntityResolver for a SAXSource. How can I correct the following code?

import java.util.logging.Logger;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.stream.StreamSource;
import javax.xml.transform.stream.StreamResult;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;

public class XMLProcessor  {

       public void transform(String xmlf, String xslf) throws TransformerConfigurationException, TransformerException, org.xml.sax.SAXException, IOException{


        Transformer transformer;
        TransformerFactory factory = TransformerFactory.newInstance();

         StreamSource stylesheet = new StreamSource(xslf);

         //Source source = StreamSource(xmlf);
         SAXSource source = new SAXSource(new InputSource(xmlf));
         org.xml.sax.XMLReader reader = XMLReaderFactory.createXMLReader();

         EntityResolver ent = new EntityResolver() {

            @Override
            public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {

                System.out.println(publicId);
                System.out.println(systemId);

                if(publicId.equals("-//OASIS//DTD DITA BookMap//EN")){
                    return new InputSource("file:///D:/dtd/bookmap/dtd/bookmap.dtd");
                }

                if(systemId.equals("file:///D:/doc/maps/bookmap.dtd")){
                    return new InputSource("file:////dtd/bookmap/dtd/bookmap.dtd");
                }
                return null;
                }
            };
        // sour.setPublicId("file:///D:/dtd/bookmap/dtd/bookmap.dtd");



            reader.setEntityResolver(ent);
            reader.parse(new InputSource(xmlf));
         //StreamSource sourcedoc = new StreamSource(xmlf);
         transformer = factory.newTransformer(stylesheet);

        try {
            transformer.transform(source, new StreamResult(new FileWriter("out/result.xml")));
        } catch (IOException ex) {
            Logger.getLogger(XMLProcessor.class.getName()).log(Level.SEVERE, null, ex);
        }

    }




}

The entity resolution seems to work for this line:

 reader.parse(new InputSource(xmlf));

But the following line fails:

transformer.transform(source, new StreamResult(new FileWriter("out/result.xml")));

and I get this error:

doc\maps\bookmap.dtd (The system cannot find the file specified)

halfer
  • 19,824
  • 17
  • 99
  • 186
Antony
  • 115
  • 1
  • 11

1 Answers1

0

There is a constructor

public SAXSource(XMLReader reader,
                 InputSource inputSource)

https://docs.oracle.com/javase/8/docs/api/javax/xml/transform/sax/SAXSource.html#SAXSource-org.xml.sax.XMLReader-org.xml.sax.InputSource-

so you should be able to use

     org.xml.sax.XMLReader reader = XMLReaderFactory.createXMLReader();

     EntityResolver ent = new EntityResolver() {

        @Override
        public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {

            System.out.println(publicId);
            System.out.println(systemId);

            if(publicId.equals("-//OASIS//DTD DITA BookMap//EN")){
                return new InputSource("file:///D:/dtd/bookmap/dtd/bookmap.dtd");
            }

            if(systemId.equals("file:///D:/doc/maps/bookmap.dtd")){
                return new InputSource("file:////dtd/bookmap/dtd/bookmap.dtd");
            }
            return null;
            }
        };



        reader.setEntityResolver(ent);

        SAXSource source = new SAXSource(reader, new InputSource(xmlf));
Martin Honnen
  • 160,499
  • 6
  • 90
  • 110
  • Thank you for helping me. It works. I have one small problem here. I apply an xsl to a book map and merge multiple topics (xml files). This code resolves the entity for the book map. However, the processor cannot locate the dtd files for the individual xml files. How do I set one location for all dtd files? Thanks in advance. – Antony Mar 24 '19 at 14:49
  • @Antony, consider to raise that problem as a new question with minimal but complete samples of the different files to demonstrate the problem, together with an exact error message. – Martin Honnen Mar 24 '19 at 14:57
  • Sure. I have posted another question here:https://stackoverflow.com/questions/55325569/when-merging-multiple-xml-files-how-can-i-set-entityresolver-for-child-xml-file – Antony Mar 24 '19 at 15:48