Bookmark and Share
Document Actions

Un esempio concreto
medio

Caso d'uso: creazione di un semplice modulo per la creazione di PDF con Apache.FOP. Un esempio concreto esemplificherà le potenzialità di Jython.

 

Il linguaggio xslt è un linguaggio (per la precisione un dialetto di xml) progettato per trasformare un file xml in un altro file xml (nel nostro caso un file fo)

Il linguaggio fo (formatting object) contiene un layout (più o meno come un file odt o doc)

Questo è un esempio tratto dalla "vita reale".

Avevo la necessità di scrivere un programma di elaborazione di file xsl-fo. In pratica dovevo trasformare un file xml in un file fo (attraverso un foglio di stile xsl) e infine ottenere un pdf.

 

Purtroppo non ho trovato una libreria per effettuare questa operazione a parte apache.fop.  Questo libreria è scritta in Java e quindi ho deciso di portare il mio progetto in Jython e utilizzarla direttamente.

Per prima cosa ho scaricato il file jar di apache fop.
Ho creato un batch per aggiungere tutti jar necessari alla classpath (path dove vengono ricercate le librerie di Java).
Seguendo l'esempio sul sito ho "tradotto" la chiamata a funzione da Java a Jython.

Come prima cosa faccio l'import dei packages Java e dei moduli Python

from javax.xml.transform import Transformer,TransformerFactory,Source,Result
from javax.xml.transform.stream import StreamSource
from javax.xml.transform.sax import SAXResult
import os.path

L'equivalente sintassi Java non mi avrebbe permesso l'import di più moduli su più righe. Inoltre i namespaces di Python permettono una maggiore leggibilità.

Di seguito creo un paio di oggetti al caricamento dei moduli:

fopFactory = FopFactory.newInstance()
foUserAgent = fopFactory.newFOUserAgent()
factory = TransformerFactory.newInstance()

Questi oggetti sono riutilizzabili per tutte le trasformazioni che dovrò effettuare.

E' interessante notare un altro "risparmio" che mi permette Python: non sono obbligato a dichiarare il tipo restituito! In Java infatti sono obbligato a scrivere:

FopFactory fopFactory = FopFactory.newInstance();

Ora creo una funzione che restituisce un oggetto transformer necessario alla trasformazione da xml a fo. Viene preso come argomento il nome del file xsl.

def loadxslt(xsltfile):
    curdir="file:///" + os.path.dirname(xsltfile).replace("\\","/") + "/"
    foUserAgent.setBaseURL(curdir)
    trans=factory.newTransformer(StreamSource(xsltfile))
    trans.setParameter("versionParam", "2.0")
    return(trans)

Il trasformer ottenuto si passa alla funzione che, dato in input il pathname dell'xml di origine e del pdf di output, si occupa della trasformazione e del rendering in pdf:

def xml2pdf(src,transformer,pdffile):
    out = java.io.BufferedOutputStream(java.io.FileOutputStream(pdffile))
    try:
        fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, out)
        res = SAXResult(fop.getDefaultHandler())
        transformer.transform(src, res)
    finally:
        out.close()

 

Il risultato finale è questo:

from javax.xml.transform import Transformer,TransformerFactory,Source,Result
from javax.xml.transform.stream import StreamSource
from javax.xml.transform.sax import SAXResult
import os.path

fopFactory = FopFactory.newInstance()
foUserAgent = fopFactory.newFOUserAgent()
factory = TransformerFactory.newInstance()

def loadxslt(xsltfile):
    curdir="file:///" + os.path.dirname(xsltfile).replace("\\","/") + "/"
    foUserAgent.setBaseURL(curdir)
    trans=factory.newTransformer(StreamSource(xsltfile))
    trans.setParameter("versionParam", "2.0")
    return(trans)

def xml2pdf(src,transformer,pdffile):
    out = java.io.BufferedOutputStream(java.io.FileOutputStream(pdffile))
    try:
        fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, out)
        res = SAXResult(fop.getDefaultHandler())
        transformer.transform(src, res)
    finally:
        out.close()


if __name__=="__main__":
    import sys
    #sintassi nomecomando file.xml file.xsl file.pdf
    transf=loadxslt(sys.argv[2])
    xml2pdf(sys.argv[1],transf,sys.argv[3])

 

Conclusioni

Jython è un grande strumento a disposizione di chi lavora in Java e anche di chi preferisce Python ma è "obbligato" a dover lavorare con Java :-)

 

 
by Maurizio Lupo last modified 2009-01-21 18:37