2010-09-13 15 views
11

Ich brauche eine XSL-Transformation mit Apache FOP zu tun, und ich hatte Code wie folgt:um relative Pfade als XSLT-Dateien laden

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

wo xslPath der Pfad ist, wo meine XSLT-Datei gespeichert wird.

Ich habe bestätigt, dass es funktioniert, wenn ich nur eine XSLT-Datei habe, aber in meinem Projekt habe ich Dinge in mehrere XSLT-Dateien unterteilt und sie mit dem <xsl:import />-Tag verbunden. Mit dieser Konfiguration erhalte ich eine NullPointerException, weil sie nicht alle in XSLT gespeicherten Informationen versteht, da sie über verschiedene Dateien verteilt sind.

Ich frage mich, ob es eine Möglichkeit gibt, alle diese Dateien in der Source xsltSrc Variable zu laden, so dass alle XSL-Informationen verfügbar sind.

UPDATE

Ich habe das auf der von Mads Hansen gegebenen Antwort basierten Code geändert, aber es funktioniert immer noch nicht. Ich muss die XSLT-SLT-Dateien in den Klassenpfad einbeziehen, also lade ich die XSLT-Datei mit ClassLoader. Ich habe überprüft, dass die URL den richtigen Pfad bei der Ausführung url.toExternalForm() hat. Das ist mein neues Stück Code:

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

Es findet und lädt myfile.xslt es gibt aber noch nicht die relativen Pfade zu den anderen XSLT-Dateien zu beheben.

Was mache ich falsch?

Antwort

10

Wenn Sie eine XSLT als Stream und nicht setzen einen SystemID laden, der Prozessor nicht weiß „wo“ die XSLT und auflösen kann nicht relative Pfade.

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

Durch eine Systemkennung als Parameter an die Stream Bereitstellung, sind Sie den XSLT-Prozessor zu sagen, wo zu sucht commonFooter.xslt. Ohne diesem Parameter kann ein Fehler auftreten, wenn der Prozessor diesen URI nicht beheben kann. Die einfache Lösung ist es, Aufruf der setSystemId() -Methode wie folgt:

// 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

danke für deine Antwort, aber es scheint mein Problem nicht zu lösen, obwohl deine Antwort sinnvoll ist. Ich habe meine Frage mit meinen Änderungen im Code aktualisiert. – Javi

+0

Möglicherweise müssen Sie einen absoluten Pfad für Ihre SystemID ermitteln. Es sei denn, Sie wissen, wo es den relativen Pfad "von" auflösen wird. Versuchen Sie, diesen relativen Pfad in einen absoluten Pfad umzuwandeln, etwa wie folgt: 'String xsltSystemId = neue Datei (systemID) .toURL() .toExternalForm();' oder 'String xsltSystemId = neue Datei (relativePath) .getAbsolutePath();' –

+0

thanks Ich hatte das schon und ich hatte das überprüft. Wenn ich url.toExternalForm() mache, bekommt es einen absoluten Pfad. Aber ich weiß nicht, wo das Problem jetzt ist. – Javi

17

ich es nur bekam, eine späte Antwort (auf FOP getestet 1.0) ------

Alle Sie brauchen, sind ein uri-Resolver für die Fabrik zu setzen, wie funktioniert bei mir folgenden:

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

und mein Import xsl (so die ‚imported.xsl‘ sollte in der classpath):

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

Vielen Dank, das hat mir Stunden gespart. –

2

Ich verwende Saxon 9.x und hatte immer noch Probleme, wenn ich das Dokument innerhalb des Stylesheets verwendete. Das Stylesheet wurde korrekt aufgelöst, aber die Xmls, die zusammen mit dem Stylesheet in der JAR-Datei enthalten sind, wurden auch mit setSystemId nicht wie erwartet geladen. Es resultierte in Datei nicht gefunden Ausnahme.Es war einfacher für mich, den Resolver mit dem unten stehenden Code zu codieren: