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 itSupraja 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.