CSS, Prince og PDF
Datagrunnlag
Vi tar utgangspunkt i to HTML-sider med litt tilfeldig tekst. lirumlarum.html og loremipsum.html.
Begge har koplet til et trivielt stilsett:
@media screen{ h1{color:black} } @media print{ h1{color:red} }
Sider
Vi lager videre et stilsett som skal brukes av Prince når det genereres PDF:
@page { size: A4; /*top, right, bottom and left*/ margin: 100pt 40pt 40pt 90pt; @top-left { content:"demo"; } @top-right { content:"Bare tull"; font-size:24px; } @bottom-right { content: counter(page); font-style: italic; font-size:11px; border-top-style:solid; border-top-width:thin; } @bottom-left { content:"B. Stenseth"; font-style: italic; font-size:11px; border-top-style:solid; border-top-width:thin; } }
Begge disse stilsettene er i bruk når Prince genererer PDF.
Slå sammen filer
Før vi går videre slår vi sammen de to filene lirumlarum.html og loremipsum.html, og vi legger på noen elementer som skal bli en forside og noen elementer som skal bli en side med innholdsfortegnelse. Tilsammen blir det slik: altsammen.html.
Denne sammenslåingen av filer er åpenbart et tema for programmering. Vi kan lett tenke oss en situasjon der brukeren via en webside velger ut et antall sider som skal skrives ut "som en bok". Det viktige er at vi har merket det som skal hentes fra hver side på en enkel måte. I vårt tilfelle er alt det interessante(?) innholdet i lirumlarum og loremipsum pakket inn i et <div>-element med class="collect".
Vi utvider stilsettet slik at det tar høyde for innholdsfortegnelse og en spesiell forside:
@page { size: A4; /*top, right, bottom and left*/ margin: 100pt 40pt 40pt 90pt; @top-left { content:"demo"; } @top-right { content:"Bare tull"; font-size:24px; } @bottom-right { content: counter(page); font-style: italic; font-size:11px; border-top-style:solid; border-top-width:thin; } @bottom-left { content:"B. Stenseth"; font-style: italic; font-size:11px; border-top-style:solid; border-top-width:thin; } } @page:first { @top-left { content:url(printlogo_txt.gif); } @top-right {content:" "} @bottom-left {content:"";border:none} @bottom-right {content:"";border:none} } .frontpage{margin-top:7cm;font-size:48px} h1{page-break-before:always} a{color:black;text-decoration:none} .TOC a::after { content: leader(".") target-counter(attr(href), page); } .TOC .level1{margin-left:1cm}
Interaktivt
Prince har et grafisk brukergrensesnitt, og det er enkelt å kople til en eller begge HTML-filene og stilsettet pdfstyle.css. Vi kan stille noen konfigurasjoner og be Prince generere PDF. Det kan være lurt å kjøre interaktivt når vi arbeider med å justere stilsett og/eller HTML/XML kode.
Fra kommandolinja
Prince lar seg kjøre direkte fra commandolinja, f.eks. kan vi lage en bat-fil slik under windows:
set PP=c:\fixed\prince\engine\bin\ set P=c:\projects\princing\ %PP%prince.exe %P%altsammen.html -o %P%altfrabat.pdf --log=%P%princelog.txt -s %P%pdfstyle.css
Fra Python
Vi kan kjøre Prince fra et python program, f.eks. slik:
""" Make a PDF-file from a HTML file with PrinceXML """ import subprocess import sys #-------------------- # fixed paths and logging """ project catalog """ cat='c:\\projects\\princing\\' """ prince path """ princepath='c:\\fixed\\prince\\engine\\bin\\prince.exe' """ log file """ logfile=cat+'princelog.txt' """ full report """ verbose=False """ Do one page to one page """ def doSinglePageJob(infile,outfile,stylesheet): params=[princepath,infile,'-o '+outfile,'--log='+logfile] if verbose: params.append('-v') params.append("-s "+stylesheet) subprocess.call(params) #-------------------------------- if __name__=="__main__": doSinglePageJob(cat+'altsammen.html', cat+'altfrapython.pdf', cat+'pdfstyle.css')
Fra Python på serveren
Vi kan kjøre Prince fra et python program på serveren, f.eks. slik:
#! /usr/bin/python """ Make a PDF-file from a HTML file with PrinceXML, running on server """ import cgitb; cgitb.enable() import cgi import subprocess import sys #-------------------- # fixed paths and logging """ prince path """ princepath='/usr/local/bin/prince' """ log file """ logfile='princelog.txt' """ full report """ verbose=False """ Do one page to one page """ def doSinglePageJob(infile,outfile,stylesheet): params=[princepath,infile,'-o '+outfile,'--log='+logfile] if verbose: params.append('-v') params.append("-s "+stylesheet) try: retcode=subprocess.call(params) print 'Location: '+outfile+'\n' return str(retcode) except: res=sys.exc_info() print 'Content-type: text/html; charset=utf-8\n' print 'Error with code: '+ str(res[1]) return res[1] #-------------------------------- result=doSinglePageJob('altsammen.html', 'altfrapython.pdf', 'pdfstyle.css')
Merk linja:
print 'Location: '+url+'altfrapython.pdf'+'\n'
Denne returnerer den PDF fila vi har produsert. Merk videre at vi ikke skriver den vanlige "Content-type ..." linja når vi styrer en fil direkte tilbake med "Location: "
Du kan teste her:
Som du ser kjører dette skriptet uten parametere. Det skulle være en enkel sak å sende med parametere og pakke ut disse på tjenersiden.