由于xsl:include,转换失败

7

我有一个Java的Maven项目,其中包含XSLT转换。我按照以下方式加载样式表:

TransformerFactory tFactory = TransformerFactory.newInstance();

DocumentBuilderFactory dFactory = DocumentBuilderFactory
                .newInstance();

dFactory.setNamespaceAware(true);

DocumentBuilder dBuilder = dFactory.newDocumentBuilder();

ClassLoader cl = this.getClass().getClassLoader();
java.io.InputStream in = cl.getResourceAsStream("xsl/stylesheet.xsl");

InputSource xslInputSource = new InputSource(in);
Document xslDoc = dBuilder.parse(xslInputSource);

DOMSource xslDomSource = new DOMSource(xslDoc);

Transformer transformer = tFactory.newTransformer(xslDomSource);

stylesheet.xsl中有许多语句。当我尝试运行我的单元测试时,这些语句似乎会引起问题,我会收到以下错误:

C:\Code\workspace\app\dummy.xsl; Line #0; Column #0; Had IO Exception with stylesheet file: footer.xsl
C:\Code\workspace\app\dummy.xsl; Line #0; Column #0; Had IO Exception with stylesheet file: topbar.xsl

XSLT中的include语句是相对链接。
xsl:include href="footer.xsl"
xsl:include href="topbar.xsl"

我尝试了实验并更改成以下内容,但仍然出现错误。

xsl:include href="xsl/footer.xsl"
xsl:include href="xsl/topbar.xsl"

任何想法?非常感谢您的任何帮助。
4个回答

12

使用URIResolver解决了我的问题。

class MyURIResolver implements URIResolver {
@Override
public Source resolve(String href, String base) throws TransformerException {
  try {
    ClassLoader cl = this.getClass().getClassLoader();
    java.io.InputStream in = cl.getResourceAsStream("xsl/" + href);
    InputSource xslInputSource = new InputSource(in);
    Document xslDoc = dBuilder.parse(xslInputSource);
    DOMSource xslDomSource = new DOMSource(xslDoc);
    xslDomSource.setSystemId("xsl/" + href);
    return xslDomSource;
 } catch (...

然后使用TransformerFactory进行赋值

tFactory.setURIResolver(new MyURIResolver());

1
不要忘记设置 documentBuilderFactory.setNamespaceAware(true)。如果没有这样做,可能会阻止父样式表加载子样式表中的任何模板,导致 ElemTemplateElement 错误。 - Xr.
注意,setURIResolver也可以在转换器上设置(而不是工厂),但那时它没有任何效果。 - robert

11

URIResolver也可以以以下更直接的方式使用:

class XsltURIResolver implements URIResolver {

    @Override
    public Source resolve(String href, String base) throws TransformerException {
        try{
              InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("xslts/" + href);
              return new StreamSource(inputStream);
        }
        catch(Exception ex){
            ex.printStackTrace();
            return null;
        }
    }
}

可使用以下代码在TransformerFactory中使用URIResolver:

TransformerFactory transFact = TransformerFactory.newInstance();
transFact.setURIResolver(new XsltURIResolver());

或者使用Lambda表达式:

transFact.setURIResolver((href, base) -> {
    final InputStream s = this.getClass().getClassLoader().getResourceAsStream("xslts/" + href);
    return new StreamSource(s);
});

1

使用EntityResolver设置您的DocumentBuilder对象。

您需要扩展EntityResolver类来解析您的外部实体(footer.xsl和topbar.xsl)。


0

我曾经在 XSLT 中使用相对路径时遇到类似的问题。

如果可以,请尝试在 XSLT 中使用绝对路径 - 这应该可以解决错误。

对于 XSLT 的最终版本来说,绝对路径可能不是首选,但它应该可以解决 maven 问题。也许你可以有两个版本的 XSLT,一个包含maven的绝对路径,另一个包含其他工具的相对路径。


1
Matt,感谢您的回复-这确实解决了问题。但是,样式表包含在jar文件中,因此一旦整个内容被打包起来,这个解决方案将无法使用。 - will

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接