CSS
Prince
pdf
CSS
Børre Stenseth

CSS, Prince og PDF

Hva

Prince [1] er et godt alternativ for å lage PDF fra XML/HTML. Prince er lisensiert, men du kan laste ned og teste den lokalt på din maskin. Denne modulen tar for seg noen svært enkle eksempler på bruke av Prince.

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:

makepdfonserver.py https://borres.hiof.no/wep/css/cssogpdf/makepdfonserver.py

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.

Referanser
  1. Prince XML Prince www.princexml.com/ 14-03-2014