java - spring - xsl 转换 dtd 未找到错误

标签 java spring xslt transformation dtd

我有一个使用 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));
}

最佳答案

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

<!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);

关于java - spring - xsl 转换 dtd 未找到错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13975222/

相关文章:

java - 在 Spring 中的 Preauthorize 表达式中使用 Autowired bean

java - Spring Hibernate查询与非主键的一对一关系

java - 如何从运行在服务器外部(Web 应用程序)的 Spring hibernate 项目中使用 JBoss AS7 JNDI 数据源?

c# - 使用 XslCompiledTransform 去除空白

java - 用于向soap xml 添加一个新标签的 XSL 文件

java - Eclipse java项目突然停止工作

java - Web 服务器在 Android 中不工作

xml - xslt 显示前 5 个总和

Java:优化/提高 DFS 中的运行速度

java - Google App Engine的自定义异常(exception)消息格式-Java