PDA

View Full Version : [XSLT] Creare il file XSL per creare PDF da XML


luxorl
26-07-2008, 12:36
Se io ho il seguente file xml:


<?xml version="1.0" encoding="windows-1252"?>
<richiesta codice="2">
<richiedente codiceFiscale="MGUAIH8787ASDSAD">PAOLO ROSSI</richiedente>
<obiettivo>TEST</obiettivo>
<destinazione>Milano, Italia</destinazione>
<dataInizio>Wed Oct 22 00:00:00 CEST 2008</dataInizio>
<durata>12</durata>
<anticipo>no</anticipo>
<dataRichiesta>Wed Jul 16 00:00:00 CEST 2008</dataRichiesta>
</richiesta>

Potete aiutarmi a formattare il file xsl per creare un pdf tramite processore FOP?

Il risultato è semplice.
Dovrebbe essere qualcosa del genere:


Il sottoscritto: ***** codice fiscale: ****
fa richiesta di missione con obiettivo: ****** e destinazione: *****
La missione inizierà in data: ***** e durerà *** gg
Data Richiesta: ****

Firma


Ho impostato tutto correttamente per la trasformazione tramite servlet java, però ho problemi seri a crearmi il .xsl
Potete aiutarmi per favore? :(

luxorl
27-07-2008, 10:01
Neanche un aiutino piccolo piccolo? :cry:

luxorl
28-07-2008, 11:17
Allora, facendo alcuni test con il seguente file .xsl

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:output method="xml" version="1.0" omit-xml-declaration="no" indent="yes"/>


<xsl:template match="root">
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">

<fo:layout-master-set>
<fo:simple-page-master
margin-right="1.5cm"
margin-left="1.5cm"
margin-bottom="2cm"
margin-top="1cm"
page-width="21cm"
page-height="29.7cm"
master-name="simpleA4" >

<fo:region-body margin-top="1cm" margin-bottom="1.5cm"/>



<fo:region-before extent="1cm"/>

<fo:region-after extent="1.5cm"/>
</fo:simple-page-master>
</fo:layout-master-set>

<fo:page-sequence master-reference="simpleA4">
<fo:static-content flow-name="xsl-region-before">
<fo:block font-size="18pt"
font-family="sans-serif"
line-height="24pt"
space-after.optimum="15pt"
background-color="blue"
color="white"
text-align="center"
padding-top="3pt"> Richiesta Missioni </fo:block>
</fo:static-content>

<fo:static-content flow-name="xsl-region-after">
<fo:block line-height="14pt" font-size="10pt"
text-align="end">Page <fo:page-number/></fo:block>
</fo:static-content>

<fo:flow flow-name="xsl-region-body">
<fo:block text-align="end"><xsl:variable name="pp" select="./@rrr" /> <fo:external-graphic src="{$pp}" /> </fo:block>

<xsl:apply-templates/>
</fo:flow>
</fo:page-sequence>
</fo:root>

</xsl:template>

<xsl:template match="richiesta">

</xsl:template>

</xsl:stylesheet>

Tutto sembra funzionare, mi si apre il pdf ma mi esce l'errore:

Questo file non può essere aperto perché non contiene alcuna pagina

Perché? :( so che non stampo ancora niente dal file xml ma non dovrebbe almeno apparire la pagina con la scritta: Richiesta Missioni ?

Di seguito vi incollo il codice della Servlet che crea prima il file xml e poi il pdf. Penso sia tutto giusto.. l'errore secondo me sta nel file .xsl
Voi che dite? Qualcuno può darmi una mano per favore?

/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/

package missioni.servlet;

import java.io.*;
import java.net.*;

import javax.ejb.EJB;
import javax.servlet.*;
import javax.servlet.http.*;
import org.jdom.*;
import org.jdom.output.XMLOutputter;
import missioni.ejb.session.GestoreMissioniLocal;

//Java
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;

//JAXP
import java.util.*;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerException;
import javax.xml.transform.Source;
import javax.xml.transform.Result;
import javax.xml.transform.stream.StreamSource;
import javax.xml.transform.sax.SAXResult;

//Avalon
//import org.apache.avalon.framework.ExceptionUtil;
import org.apache.avalon.framework.logger.ConsoleLogger;
import org.apache.avalon.framework.logger.Logger;

//FOP
import org.apache.fop.messaging.*;
import org.apache.fop.apps.Driver;
import org.apache.fop.apps.FOPException;

/**
*
* @author while
*/
public class CreaPDFServlet extends HttpServlet {

@EJB
GestoreMissioniLocal gestore=null;

protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try{

RequestDispatcher rd =null;
String path=getServletContext().getRealPath(""); //recupera il path assoluto --rende così
path=path+"/"; //l'applicazione indipendent dal file System locale
// del container che la esegue --

HttpSession sessione=request.getSession();
//RICHIEDENTE
String n=(String)sessione.getAttribute("nome");
String c=(String)sessione.getAttribute("cognome");
String codiceFiscale=(String)sessione.getAttribute("codiceFiscale");
//DATI MISSIONE
String codiceRichiesta=request.getParameter("codiceRichiesta");
String ob=request.getParameter("obiettivo");
String cit=request.getParameter("citta");
String naz=request.getParameter("nazione");
String di=request.getParameter("dataInizio");
String dr=request.getParameter("dataRichiesta");
String ant=request.getParameter("anticipo");
String dur=request.getParameter("durata");

//CREO FILE XML
File fileTmp = new File(path+"rich.xml");

//CREO L'ELEMENTO ROOT
Element root = new Element("richiesta");

/* Per specificare il foglio di stile associato al file all'apertura tramite browser
* dobbiamo creare un'istanza della classe ProcessingInstruction in cui tramite l'ogetto HashMap
* in cui settiamo le coppie chiave valore opportune
*/
Map mapping=new HashMap();
mapping.put("type","text/xsl");
mapping.put("href",path+"richieste.xsl");
ProcessingInstruction pi=new ProcessingInstruction("xml-stylesheet",mapping);

ArrayList arry=new ArrayList();
arry.add(pi);
arry.add(root);

Document documento = new Document(arry);

//AGGIUNGIAMO ATTRIBUTO: <root attributo=valore>
root = root.setAttribute("codice",codiceRichiesta);

//ELEMENTI INNESTATI
Element richiedente = new Element("richiedente");
richiedente = richiedente.setAttribute("codiceFiscale", codiceFiscale);
Element obiettivo = new Element("obiettivo");
Element destinazione = new Element("destinazione");
Element dataInizio = new Element("dataInizio");
Element durata = new Element("durata");
Element anticipo = new Element("anticipo");
Element dataRichiesta = new Element("dataRichiesta");

//VALORI ELEMENTI INNESTATI
richiedente.addContent(n+" "+c);
obiettivo.addContent(ob);
destinazione.addContent(cit+", "+naz);
dataInizio.addContent(di);
durata.addContent(dur);
anticipo.addContent(ant);
dataRichiesta.addContent(dr);

//ATTACCO TUTTO A ROOT
root.addContent(richiedente);
root.addContent(obiettivo);
root.addContent(destinazione);
root.addContent(dataInizio);
root.addContent(durata);
root.addContent(anticipo);
root.addContent(dataRichiesta);

BufferedWriter out = null;
out = new BufferedWriter(new FileWriter(fileTmp));

/* ISTANZIAMO LA CLASSE XMLOutputter CHE CI PERMETTE DI FORMATTARE IL FILE XML. */
XMLOutputter xout = new XMLOutputter();
xout.setEncoding("windows-1252"); //impostiamo l'encoding per la corretta visualizzazione con explorer
xout.setIndent(true);
xout.setNewlines(true);

/* CON QUESTA ISTRUZIONE SCRIVIAMO IL DOCUMENTO documento IN UN BufferedWriter CHE CREA
IL FILE TRAMITE UN FileWriter */

xout.output(documento,out);

out.close();

String fwd ="/rich.pdf";

//*********** creazione del file PDF ****************/
File xmlfile = new File (path+"rich.xml");
File xsltfile = new File (path+"richieste2.xsl");
File pdffile = new File (path+"rich.pdf");

Xml2Pdf app = new Xml2Pdf();
app.convertXML2PDF(xmlfile, xsltfile, pdffile);

rd=request.getRequestDispatcher(fwd);
rd.forward(request, response);

}catch(Exception e){
e.printStackTrace();
HttpSession sessione=request.getSession();
sessione.setAttribute("msg", e);
response.sendRedirect("jsp/error.jsp");
}
}



}

class Xml2Pdf {


public void convertXML2PDF(File xml, File xslt, File pdf)
throws IOException, FOPException, TransformerException {
//Construct driver
Driver driver = new Driver();

//Setup logger
Logger logger = new ConsoleLogger(ConsoleLogger.LEVEL_INFO);
MessageHandler.setScreenLogger(logger);
driver.setLogger(logger);
//Driver.enableLogging(logger);
//driver.initialize();

//Setup Renderer (output format)
driver.setRenderer(Driver.RENDER_PDF);

//Setup output
OutputStream out = new java.io.FileOutputStream(pdf);
out = new java.io.BufferedOutputStream(out);
try {
driver.setOutputStream(out);

//Setup XSLT
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer(new StreamSource(xslt));

//Setup input for XSLT transformation
Source src = new StreamSource(xml);

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

//Start XSLT transformation and FOP processing
transformer.transform(src, res);
} finally {
out.close();
}
}


}

luxorl
28-07-2008, 15:34
Ho risolto.
Per dare un contributo alla sezione scrivo il codice di seguito:

xsl (incompleto ma da cui si può prendere spunto)

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



<xsl:template match="/">

<fo:root>

<fo:layout-master-set>
<fo:simple-page-master master-name="A4">
<fo:region-body margin="2cm" />
<fo:region-before/>
</fo:simple-page-master>
</fo:layout-master-set>

<fo:page-sequence master-reference="A4">
<fo:flow flow-name="xsl-region-body">
<fo:block>

<xsl:value-of select="richiesta/richiedente"/>

</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>

</xsl:template>



</xsl:stylesheet>

Codice per richiamare la trasformazione:

FopFactory fopFactory = FopFactory.newInstance();
TransformerFactory tFactory = TransformerFactory.newInstance();

//Setup a buffer to obtain the content length
ByteArrayOutputStream out2 = new ByteArrayOutputStream();

//Setup FOP
Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, out2);

//Setup Transformer
Source xsltSrc = new StreamSource(new File(path+"rich.xsl"));
Transformer transformer = tFactory.newTransformer(xsltSrc);

//Make sure the XSL transformation's result is piped through to FOP
Result res = new SAXResult(fop.getDefaultHandler());

//Setup input
Source src = new StreamSource(new File(path+"rich.xml"));

//Start the transformation and rendering process
transformer.transform(src, res);

//Prepare response
response.setContentType("application/pdf");
response.setContentLength(out2.size());

//Send content to Browser
response.getOutputStream().write(out2.toByteArray());
response.getOutputStream().flush();


Codice di tutta la Servlet che crea prima il .xml e poi lo trasforma in .pdf (il codice della trasformazione è compreso)

/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/

package missioni.servlet;

import java.io.*;
import java.net.*;

import javax.ejb.EJB;
import javax.servlet.*;
import javax.servlet.http.*;
import org.jdom.*;
import org.jdom.output.XMLOutputter;
import missioni.ejb.session.GestoreMissioniLocal;

//Java
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;

//JAXP
import java.util.*;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerException;
import javax.xml.transform.Source;
import javax.xml.transform.Result;
import javax.xml.transform.stream.StreamSource;
import javax.xml.transform.sax.SAXResult;

//Avalon
//import org.apache.avalon.framework.ExceptionUtil;
import org.apache.avalon.framework.logger.ConsoleLogger;
import org.apache.avalon.framework.logger.Logger;

//FOP
//import org.apache.fop.messaging.*;
//import org.apache.fop.apps.Driver;
import org.apache.fop.apps.FOPException;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.logging.Level;
//import java.util.logging.Logger;
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.FopFactory;
import org.apache.fop.apps.Fop;
import org.apache.fop.apps.MimeConstants;

/**
*
* @author while
*/
public class CreaPDFServlet extends HttpServlet {

@EJB
GestoreMissioniLocal gestore=null;

protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try{

RequestDispatcher rd =null;
String path=getServletContext().getRealPath(""); //recupera il path assoluto --rende così
path=path+"/"; //l'applicazione indipendent dal file System locale
// del container che la esegue --

HttpSession sessione=request.getSession();
//RICHIEDENTE
String n=(String)sessione.getAttribute("nome");
String c=(String)sessione.getAttribute("cognome");
String codiceFiscale=(String)sessione.getAttribute("codiceFiscale");
//DATI MISSIONE
String codiceRichiesta=request.getParameter("codiceRichiesta");
String ob=request.getParameter("obiettivo");
String cit=request.getParameter("citta");
String naz=request.getParameter("nazione");
String di=request.getParameter("dataInizio");
String dr=request.getParameter("dataRichiesta");
String ant=request.getParameter("anticipo");
String dur=request.getParameter("durata");

//CREO FILE XML
File fileTmp = new File(path+"rich.xml");

//CREO L'ELEMENTO ROOT
Element root = new Element("richiesta");

/* Per specificare il foglio di stile associato al file all'apertura tramite browser
* dobbiamo creare un'istanza della classe ProcessingInstruction in cui tramite l'ogetto HashMap
* in cui settiamo le coppie chiave valore opportune
*/
Map mapping=new HashMap();
mapping.put("type","text/xsl");
mapping.put("href",path+"richieste.xsl");
ProcessingInstruction pi=new ProcessingInstruction("xml-stylesheet",mapping);

ArrayList arry=new ArrayList();
arry.add(pi);
arry.add(root);

Document documento = new Document(arry);

//AGGIUNGIAMO ATTRIBUTO: <root attributo=valore>
root = root.setAttribute("codice",codiceRichiesta);

//ELEMENTI INNESTATI
Element richiedente = new Element("richiedente");
richiedente = richiedente.setAttribute("codiceFiscale", codiceFiscale);
Element obiettivo = new Element("obiettivo");
Element destinazione = new Element("destinazione");
Element dataInizio = new Element("dataInizio");
Element durata = new Element("durata");
Element anticipo = new Element("anticipo");
Element dataRichiesta = new Element("dataRichiesta");

//VALORI ELEMENTI INNESTATI
richiedente.addContent(n+" "+c);
obiettivo.addContent(ob);
destinazione.addContent(cit+", "+naz);
dataInizio.addContent(di);
durata.addContent(dur);
anticipo.addContent(ant);
dataRichiesta.addContent(dr);

//ATTACCO TUTTO A ROOT
root.addContent(richiedente);
root.addContent(obiettivo);
root.addContent(destinazione);
root.addContent(dataInizio);
root.addContent(durata);
root.addContent(anticipo);
root.addContent(dataRichiesta);

BufferedWriter out = null;
out = new BufferedWriter(new FileWriter(fileTmp));

/* ISTANZIAMO LA CLASSE XMLOutputter CHE CI PERMETTE DI FORMATTARE IL FILE XML. */
XMLOutputter xout = new XMLOutputter();
xout.setIndent(true);
xout.setNewlines(true);

/* CON QUESTA ISTRUZIONE SCRIVIAMO IL DOCUMENTO documento IN UN BufferedWriter CHE CREA
IL FILE TRAMITE UN FileWriter */

xout.output(documento,out);

out.close();

FopFactory fopFactory = FopFactory.newInstance();
TransformerFactory tFactory = TransformerFactory.newInstance();

//Setup a buffer to obtain the content length
ByteArrayOutputStream out2 = new ByteArrayOutputStream();

//Setup FOP
Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, out2);

//Setup Transformer
Source xsltSrc = new StreamSource(new File(path+"rich.xsl"));
Transformer transformer = tFactory.newTransformer(xsltSrc);

//Make sure the XSL transformation's result is piped through to FOP
Result res = new SAXResult(fop.getDefaultHandler());

//Setup input
Source src = new StreamSource(new File(path+"rich.xml"));

//Start the transformation and rendering process
transformer.transform(src, res);

//Prepare response
response.setContentType("application/pdf");
response.setContentLength(out2.size());

//Send content to Browser
response.getOutputStream().write(out2.toByteArray());
response.getOutputStream().flush();


}catch(Exception e){
e.printStackTrace();
HttpSession sessione=request.getSession();
sessione.setAttribute("msg", e);
response.sendRedirect("jsp/error.jsp");
}
}








}

Ciao ;)

banryu79
28-07-2008, 15:54
Solo un appunto: nel codice che hai postato della Servlet hai degli import duplicati (in particolare gli import di Java.io.* di org.apache.fop.apps.FOPException)

luxorl
28-07-2008, 16:24
Solo un appunto: nel codice che hai postato della Servlet hai degli import duplicati (in particolare gli import di Java.io.* di org.apache.fop.apps.FOPException)

Grazie per la segnalazione.

luxorl
28-07-2008, 16:28
Erano rimasti molti import inutili del vecchio codice.
Di seguito solo quelli necessari:


import java.io.*;
import java.net.*;

import javax.ejb.EJB;
import javax.servlet.*;
import javax.servlet.http.*;
import org.jdom.*;
import missioni.ejb.session.GestoreMissioniLocal;

import java.util.*;
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;

import javax.xml.transform.Result;

import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.stream.StreamSource;
import org.apache.fop.apps.FopFactory;
import org.apache.fop.apps.Fop;
import org.apache.fop.apps.MimeConstants;