2010-09-13 13 views
11

ho bisogno di fare una trasformazione XSL usando Apache FOP e ho avuto il codice come questo:Risoluzione percorsi relativi durante il caricamento di file XSLT

//Setup FOP 
Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, out); 
//Setup Transformer 
Source xsltSrc = new StreamSource(new File(xslPath)); 
Transformer transformer = tFactory.newTransformer(xsltSrc); 

//Make sure the XSL transformation's result is piped through to FOP 
Result res = new SAXResult(fop.getDefaultHandler()); 
//Setup input 
Source src = new StreamSource(new File(xmlPath)); 
//Start the transformation and rendering process 
transformer.transform(src, res); 

dove xslPath è il percorso in cui è memorizzato il mio file XSLT.

Ho confermato che funziona quando ho un solo file XSLT, ma nel mio progetto ho diviso le cose in diversi file XSLT e li ho uniti con il tag <xsl:import />. Con questa configurazione, ottengo una NullPointerException perché non capisce tutte le informazioni memorizzate in XSLT perché è distribuita su file diversi.

Mi chiedo se è possibile caricare tutti questi file nella variabile Source xsltSrc in modo che tutte le informazioni XSL siano disponibili.

UPDATE

ho cambiato il codice in base alla risposta data da Mads Hansen, ma ancora non funziona. Devo includere i file slt XSLT nel classpath, quindi carico il file XSLT con ClassLoader. Ho controllato che l'URL abbia il percorso corretto quando si esegue url.toExternalForm(). Questo è il mio nuovo pezzo di codice:

ClassLoader cl = this.getClass().getClassLoader(); 
String systemID = "resources/xslt/myfile.xslt"; 
InputStream in = cl.getResourceAsStream(systemID); 
URL url = cl.getResource(systemID); 
Source source = new StreamSource(in); 
source.setSystemId(url.toExternalForm()); 
transformer = tFactory.newTransformer(source); 

Essa trova e carichi myfile.xslt ma ancora non risolve i percorsi relativi agli altri file XSLT.

Cosa sto sbagliando?

risposta

10

Quando si carica un XSLT come StreamSource e non si imposta una SystemID, il processore non sa "dove" l'XSLT è e non può risolvere i percorsi relativi.

http://www.onjava.com/pub/a/onjava/excerpt/java_xslt_ch5/index.html?page=5

Fornendo un identificatore di sistema come parametro al StreamSource, si sono dice il processore XSLT dove cercare commonFooter.xslt. Senza questo parametro, è possibile riscontrare un errore quando il processore non può risolvere questo URI. La soluzione semplice è quella di chiamata setSystemId() Metodo segue:

// construct a Source that reads from an InputStream 
Source mySrc = new StreamSource(anInputStream); 
// specify a system ID (a String) so the 
// Source can resolve relative URLs 
// that are encountered in XSLT stylesheets 
mySrc.setSystemId(aSystemId); 
+0

grazie per la risposta, ma non sembra risolvere il mio problema, anche se la risposta ha un senso. Ho aggiornato la mia domanda con le mie modifiche nel codice. – Javi

+0

Potrebbe essere necessario ottenere un percorso assoluto per il SystemID. A meno che tu non sappia dove risolverà il percorso relativo "da". Prova a convertire quel percorso relativo in un percorso assoluto con qualcosa di simile: 'String xsltSystemId = new File (systemID) .toURL(). AExternalForm();' o 'String xsltSystemId = new File (relativePath) .getAbsolutePath();' –

+0

grazie , Avevo già pensato e ho verificato che quando eseguo url.toExternalForm() ottiene un percorso assoluto. Ma non so dove sia il problema ora. – Javi

17

Ho appena ricevuto che, una risposta tardiva (testato su FOP 1.0) ------

Tutto ciò che serve è di impostare un resolver uri per la vostra fabbrica, come in seguito a lavori per me:

TransformerFactory transFact = TransformerFactory.newInstance(); 
StreamSource xsltSource = new StreamSource(xsl); 

// XXX for 'xsl:import' to load other xsls from class path 
transFact.setURIResolver(new ClasspathResourceURIResolver()); 
Templates cachedXSLT = transFact.newTemplates(xsltSource); 
Transformer transformer = cachedXSLT.newTransformer(); 


class ClasspathResourceURIResolver implements URIResolver { 
    @Override 
    public Source resolve(String href, String base) throws TransformerException { 
    return new StreamSource(XXX.getClassLoader().getResourceAsStream(href)); 
    } 
} 

e il mio xsl importazione (in modo che il 'imported.xsl' dovrebbe essere nel classpath):

<xsl:import href="META-INF/companybusinesscredit/imported.xsl"/> 
+0

Grazie mille, questo mi ha fatto risparmiare ore. –

2

Sto usando Saxon 9.x e ho ancora avuto problemi quando ho usato il documento all'interno del foglio di stile. Il foglio di stile è stato risolto correttamente ma gli xml raggruppati insieme al foglio di stile nel file jar non si caricava come previsto anche con setSystemId. Ha provocato l'eccezione di file non trovato.Per me è stato più semplice codificare il resolver con il codice seguente:

JarfileResolver jarfileResolver = new JarfileResolver(); 
transformer.setURIResolver(jarfileResolver); 


public class JarfileResolver implements URIResolver 
{ 
    public Source resolve(String fileName, String base) throws TransformerException 
    { 
     URL url = getClass().getClassLoader().getResource(fileName); 
     StreamSource jarFileSS = new StreamSource(); 

     try 
     { 
      InputStream jarfileIS = url.openStream(); 
      jarFileSS.setInputStream(jarfileIS); 
     } 
     catch(IOException ioExp) 
     { 
      throw new TransformerException(ioExp); 
     } 
     return jarFileSS; 
    } 
} 
Problemi correlati