xsltentityresolver

When merging multiple xml files, how can I set EntityResolver for child xml files as well besides the parent xml?


I have a book xml file which references other multiple xml files. When I try to run an xslt on the book.xml file, the EntityResolver in my code resolves the dtd path. However, for the children xml files which are being merged, the dtd paths are not resolved.

Sample sample_book.ditamap

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE bookmap PUBLIC "-//OASIS//DTD DITA BookMap//EN" "bookmap.dtd">
<bookmap>
    <booktitle>
        <mainbooktitle>sample book</mainbooktitle>
    </booktitle>
    <part navtitle="Overview">
        <topicref href="../topics/introduction.dita"/>
        <topicref href="../topics/install.dita"/>
    </part>
</bookmap>

`

Java Code

public class XMLProcessor  {

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

        org.xml.sax.XMLReader reader = XMLReaderFactory.createXMLReader();
        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:/sample/dtd/bookmap.dtd");
                }

                return null;
                }
            };
        // sour.setPublicId("file:///D:/sample/dtd/bookmap/dtd/bookmap.dtd");


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

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

    }





}`

Expected Result

`

<?xml version="1.0" encoding="UTF-8"?>
<pages xmlns:mf="urn:mf">
    <parentpage>
        <parentpagename>sample book</parentpagename>
    </parentpage>
    <part>
        <partname>Overview</partname>
        <text/>
        <level-2>
            <concept xmlns:ditaarch="http://dita.oasis-open.org/architecture/2005/"
                id="introduction" ditaarch:DITAArchVersion="1.3"
                domains="(topic concept)                            (topic abbrev-d)                            a(props deliveryTarget)                            (topic equation-d)                            (topic hazard-d)                            (topic hi-d)                            (topic indexing-d)                            (topic markup-d)                            (topic mathml-d)                            (topic pr-d)                            (topic relmgmt-d)                            (topic sw-d)                            (topic svg-d)                            (topic ui-d)                            (topic ut-d)                            (topic markup-d xml-d)   "
                class="- topic/topic concept/concept ">
                <title class="- topic/title ">Introduction</title>
                <shortdesc class="- topic/shortdesc "/>
                <conbody class="- topic/body  concept/conbody ">
                    <p class="- topic/p ">Sample introduction</p>
                </conbody>
            </concept>
        </level-2>
        <text/>
        <level-2>
            <task xmlns:ditaarch="http://dita.oasis-open.org/architecture/2005/" id="install"
                ditaarch:DITAArchVersion="1.3"
                domains="(topic task)                            (topic abbrev-d)                            a(props deliveryTarget)                            (topic equation-d)                            (topic hazard-d)                            (topic hi-d)                            (topic indexing-d)                            (topic markup-d)                            (topic mathml-d)                            (topic pr-d)                            (topic relmgmt-d)                            (topic sw-d)                            (topic svg-d)                            (topic ui-d)                            (topic ut-d)                            (topic markup-d xml-d)                            (topic task strictTaskbody-c)   "
                class="- topic/topic task/task ">
                <title class="- topic/title ">Install</title>
                <shortdesc class="- topic/shortdesc "/>
                <taskbody class="- topic/body task/taskbody ">
                    <context class="- topic/section task/context ">
                        <p class="- topic/p ">Download xyz installer from here. </p>
                    </context>
                    <steps class="- topic/ol task/steps ">
                        <step class="- topic/li task/step ">
                            <cmd class="- topic/ph task/cmd ">Double-click the downloader
                                installer.</cmd>
                        </step>
                        <step class="- topic/li task/step ">
                            <cmd class="- topic/ph task/cmd ">Do this.</cmd>
                        </step>
                        <step class="- topic/li task/step ">
                            <cmd class="- topic/ph task/cmd ">Do that</cmd>
                        </step>
                    </steps>
                </taskbody>
            </task>
        </level-2>
    </part>
</pages>

`

Actual Result

When the XSLT is run, the following error message is displayed. The error goes away, when I move the dtd files to the topics folder.

Warning   XTDE0540: Ambiguous rule match for /bookmap/booktitle[1] Matches both "element(Q{}booktitle)" on line 54 of
>file:///D:/sample/xsl/merge.xsl and "element(Q{}booktitle)" on line 18 of >file:///D:/sample/xsl/merge.xsl Warning at char 11 in

xsl:apply-templates/@select on line 30 column 104 of >merge.xsl: FODC0002: I/O error reported by XML parser processing file:/D:/sample/sampledoc/topics/introduction.dita: D:\sample\sampledoc\topics\concept.dtd (The system cannot find the

file specified) Warning at char 11 in xsl:apply-templates/@select on line 30 column 104 of >merge.xsl: FODC0002: I/O error reported by XML parser processing file:/D:/sample/sampledoc/topics/install.dita: D:\sample\sampledoc\topics\task.dtd (The system cannot find the >file specified)


Solution

  • You can set a URIResolver on the Transformer, which will be called when your XSLT code calls doc() or document() to fetch the referenced XML files. The URIResolver can then set an EntityResolver on the XML parser used to parse these files.

    Alternatively you can do all of this with the Apache XMLResolver which deferences URIs at both the XSLT and the XML level by reference to a catalog file in a format defined by OASIS.