0
votes

Generating PDF using fop and XSL when having URLS in XSLT

I am generating PDF using FOP 2.0 and XSLT. Here i am getting XSL from web url. my one XSL URL is including and importing other urls of XSLs. If its a single XSL I could able to generate PDF. If i have multiple URLS in one XSLT on Web . The FOP is not able to Connect automatically to other URLS[ Example of using XSLTS]


xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" \

xmlns:fo="http://www.w3.org/1999/XSL/Format" version="1.0">

<xsl:include href="abc.xsl"/> 

<xsl:include href="xyz.xsl"/>

<xsl:include href="wgh.xsl"/>

This is the way Its including XSLs in one XSLs. In this Case my FOP is not redirecting to those xsls and couldn't able to generate PDF

ERROR:

SystemId Unknown; Line #3; Column #34; Had IO Exception with stylesheet file: header.xsl SystemId Unknown; Line #4; Column #34; Had IO Exception with stylesheet file: footer.xsl SystemId Unknown; Line #5; Column #36; Had IO Exception with stylesheet file: mainbody.xsl SystemId Unknown; Line #6; Column #41; Had IO Exception with stylesheet file: secondarybody.xsl SystemId Unknown; Line #10; Column #38; org.xml.sax.SAXException: ElemTemplateElement error: layout javax.xml.transform.TransformerException: ElemTemplateElement error: layout 13:58:27.326 [http-nio-auto-1-exec-2] DEBUG org.apache.fop.fo.FOTreeBuilder - Building formatting object tree SystemId Unknown; Line #10; Column #38; Could not find template named: layout

Code for PDF Generator:

public class PdfGenerator {

private static final Logger LOG=LoggerFactory.getLogger(PdfGenerator.class);

public List<OutputStream>  generatePdfs(List<Content> xmlList, int reqestListSize,String xslPath)

{ try {

    List<OutputStream> pdfOutputStreams= new ArrayList();   

    for(int p = 0; p <reqestListSize; p++) {

        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        String jaxbType = "com.abc.model"; // model package
        JAXBContext context = JAXBContext.newInstance(jaxbType);  
        Marshaller marshaller = context.createMarshaller();
        marshaller.setProperty("jaxb.formatted.output",Boolean.TRUE);
        marshaller.marshal(xmlList.get(p),bos);
        ByteArrayInputStream inStream = new ByteArrayInputStream(bos.toByteArray());                
        StreamSource xmlSource = new StreamSource(inStream);                
        // create an instance of fop factory
        FopFactory fopFactory = FopFactory.newInstance(new File(".").toURI());
        // a user agent is needed for transformation
        FOUserAgent foUserAgent = fopFactory.newFOUserAgent();

        ByteArrayOutputStream tempOutputStream = new ByteArrayOutputStream();
        Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, tempOutputStream);
        pdfOutputStreams.add(p, tempOutputStream);      
        // Setup XSLT
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        URL url = new URL(xslPath);
        InputStream xslFile = url.openStream();  (   **http://home.www.test.com/abc_web/xsl/test.xsl**  ( Using an url to get XSLT. faild loading due to XSL :include) )
        StreamSource xsltStreamSource = new StreamSource(xslFile);
        Transformer transformer = transformerFactory.newTransformer(xsltStreamSource);  
        Result res = new SAXResult(fop.getDefaultHandler());    
        // Start XSLT transformation and FOP processing
        // That's where the XML is first transformed to XSL-FO and then 
        // PDF is created      
        transformer.transform(xmlSource, res);
    }
    return pdfOutputStreams;

    }catch(Exception ex) {
        LOG.error("Error", ex);
        return new ArrayList();
    }
1
Do you write Java code to run Apache FOP? Then show us the relevant code. Also tells us the exact error messages. - Martin Honnen
Note that FOP really comes into play to process the result of the XSLT transformation; before that, it's the XSLT processor that is working. - lfurini
@MartinHonnen I have added the part of logic and errors could you please look into it - Supraja reddy
Does it not suffice and avoid the problem if you directly use StreamSource xsltStreamSource = new StreamSource(xslPath);? - Martin Honnen
Thanks @MartinHonnen Its Working. you made my day :) - Supraja reddy

1 Answers

0
votes

Simply replace

URL url = new URL(xslPath);
InputStream xslFile = url.openStream();
StreamSource xsltStreamSource = new StreamSource(xslFile);

with

StreamSource xsltStreamSource = new StreamSource(xslPath);

and the XSLT processor should be able to resolve any relative imports or includes.

Or you would need to explicitly set the SystemId on your xsltStreamSource. But the single line I have suggested should do the job just fine.