【问题标题】:java - spring - xsl transformation dtd not found errorjava - spring - xsl 转换 dtd 未找到错误
【发布时间】:2019-03-12 17:20:07
【问题描述】:

我有一个使用 xsl 转换 xml 文件的代码,我的代码如下。我的问题是当我运行执行点时,它给了我以下错误。

StackTrace: javax.xml.transform.TransformerException: javax.xml.transform.TransformerException: com.sun.org.apache.xml.internal.utils.WrappedRuntimeException: /home/app/myapp/bin/xhtml11-flat.dtd (No such file or directory)
    at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:720)
    at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl.transform(TransformerImpl.java:313)
    at com.core.util.XmlUtils.transform(XmlUtils.java:151)
    at com.core.util.XmlUtils.transform(XmlUtils.java:147)

长话短说,它试图在我执行应用程序的 bin 目录中找到 dtd 文件。

/home/app/myapp/bin/xhtml11-flat.dtd

我有 xhtml11-flat.dtd 文件,如果我将此文件复制到 bin 目录中它可以正常工作,而不是 bin 目录我想从类路径加载它知道如何以最少的更改实现这一点吗? 我不知道从哪里加载 .dtd 代码,以便我可以在其中设置路径。

//Execution Point
function transform(){
    Templates templates = getTemplates();
    StringWriter result = new StringWriter();
    XmlUtils.transform(templates.newTransformer(), input, new StreamResult(result));

    ...
}

private Templates getTemplates() throws Exception {
    if (templates == null) {
        templates = XmlUtils.createTemplates(XslRdcSourceDocTransformer.class.getResourceAsStream("/xsl/" + getXslFileName()));
    }
    return templates;
}


public static Templates createTemplates(InputStream stream) throws Exception {
    TransformerFactory tfactory = TransformerFactory.newInstance();
    return tfactory.newTemplates(new StreamSource(stream));
}

【问题讨论】:

    标签: java spring xslt transformation dtd


    【解决方案1】:

    您的 xml 文件可能包含一个 doctype 声明,其中包含 dtd 的相对路径:

    <!DOCTYPE html SYSTEM "xhtml11-flat.dtd">
    

    transformer api 尝试将此路径解析为 java 程序的当前工作目录。要自定义路径的解析方式,您需要实现EntityResolver。这个EntityResolver 可以返回一个InputSource 引用从类路径加载的dtd 的副本。

    public InputSource resolveEntity(final String publicId, final String systemId) throws SAXException {
        if ("xhtml11-flat.dtd".equals(systemId)) {
            ClassLoader cl = Thread.currentThread().getContextClassLoader();
            InputSource is = new InputSource();
            is.setSystemId(systemId);
            is.setByteStream(cl.getResourceAsStream("/com/example/dtd/xhtml11-flat.dtd"));
            return is;
        } else {
            return null;
        }
    }
    

    如何使用此类取决于转换的源类型。对于DOMSource,您必须配置DocumentBuilder

    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    factory.setValidating(false);
    factory.setNamespaceAware(true);
    
    DocumentBuilder builder = factory.newDocumentBuilder();
    DocumentBuilder builder = ...
    builder.setEntityResolver(entityResolver);
    
    Source source = new DOMSource(builder.parse(inputStream));
    

    对于SAXSource,设置在XMLReader 实例上:

    SAXParserFactory factory1 = SAXParserFactory.newInstance();
    factory1.setValidating(false);
    factory1.setNamespaceAware(true);
    
    SAXParser parser = factory1.newSAXParser();
    XMLReader xmlreader = parser.getXMLReader();
    xmlreader.setEntityResolver(entityResolver);
    
    Source source = new SAXSource(xmlreader, new InputSource(stream));
    

    无论源类型如何,转换的代码都是相同的,并且应该与您当前在 XmlUtils 类中的代码相似:

    Templates templates = ...
    Result result = new StreamResult(...);
    Transformer transformer = templates.newTransformer();
    transformer.transform(source, result);
    

    【讨论】:

    • 感谢您的回答,您能告诉我如何将 DomSource 与变换方法相匹配。
    • @Faisalkhan:我添加了 SAXSource 和转换本身的示例,代码应该与您的 XmlUtils 类中的代码类似。
    • 非常感谢,您帮我解决了关键问题
    • 我得到 StackTrace: org.xml.sax.SAXParseException: Premature end of file。在 com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:239) 在 com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:283)
    • 我得到 StackTrace: org.xml.sax.SAXParseException: Premature end of file。在 com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:239) 在 com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:283)
    猜你喜欢
    • 2021-10-08
    • 1970-01-01
    • 2016-07-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-18
    • 2019-07-01
    • 1970-01-01
    相关资源
    最近更新 更多