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

与世无争的帅哥 提交于 2019-12-24 20:52:32

问题


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)


回答1:


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.




回答2:


Thanks to Michael, I could resolve this issue.

  1. Added a CatalogManager.properties file in the classpath.

  2. Created a catalog.xml with all public ids.

    public class XMLProcessor  {
    
       public void transform(String xmlf, String xslf, String outpath) throws TransformerConfigurationException, TransformerException, org.xml.sax.SAXException, IOException{
    
        org.xml.sax.XMLReader reader = XMLReaderFactory.createXMLReader();
        Transformer transformer = null;
        TransformerFactory factory = TransformerFactory.newInstance();
    
         StreamSource stylesheet = new StreamSource(xslf);
    
            CatalogResolver cr = new CatalogResolver();
            reader.setEntityResolver(cr);
            factory.setURIResolver(cr);
    
            SAXSource source = new SAXSource(reader, new InputSource(xmlf));
    
         transformer = factory.newTransformer(stylesheet);
    
        try {
            transformer.transform(source, new StreamResult(new FileWriter(outpath)));
        } catch (IOException ex) {
            Logger.getLogger(XMLProcessor.class.getName()).log(Level.SEVERE, null, ex);
        }
    
    }
    

    }



来源:https://stackoverflow.com/questions/55325569/when-merging-multiple-xml-files-how-can-i-set-entityresolver-for-child-xml-file

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!