Thursday, May 27, 2010

Working with XSLFO

XSLFO is great.

Create a stand-alone XML file or use XSLT and XML. For testing, the stand-alone file is good. For production, it is better to use XSLT-XML to separate style from data.

Use Apache FOP to access XSLFO. It can be run from the command line or can be used from a Java program.

Download and Verify


Download Apache FOP from the site:
http://xmlgraphics.apache.org/fop/download.html

Use gpg to verify that the file is not corrupt.
Download the KEYS file from the Apache site (not a mirror site).
Import the KEYS into gpg

gpg --import KEYS

Download the file and the associated .asc file. I used the zip version, since I am running on Windows.

gpg --verify fop-xxx.zip.asc fop-xxx.zip

The verification will not be signed, but short of contacting the author, you have done a partial job of verifying the file.

Install


Expand the binary file
The jar file is in the build folder.
The lib file contains additional jars that are needed for embedding into Java.
The fop.bat is the command line front end.

Command line


There are just a few options that are needed.

Data and formatting in one file named file.fo
fop -fo file.fo -pdf file.pdf

Data in xml file, formatting in xslt file.
fop -xml file.xml -xslt file.xslt -pdf file.pdf

For pdf output, the default fop will not recognize all the system fonts. Copy the fop.xconf file into the current folder and modify it to recognize the system fonts.
http://xmlgraphics.apache.org/fop/trunk/fonts.html

<renderers>
<renderer mime="application/pdf">
<fonts>
<!-- automatically detect operating system installed fonts -->
<auto-detect/>
</fonts>
</renderer>
</renderers>

Use the -c option to include the config file

gpg -c fop.xconf -xml name.xml -xslt name2fo.xsl -pdf name.pdf

Embedding in Java


Basic instructions can be found on the Apache FOP site:
http://xmlgraphics.apache.org/fop/0.95/embedding.html

Use a simple transformer if using a stand-alone fo file.

   //without XSLT:
transformer = factory.newTransformer();
...
Source src = new StreamSource(new File("src/currency.fo"));
Add the stylesheet if using XSLT-XML.

   //with XSLT
Source xslt = new StreamSource(new File("src/name2fo.xsl"));
transformer = factory.newTransformer(xslt);
...
Source src = new StreamSource(new File("src/name.xml"));

Main Java method

// 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 = null;
try {
out = new BufferedOutputStream(new FileOutputStream(new File("src/currency.rtf")));
Fop fop;
fop = fopFactory.newFop(MimeConstants.MIME_RTF, out);

// Step 4: Setup JAXP using identity transformer
TransformerFactory factory = TransformerFactory.newInstance();

Transformer transformer; // identity transformer

//without XSLT:
transformer = factory.newTransformer();

//with XSLT:
//Source xslt = new StreamSource(new File("src/name2fo.xsl"));
//transformer = factory.newTransformer(xslt);

// Step 5: Setup input and output for XSLT transformation
// Setup input stream
//without XSLT
Source src = new StreamSource(new File("src/currency.fo"));
//with XSLT
//Source src = new StreamSource(new File("src/name.xml"));

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

// Step 6: Start XSLT transformation and FOP processing
transformer.transform(src, res);


} catch (FileNotFoundException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
} catch (FOPException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
} catch (TransformerConfigurationException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
} finally {
//Clean-up
if (out != null) {
out.close();
}
}

No comments:

Post a Comment

Followers