Un esempio concreto
medio
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 :-)