Come si crea un PDF da XML in Java?
Domanda
Al momento, sto creando un file XML in Java e lo sto visualizzando in una pagina JSP trasformandolo con XSL / XSLT. Ora devo prendere quel file XML e visualizzare le stesse informazioni in un PDF. C'è un modo per farlo usando una specie di file XSL?
Ho visto la libreria iText Java, ma non riesco a trovare alcun modo per usarlo con XML e un foglio di stile.
Qualsiasi aiuto sarebbe molto apprezzato. Grazie in anticipo!
Soluzione
Puoi usare oggetti di formattazione XSL. Ecco alcuni buoni articoli su come farlo:
Altri suggerimenti
A - Spiegazione
Dovresti utilizzare il Apache FOP per generare output pdf . Fornisci semplicemente i dati in formato xml e rendi la pagina con un file xsl-fo e specifichi parametri come margine , layout di pagina in questo file xsl-fo .
Fornirò una semplice demo, utilizzo lo strumento di costruzione maven per raccogliere i file jar necessari. Si noti che alla fine della pagina è presente una grafica svg incorporata in pdf. Voglio anche dimostrare che puoi incorporare la grafica svg in pdf.
B - Dati di input XML di esempio
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="application/xml"?>
<users-data>
<header-section>
<data-type id="019">User Bill Data</data-type>
<process-date>Thursday December 9 2016 00:04:29</process-date>
</header-section>
<user-bill-data>
<full-name>John Doe</full-name>
<postal-code>34239</postal-code>
<national-id>123AD329248</national-id>
<price>17.84</price>
</user-bill-data>
<user-bill-data>
<full-name>Michael Doe</full-name>
<postal-code>54823</postal-code>
<national-id>942KFDSCW322</national-id>
<price>34.50</price>
</user-bill-data>
<user-bill-data>
<full-name>Jane Brown</full-name>
<postal-code>66742</postal-code>
<national-id>ABDD324KKD8</national-id>
<price>69.36</price>
</user-bill-data>
</users-data>
C - Il modello XSL-FO
<?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:output encoding="UTF-8" indent="yes" method="xml" standalone="no" omit-xml-declaration="no"/>
<xsl:template match="users-data">
<fo:root language="EN">
<fo:layout-master-set>
<fo:simple-page-master master-name="A4-portrail" page-height="297mm" page-width="210mm" margin-top="5mm" margin-bottom="5mm" margin-left="5mm" margin-right="5mm">
<fo:region-body margin-top="25mm" margin-bottom="20mm"/>
<fo:region-before region-name="xsl-region-before" extent="25mm" display-align="before" precedence="true"/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="A4-portrail">
<fo:static-content flow-name="xsl-region-before">
<fo:table table-layout="fixed" width="100%" font-size="10pt" border-color="black" border-width="0.4mm" border-style="solid">
<fo:table-column column-width="proportional-column-width(20)"/>
<fo:table-column column-width="proportional-column-width(45)"/>
<fo:table-column column-width="proportional-column-width(20)"/>
<fo:table-body>
<fo:table-row>
<fo:table-cell text-align="left" display-align="center" padding-left="2mm">
<fo:block>
Bill Id:<xsl:value-of select="header-section/data-type/@id"/>
, Date: <xsl:value-of select="header-section/process-date"/>
</fo:block>
</fo:table-cell>
<fo:table-cell text-align="center" display-align="center">
<fo:block font-size="150%">
<fo:basic-link external-destination="http://www.example.com">XXX COMPANY</fo:basic-link>
</fo:block>
<fo:block space-before="3mm"/>
</fo:table-cell>
<fo:table-cell text-align="right" display-align="center" padding-right="2mm">
<fo:block>
<xsl:value-of select="data-type"/>
</fo:block>
<fo:block display-align="before" space-before="6mm">Page <fo:page-number/> of <fo:page-number-citation ref-id="end-of-document"/>
</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>
</fo:static-content>
<fo:flow flow-name="xsl-region-body" border-collapse="collapse" reference-orientation="0">
<fo:block>MONTHLY BILL REPORT</fo:block>
<fo:table table-layout="fixed" width="100%" font-size="10pt" border-color="black" border-width="0.35mm" border-style="solid" text-align="center" display-align="center" space-after="5mm">
<fo:table-column column-width="proportional-column-width(20)"/>
<fo:table-column column-width="proportional-column-width(30)"/>
<fo:table-column column-width="proportional-column-width(25)"/>
<fo:table-column column-width="proportional-column-width(50)"/>
<fo:table-body font-size="95%">
<fo:table-row height="8mm">
<fo:table-cell>
<fo:block>Full Name</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block>Postal Code</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block>National ID</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block>Payment</fo:block>
</fo:table-cell>
</fo:table-row>
<xsl:for-each select="user-bill-data">
<fo:table-row>
<fo:table-cell>
<fo:block>
<xsl:value-of select="full-name"/>
</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block>
<xsl:value-of select="postal-code"/>
</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block>
<xsl:value-of select="national-id"/>
</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block>
<xsl:value-of select="price"/>
</fo:block>
</fo:table-cell>
</fo:table-row>
</xsl:for-each>
</fo:table-body>
</fo:table>
<fo:block id="end-of-document">
<fo:instream-foreign-object>
<svg width="200mm" height="150mm" version="1.1" xmlns="http://www.w3.org/2000/svg">
<path d="M153 334
C153 334 151 334 151 334
C151 339 153 344 156 344
C164 344 171 339 171 334
C171 322 164 314 156 314
C142 314 131 322 131 334
C131 350 142 364 156 364
C175 364 191 350 191 334
C191 311 175 294 156 294
C131 294 111 311 111 334
C111 361 131 384 156 384
C186 384 211 361 211 334
C211 300 186 274 156 274" style="fill:yellow;stroke:red;stroke-width:2"/>
</svg>
</fo:instream-foreign-object>
</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
</xsl:stylesheet>
D - Struttura della directory di progetto
E - File Pom
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.levent.fopdemo</groupId>
<artifactId>apache-fop-demo</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>apache-fop-demo</name>
<url>http://maven.apache.org</url>
<properties>
<fop.version>2.1</fop.version>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.apache.xmlgraphics/fop -->
<dependency>
<groupId>org.apache.xmlgraphics</groupId>
<artifactId>fop</artifactId>
<version>${fop.version}</version>
</dependency>
</dependencies>
<build>
<finalName>Apache Fop Demo</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
F - Codice demo: PdfGenerationDemo.java
package com.levent.fopdemo;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import javax.xml.transform.Result;
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.FOUserAgent;
import org.apache.fop.apps.Fop;
import org.apache.fop.apps.FopFactory;
import org.apache.fop.apps.MimeConstants;
public class PdfGenerationDemo
{
public static final String RESOURCES_DIR;
public static final String OUTPUT_DIR;
static {
RESOURCES_DIR = "src//main//resources//";
OUTPUT_DIR = "src//main//resources//output//";
}
public static void main( String[] args )
{
try {
convertToPDF();
} catch (FOPException | IOException | TransformerException e) {
e.printStackTrace();
}
}
public static void convertToPDF() throws IOException, FOPException, TransformerException {
// the XSL FO file
File xsltFile = new File(RESOURCES_DIR + "//template.xsl");
// the XML file which provides the input
StreamSource xmlSource = new StreamSource(new File(RESOURCES_DIR + "//data.xml"));
// create an instance of fop factory
FopFactory fopFactory = FopFactory.newInstance(new File(".").toURI());
// a user agent is needed for transformation
FOUserAgent foUserAgent = fopFactory.newFOUserAgent();
// Setup output
OutputStream out;
out = new java.io.FileOutputStream(OUTPUT_DIR + "//output.pdf");
try {
// Construct fop with desired output format
Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, out);
// Setup XSLT
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer(new StreamSource(xsltFile));
// Resulting SAX events (the generated FO) must be piped through to
// FOP
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);
} finally {
out.close();
}
}
}
G - Output di esempio: output.pdf
Puoi anche controllare il progetto apache qui
BIRT ha una GUI per Eclipse che ti consente di definire il PDF da XML, DB , CSV, ecc. Ecc.
Potresti voler guardare le librerie XSL-FO che sono là fuori che possono fare la creazione di PDF come trasformazione. Proverò a trovare un link.
Prova il progetto xhtmlrenderer . Vedi l'articolo " Generazione di PDF per divertimento e profitto con Flying Saucer e iText " ;.
Puoi applicare XSL-Fo al tuo XML e trasformarlo con il trasformatore Java:
File xmlfile = new File(baseDir, xml);
File xsltfile = new File(baseDir, xsl);
File pdffile = new File(outDir, "ResultXMLPDF.pdf");
FopFactory fopFactory = FopFactory.newInstance();
FOUserAgent foUserAgent = fopFactory.newFOUserAgent();
OutputStream out = new java.io.FileOutputStream(pdffile);
out = new java.io.BufferedOutputStream(out);
try
{
Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, out);
// Setup XSLT
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer(new StreamSource(xsltfile));
transformer.setParameter("versionParam", "1.0");
Source src = new StreamSource(xmlfile);
Result res = new SAXResult(fop.getDefaultHandler());
transformer.transform(src, res);
} finally {
out.close();
}
System.out.println("Success!");
Usa JasperReports. È possibile estrarre i dati dal database o dall'XML. Puoi esportare in molti formati: pdf, excel, html, ecc ...
In ritardo, puoi creare un PDF statico con il designer di Adobe con campi modificabili, quindi creare un documento XML XDP corrispondente.
Esistono due modi per farlo.
-
In primo luogo, è possibile creare un normale PDF che quando viene riletto non fornisce la gerarchia del file XML originale. Questo è spiegato in modo molto elaborato nella
'Sezione 9.4.2 Analisi XML'
del'iText in Action: Edition 2'
. -
In secondo luogo, è possibile creare un PDF con tag che contenga sia la gerarchia dell'XML sia i dati. Ciò consente di rileggere il file PDF e creare un file XML da questo (che corrisponde esattamente al file XML originale). Questo concetto è anche trattato in dettaglio in
'15 .2.3 Aggiunta di struttura '
del' iText in Action: Edition 2 '
.
In base alle tue esigenze, puoi utilizzare uno degli approcci sopra menzionati.
XML, CSS, XHTML, ecc. consistono in un "ecosistema vivo" di standard aperti, mentre XSL-FO è uno standard isolato.
... Storicamente XSL-FO e XSLT sono stati creati come fratelli gemelli, ma solo XSLT rimane uno "standard vivo", XSL-FO concentra molto DNA negli standard proprietari (Adobe) ... ora è obsoleto.
A rigor di termini, XSL-FO fa parte di un modo "abbandonato". che non si evolverà, ignora i CSS, il "nuovo modo" per esprimere il layout nell'ecosistema "vivo" " ;.
Non è un problema Java
Vedi questa risposta sull'uso della pagina CSS con XML o XHTML.