Crear documentos PDF con Java


Utilizaremos el proyecto open source Apache FOP (Formatting Objects Processor) que nos da una serie de funciones para convertir un documento XML a un documento PDF, PS, Texto entre otros.

Este proyecto toma un archivo XSL-FO y lo convierte en formato PDF, por lo que habrá que convertir primero nuestro archivo XML a XSL-FO antes de convertirlo a un documento PDF.

Archivos XML y XSLT

Vamos a crear dos archivos, el primero será en formato xml. En este archivo se guardarán los datos de nuestro documento PDF.

Archivo glossary.xml

<?xml version="1.0"?>
<glossary>
<term-entry>
	<term>basic-link</term>
	<definition>The fo:basic-link is used for representing the start resource
	of a simple link.</definition>
</term-entry>
<term-entry>
	<term>bidi-override</term>
	<definition>The fo:bidi-override inline formatting object is used where
	it is necessary to override the default Unicode-bidirectionality
	algorithm direction for different (or nested) inline scripts in
	mixed-language documents.</definition>
</term-entry>
<term-entry>
	<term>block</term>
	<definition>The fo:block formatting object is commonly used for formatting
	paragraphs, titles, headlines, figure and table captions, etc.</definition>
</term-entry>

Archivo glossary.xslt

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" version="1.0">
<xsl:template match="glossary">
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">

<fo:layout-master-set>
<fo:simple-page-master master-name="all" page-height="11.5in" page-width="8.5in" margin-top="1in" margin-bottom="1in" margin-left="0.75in" margin-right="0.75in">
	<fo:region-body margin-top="1in" margin-bottom="0.75in"/>
	<fo:region-before extent="0.75in"/>
	<fo:region-after extent="0.5in"/>
</fo:simple-page-master>
</fo:layout-master-set>

<fo:page-sequence master-reference="all" format="i">

<fo:static-content flow-name="xsl-region-before">
<fo:block text-align="start" font-size="10pt" font-family="serif" line-height="1em + 2pt">
	<fo:retrieve-marker retrieve-class-name="term" retrieve-boundary="page" retrieve-position="first-starting-within-page"/>
	<fo:leader leader-alignment="reference-area" leader-pattern="dots" leader-length="4in"/>
	<fo:retrieve-marker retrieve-class-name="term" retrieve-boundary="page" retrieve-position="last-ending-within-page"/>
</fo:block>
</fo:static-content> 

<fo:static-content flow-name="xsl-region-after">
<fo:block text-align="start" font-size="10pt" font-family="serif" line-height="1em + 2pt"> Page (<fo:page-number/>)
</fo:block>
</fo:static-content> 

<fo:flow flow-name="xsl-region-body">
<xsl:apply-templates select="term-entry"/>
</fo:flow>

</fo:page-sequence>

</fo:root>
</xsl:template>

<xsl:template match="term-entry">
<fo:block text-align="start" font-size="12pt" font-family="sans-serif">
	<xsl:apply-templates select="term"/>
	<xsl:apply-templates select="definition"/>
</fo:block>
</xsl:template>

<xsl:template match="term">
<fo:block color="blue" space-before.optimum="3pt">
	<fo:marker marker-class-name="term"><xsl:value-of select="."/>
	</fo:marker>
	<xsl:value-of select="."/>
</fo:block>
</xsl:template>

<xsl:template match="definition">
	<fo:block text-align="start" start-indent="2em">
	<xsl:value-of select="."/>
	</fo:block>
</xsl:template>

</xsl:stylesheet>

Convertir documento XML a XSL-FO

El proyecto Apache FOP incluye las librerías: FOP, Logger, Graphics, Xerces, XML y XSLT.

De esta manera declaramos las librerías:

import org.apache.avalon.framework.logger.*;
import org.apache.fop.apps.*;
import org.xml.sax.InputSource;
import org.xml.sax.*;
import org.w3c.dom.*;
public void generarXSLFO(File archivoXML, File archivoXSLT)
{
	try {
		System.setProperty("javax.xml.parsers.DocumentBuilderFactory", "org.apache.xerces.jaxp.DocumentBuilderFactoryImpl");
		System.setProperty("javax.xml.transform.TransformerFactory", "org.apache.xalan.processor.TransformerFactoryImpl");

		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder = factory.newDocumentBuilder();
		Document documento = builder.parse(archivoXML);

		TransformerFactory tFactory = TransformerFactory.newInstance();
		StreamSource stylesource = new StreamSource(archivoXSLT);

		Transformer transformer = tFactory.newTransformer(stylesource);
		DOMSource source = new DOMSource(documento);

		StreamResult result = new StreamResult("glossary.fo");
		transformer.transform(source, result);

	} catch (TransformerConfigurationException e) {
		System.out.println(e.getMessage());
	} catch (TransformerException e) {
		System.out.println(e.getMessage());
	} catch (SAXException e) {
		System.out.println(e.getMessage());
	} catch (ParserConfigurationException e) {
		System.out.println(e.getMessage());
	} catch (IOException e) {
		System.out.println(e.getMessage());
	}
}

Generar documento PDF

Una vez generados el archivo glossary.fo, podemos generar nuestro documento PDF.

public void generarPDF()
{
	try {
		Driver driver = new Driver();
		Logger logger = new ConsoleLogger(ConsoleLogger.LEVEL_INFO);
		driver.setLogger(logger);
		org.apache.fop.messaging.MessageHandler.setScreenLogger(logger);
		driver.setRenderer(Driver.RENDER_PDF);

		InputStream input = new FileInputStream(new File("glossary.fo"));
		driver.setInputSource(new InputSource(input));

		OutputStream output = new FileOutputStream(new File("glossary.pdf"));
		driver.setOutputStream(output);

		driver.run();
		output.flush();
		output.close();

	} catch (IOException e) {
		System.out.println(e.getMessage());
	} catch (org.apache.fop.apps.FOPException e) {
		System.out.println(e.getMessage());
	}
}

Código Completo

Código del archivo ConvertirPDF.java

package org.luisalberto.xml2pdf;

import java.io.*;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.*;
import javax.xml.transform.stream.*;

import org.apache.avalon.framework.logger.*;
import org.apache.fop.apps.*;
import org.xml.sax.InputSource;
import org.xml.sax.*;
import org.w3c.dom.*;

public class ConvertirPDF
{
	public void generarXSLFO(File archivoXML, File archivoXSLT)
	{
		try {
			System.setProperty("javax.xml.parsers.DocumentBuilderFactory", "org.apache.xerces.jaxp.DocumentBuilderFactoryImpl");
			System.setProperty("javax.xml.transform.TransformerFactory", "org.apache.xalan.processor.TransformerFactoryImpl");

			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
			DocumentBuilder builder = factory.newDocumentBuilder();
			Document documento = builder.parse(archivoXML);

			TransformerFactory tFactory = TransformerFactory.newInstance();
			StreamSource stylesource = new StreamSource(archivoXSLT);

			Transformer transformer = tFactory.newTransformer(stylesource);
			DOMSource source = new DOMSource(documento);

			StreamResult result = new StreamResult("glossary.fo");
			transformer.transform(source, result);

		} catch (TransformerConfigurationException e) {
			System.out.println(e.getMessage());

		} catch (TransformerException e) {
			System.out.println(e.getMessage());

		} catch (SAXException e) {
			System.out.println(e.getMessage());

		} catch (ParserConfigurationException e) {
			System.out.println(e.getMessage());

		} catch (IOException e) {
			System.out.println(e.getMessage());
		}
	}

	public void generarPDF()
	{
		try {
			Driver driver = new Driver();
			Logger logger = new ConsoleLogger(ConsoleLogger.LEVEL_INFO);
			driver.setLogger(logger);
			org.apache.fop.messaging.MessageHandler.setScreenLogger(logger);
			driver.setRenderer(Driver.RENDER_PDF);

			InputStream input = new FileInputStream(new File("glossary.fo"));
			driver.setInputSource(new InputSource(input));

			OutputStream output = new FileOutputStream(new File("glossary.pdf"));
			driver.setOutputStream(output);

			driver.run();
			output.flush();
			output.close();

		} catch (IOException e) {
		} catch (org.apache.fop.apps.FOPException e) {
			System.out.println(e.getMessage());
		}
	}
}

Código del archivo Test.java

package org.luisalberto.xml2pdf;

import java.io.*;

import org.luisalberto.xml2pdf.ConvertirPDF;

public class Test
{
	public static void main(String[] argv)
	{
		ConvertirPDF xmlPDF= new ConvertirPDF();
		File archivoXML = new File("glossary.xml");
		File archivoXSLT = new File("glossary.xslt");

		xmlPDF.generarXSLFO(archivoXML, archivoXSLT);
		xmlPDF.generarPDF();
	}
}

Posted in

Leave a Reply