I need to do an XSL transformation using Apache FOP and I had code like this:
//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);
where xslPath
is the path where my XSLT file is stored.
I have confirmed that it works when I have only one XSLT file, but in my project I have divided things into several XSLT files and joined them with the <xsl:import />
tag. With this configuration, I get a NullPointerException because it doesn't understand all the information stored in XSLT because it's distributed over different files.
I wonder if there's any way to load all these files in the Source xsltSrc
variable so all the XSL information is available.
UPDATE
I've changed the code based on the answer given by Mads Hansen, but it still doesn't work. I have to include the XSLT slt files in the classpath, so I load the XSLT file with ClassLoader. I've checked that the URL has the correct path when executing url.toExternalForm()
. This is my new piece of 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);
It finds and loads myfile.xslt
but it still doesn't resolve the relative paths to the other XSLT files.
What am I doing wrong?
I'm using Saxon 9.x and still had issues when I used document within the stylesheet. The stylesheet was correctly resolved but the xmls bundled along with the stylesheet in the jar file didn't load as expected even with setSystemId. It resulted in file not found exception. It was easier for me to custom code the resolver with the code below:
When you load an XSLT as a StreamSource and do not set a SystemID, the processor doesn't know "where" the XSLT is and cannot resolve relative paths.
http://www.onjava.com/pub/a/onjava/excerpt/java_xslt_ch5/index.html?page=5
I just got it, a late answer(tested on FOP 1.0) ------
All you need is to set an uri resolver for your factory, as following works for me:
and my importing xsl(so the 'imported.xsl' should be in the classpath):