Bonjour,
J'essaie d'adapter un exemple de transformation XML => PDF trouvé sur le site FOP d'Apache, mais je n'arrive pas au résultat que je souhaiterais...
Cet exemple permet de créer un document PDF (1 page) en se basant sur le contenu d'un fichier XML ("annuaire"); ceci marche très bien, mais ce que je voudrais c'est créer un document PDF qui contiendrait 2 pages avec le contenu du fichier XML : page 1 => affichage de mon tableau de personnes; page 2 : affichage du même tableau.
Le problème c'est que comme je ne maîtrise pas du tout le XML/XSLT/XSL-FO/FOP, je ne sais pas si pour arriver à un tel résultat je dois m'orienter vers :
- la modification de la structure de mon fichier XML
- et/ou la modification de mon fichier xsl
Par exemple :
Dois-je modifier la structure de mon XML pour obtenir quelque chose du style :
et trouver le moyen de boucler dans la XSL sur les éléments "page" ?
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59 <projectteam> <page> <projectname>The Killer Application</projectname> <member> <name>John Doe</name> <function>lead</function> <email>jon.doe@killerapp.fun</email> </member> <member> <name>Paul Coder</name> <function>dev</function> <email>paul.coder@killerapp.fun</email> </member> <member> <name>Max Hacker</name> <function>dev</function> <email>max.hacker@killerapp.fun</email> </member> <member> <name>Donna Book</name> <function>doc</function> <email>donna.book@killerapp.fun</email> </member> <member> <name>Henry Tester</name> <function>qa</function> <email>henry.tester@killerapp.fun</email> </member> </page> <page> <projectname>The Killer Application II</projectname> <member> <name>John Doe II</name> <function>lead II</function> <email>jon.doe2@killerapp.fun</email> </member> <member> <name>Paul Coder II</name> <function>dev II</function> <email>paul.coder2@killerapp.fun</email> </member> <member> <name>Max Hacker II</name> <function>dev II</function> <email>max.hacker2@killerapp.fun</email> </member> <member> <name>Donna Book II</name> <function>doc II</function> <email>donna.book2@killerapp.fun</email> </member> <member> <name>Henry Tester II</name> <function>qa II</function> <email>henry.tester2@killerapp.fun</email> </member> </page> </projectteam>
Ou y a-t-il un moyen de rappeler 2 fois le contenu du fichier XML sans dupliquer les données dedans ?
Bref un début de piste et des conseils avisés sur la meilleure solution ne seraient pas de refus
Merci.
NB : ci-joint le doc PDF résultat.
Ci-dessous les sources sur lesquelles je me base :
Une servlet :
Un fichier XML :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94/** * This class demonstrates the conversion of an XML file to PDF using * JAXP (XSLT) and FOP (XSL-FO). */ package PDF; //Java import java.io.File; import java.io.OutputStream; import javax.servlet.http.*; import javax.servlet.ServletException; import java.io.IOException; import java.io.BufferedWriter; import java.io.PrintWriter; import java.io.FileWriter; import java.util.ArrayList; import java.sql.ResultSet; //JAXP import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.Source; import javax.xml.transform.Result; import javax.xml.transform.stream.StreamSource; import javax.xml.transform.sax.SAXResult; //FOP 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 XML2PDF extends HttpServlet { public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { // Setup directories File baseDir = new File("."); outDir.mkdirs(); // Setup input and output files File xmlfile = new File(baseDir, "XML/projectteam.xml"); File xsltfile = new File(baseDir, "XSL/projectteam2fo.xsl"); File pdffile = new File(outDir, "ResultXML2PDF.pdf"); // configure fopFactory as desired FopFactory fopFactory = FopFactory.newInstance(); FOUserAgent foUserAgent = fopFactory.newFOUserAgent(); // configure foUserAgent as desired // Setup output OutputStream out = new java.io.FileOutputStream(pdffile); out = new java.io.BufferedOutputStream(out); 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)); // Set the value of a <param> in the stylesheet transformer.setParameter("versionParam", "2.0"); // Setup input for XSLT transformation Source src = new StreamSource(xmlfile); // Resulting SAX events (the generated FO) must be piped through to FOP Result res = new SAXResult(fop.getDefaultHandler()); // Start XSLT transformation and FOP processing transformer.transform(src, res); } finally { out.close(); } } catch (Exception e) { System.exit(-1); } } public synchronized void destroy () { super.destroy(); } }
Un fichier XSL :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 <projectteam> <projectname>The Killer Application</projectname> <member> <name>John Doe</name> <function>lead</function> <email>jon.doe@killerapp.fun</email> </member> <member> <name>Paul Coder</name> <function>dev</function> <email>paul.coder@killerapp.fun</email> </member> <member> <name>Max Hacker</name> <function>dev</function> <email>max.hacker@killerapp.fun</email> </member> <member> <name>Donna Book</name> <function>doc</function> <email>donna.book@killerapp.fun</email> </member> <member> <name>Henry Tester</name> <function>qa</function> <email>henry.tester@killerapp.fun</email> </member> </projectteam>
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61 <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.1" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" exclude-result-prefixes="fo"> <xsl:output method="xml" version="1.0" omit-xml-declaration="no" indent="yes"/> <xsl:param name="versionParam" select="'1.0'"/> <!-- ========================= --> <!-- root element: projectteam --> <!-- ========================= --> <xsl:template match="projectteam"> <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"> <fo:layout-master-set> <fo:simple-page-master master-name="simpleA4" page-height="29.7cm" page-width="21cm" margin-top="2cm" margin-bottom="2cm" margin-left="2cm" margin-right="2cm"> <fo:region-body/> </fo:simple-page-master> </fo:layout-master-set> <fo:page-sequence master-reference="simpleA4"> <fo:flow flow-name="xsl-region-body"> <fo:block font-size="16pt" font-weight="bold" space-after="5mm">Project: <xsl:value-of select="projectname"/> </fo:block> <fo:block font-size="12pt" space-after="5mm">Version <xsl:value-of select="$versionParam"/> </fo:block> <fo:block font-size="10pt"> <fo:table table-layout="fixed" width="100%" border-collapse="separate"> <fo:table-column column-width="4cm"/> <fo:table-column column-width="4cm"/> <fo:table-column column-width="5cm"/> <fo:table-body> <xsl:apply-templates select="member"/> </fo:table-body> </fo:table> </fo:block> </fo:flow> </fo:page-sequence> </fo:root> </xsl:template> <!-- ========================= --> <!-- child element: member --> <!-- ========================= --> <xsl:template match="member"> <fo:table-row> <xsl:if test="function = 'lead'"> <xsl:attribute name="font-weight">bold</xsl:attribute> </xsl:if> <fo:table-cell> <fo:block> <xsl:value-of select="name"/> </fo:block> </fo:table-cell> <fo:table-cell> <fo:block> <xsl:value-of select="function"/> </fo:block> </fo:table-cell> <fo:table-cell> <fo:block> <xsl:value-of select="email"/> </fo:block> </fo:table-cell> </fo:table-row> </xsl:template> </xsl:stylesheet>
Partager