d-m*_*man 1 java xslt spring dtd transformation
我有一个使用 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)
Run Code Online (Sandbox Code Playgroud)
长话短说,它试图在我执行应用程序的 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));
}
Run Code Online (Sandbox Code Playgroud)
您的 xml 文件可能包含一个 doctype 声明,其中包含到 dtd 的相对路径:
<!DOCTYPE html SYSTEM "xhtml11-flat.dtd">
Run Code Online (Sandbox Code Playgroud)
转换器 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;
}
}
Run Code Online (Sandbox Code Playgroud)
如何使用此类取决于转换的源类型。对于 aDOMSource您必须配置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));
Run Code Online (Sandbox Code Playgroud)
对于 aSAXSource设置在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));
Run Code Online (Sandbox Code Playgroud)
无论源类型如何,转换代码都是相同的,并且看起来应该与您当前在XmlUtils类中的代码相似:
Templates templates = ...
Result result = new StreamResult(...);
Transformer transformer = templates.newTransformer();
transformer.transform(source, result);
Run Code Online (Sandbox Code Playgroud)