2008-11-03 14 views
5

Tengo un proyecto Java maven que incluye transformaciones XSLT. Me carga la hoja de estilo de la siguiente manera:Error de transformación debido a 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); 

El stylesheet.xsl tiene una serie de declaraciones. Estos parecen ser la causa de problemas, cuando trato de ejecutar mis pruebas de unidad consigo los siguientes errores:

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 

El incluyen declaraciones en el XSLT son enlaces relativos

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

he intentado experimentar y cambiar estos a lo siguiente - pero aún así obtengo el error.

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

¿Alguna idea? Cualquier ayuda muy apreciada.

Respuesta

11

Resolvió mi problema usando un 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 (... 

y la asignación de esto con el TransformerFactory

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

No olvides establecer 'documentBuilderFactory.setNamespaceAware (true)'. Si no lo hace, puede evitar que la hoja de estilo primaria cargue cualquier plantilla en la hoja de estilos secundaria, lo que da como resultado errores ElemTemplateElement. –

+0

Tenga cuidado, setURIResolver también se puede configurar en el transformador (es decir, en lugar de la fábrica), pero no tiene efecto entonces. – robert

0

Tuve un problema similar a este una vez con las rutas relativas en el XSLT.

Si puede, trate de poner rutas absolutas en el XSLT, eso debería resolver el error.

Una ruta absoluta probablemente no sea preferible para la versión final del XSLT, pero debería superar el problema del experto. Quizás puedas tener dos versiones del XSLT, una con rutas absolutas para maven y otra con rutas relativas para cualquier otra herramienta con la que se esté utilizando.

+1

Matt, gracias por la respuesta, esto soluciona el problema. Sin embargo, las hojas de estilo se incluyen en el archivo jar y, por lo tanto, esta solución no funcionará una vez que todo esté empaquetado. – will

1

Establezca su objeto DocumentBuilder con EntityResolver.

Tendrá que extender la clase EntityResolver para resolver sus entidades externas (footer.xsl y topbar.xsl).

7

URIResolver también se puede utilizar de una manera más sencilla de la siguiente manera:

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

Uso del URIResolver con TransformerFactory como se muestra a continuación:

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

O con una expresión lambda:

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