2008-11-03 7 views
5

Ich habe ein Java Maven-Projekt, das XSLT-Transformationen enthält. Ich lade das Stylesheet wie folgt:Umwandlung fehlgeschlagen wegen xsl: include

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

Die stylesheet.xsl hat eine Reihe von Anweisungen. Diese scheinen, Probleme zu verursachen, wenn ich versuche, meine Unit-Tests zu laufen bekomme ich folgende Fehler:

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 

Die include-Anweisungen in der XSLT sind relative Links

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

ich versucht habe, zu experimentieren und zu ändern diese zu den folgenden - aber ich bekomme immer noch den Fehler.

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

Irgendwelche Ideen? Jede Hilfe wird sehr geschätzt.

Antwort

11

Mein Problem mit einem URIResolver gelöst.

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 (... 

Und die

tFactory.setURIResolver(new MyURIResolver()); 
+0

Vergessen Sie nicht, 'documentBuilderFactory.setNamespaceAware (true)' zu setzen. Andernfalls kann das übergeordnete Stylesheet verhindern, dass die Vorlage in Ihrem untergeordneten Stylesheet geladen wird, was zu ElemTemplateElement-Fehlern führt. –

+0

Achtung, setURIResolver kann auch auf den Transformator gesetzt werden (d. H. Statt auf die Fabrik), hat aber keine Wirkung. – robert

0

Ich hatte ein ähnliches Problem mit relativen Pfaden in der XSLT.

Wenn Sie können, versuchen Sie absolute Pfade in die XSLT zu setzen - das sollte den Fehler beheben.

Ein absoluter Pfad ist wahrscheinlich nicht für die endgültige Version des XSLT vorzuziehen, aber es sollte Sie über das Maven-Problem hinaus bringen. Vielleicht können Sie zwei Versionen der XSLT haben, eine mit absoluten Pfaden für Maven und eine mit relativen Pfaden für jedes andere Werkzeug, mit dem sie benutzt wird.

+1

Matt, Danke für die Antwort - das behebt das Problem. Die Stylesheets sind jedoch in der JAR-Datei enthalten, so dass diese Lösung nicht funktioniert, sobald das Ganze verpackt ist. – will

1

Legen Sie Ihr DocumentBuilder-Objekt mit einem EntityResolver fest.

Sie müssen die EntityResolver-Klasse erweitern, um Ihre externen Entitäten aufzulösen (footer.xsl und topbar.xsl).

7

URIResolver kann auch, wie unten in einfacher Art und Weise verwendet werden, mit dem TransformerFactory Zuweisen:

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; 
     } 
    } 
} 

Verwenden Sie die URIResolver mit TransformerFactory wie unten dargestellt:

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

Oder mit einem Lambda-Ausdruck:

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