简体   繁体   中英

How to print array in pdf using xsl FO

I have a collection of objects which i want to print to pdf in a templated format. I have tried to print the collection as PDF using the code below, but i do not see any text rendered in PDF after file is created.

The java code is as follows:

FopFactory fopFactory = FopFactory.newInstance();
OutputStream out = new BufferedOutputStream(new FileOutputStream(new File("/home/myfile.pdf")));
try {
Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, out);
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer(); 
    Eden[] ed=new Eden[3];
    for(int i=0;i<ed.length;i++)
    {
        ed[i]=new Eden();
    ed[i].setBlow(String.valueOf(i));
    }
Source src = new StreamSource(new File("/home/tables.fo"));
Result res = new SAXResult(fop.getDefaultHandler());
transformer.setParameter("dep", ed);
transformer.transform(src, res);
} finally {
out.close();
}

The fo file is as follows:

<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" 
 xmlns:xsl="http://www.w3.org    /1999/XSL/Transform">
   <fo:layout-master-set>
    <fo:simple-page-master master-name="my-page">
  <fo:region-body margin="0.5in"/>
</fo:simple-page-master>
 </fo:layout-master-set>
  <fo:page-sequence master-reference="my-page">
 <fo:flow flow-name="xsl-region-body" font="7pt Times">
    <fo:block border="thin solid black" text-align="center">
    <xsl:for-each select="dep">
        {$blow}
    </xsl:for-each>
</fo:block>
 </fo:flow>
  </fo:page-sequence>
</fo:root>

There is no way to output values using XSL- (ormatting) (bjects). (格式化) (对象)输出值。 The example you're using does not in fact do an XSLT transformation which is required to be able to pass values to your stylesheet.

The following code will do what you want, the only difference from your code being the XSLT transformation:

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.FileOutputStream;

import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.stream.StreamSource;

import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.Fop;
import org.apache.fop.apps.FopFactory;
import org.apache.fop.apps.MimeConstants;


public class test {

    public static void main(String[] args) throws FOPException, TransformerException, IOException 
    {
    /*..*/

     // Step 1: Construct a FopFactory
     // (reuse if you plan to render multiple documents!)
     FopFactory fopFactory = FopFactory.newInstance();

     // Step 2: Set up output stream.
     // Note: Using BufferedOutputStream for performance reasons (helpful with FileOutputStreams).
     OutputStream out = new BufferedOutputStream(new FileOutputStream(new File("F:/myfile.pdf")));

     try 
     {
        // Step 3: Construct fop with desired output format
        Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, out);

        // Step 5: Setup input and output for XSLT transformation
        // Setup input stream

        Source xsltSource = new StreamSource(new File("F:/myfile.xsl"));
        TransformerFactory transformerFactory = TransformerFactory.newInstance();
        Transformer transformer = transformerFactory.newTransformer(xsltSource);

        int[] array = {1,2,3};
        transformer.setParameter("test", "1234");
        transformer.setParameter("testRaw", array);

        // Resulting SAX events (the generated FO) must be piped through to FOP
        Result res = new SAXResult(fop.getDefaultHandler());

        transformer.transform(xsltSource, res);

     } 
     finally 
     {
         out.close();
     }
    }

}

Now, to use the parameter in your XSL stylesheet (myfile.xsl for me), it will have to look like the following:

<xsl:stylesheet version="2.0" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:param name="test"/>
    <xsl:param name="testRaw"/>
    <xsl:template match="/">
        <fo:root>
           <fo:layout-master-set>
            <fo:simple-page-master master-name="my-page">
          <fo:region-body margin="0.5in"/>
        </fo:simple-page-master>
         </fo:layout-master-set>
          <fo:page-sequence master-reference="my-page">
         <fo:flow flow-name="xsl-region-body" font="7pt Times">
            <fo:block border="thin solid black" text-align="center">
                <xsl:value-of select="$test"/>
            </fo:block>
            <fo:block break-before="page" border="thin solid black" text-align="center">
                <xsl:value-of select="$testRaw"/>
            </fo:block>
         </fo:flow>
          </fo:page-sequence>
        </fo:root>
    </xsl:template>
</xsl:stylesheet>

This stylesheet defines two parameters: "test" and "testRaw", which are both output to two separate pages. To do this, you use <xsl:value-of select="$paramName"/> .

In the code I posted, the two values were a string and an array of int. PLEASE NOTE: You will NOT be able to just pass any class to a stylesheet and expect the XSL transformer to know about it. This will not work. Usually, parameters passed to a stylesheet are considered string values. If you pass anything else, you need to make sure your stylesheet and transformer can actually handle it.

Run the code on your machine and have a look at what's written to the second page: It's just gibberish, since the stylesheet and transformer cannot process an array of int. If you really need to process data from a custom class, I'd suggest passing the values you really need to the stylesheet as (concatenated) strings.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM