PDFs mit PHP und XSLT erstellen
PDF-Export

DeveloperIT-ProjekteSoftware

Das Standardformat, mit dem Web-Inhalte ausgegeben werden, ist nach wie vor HTML. Vielfach ist jedoch auch PDF gefragt. Der Workshop zeigt verschiedene Verfahren PDFs online zu generieren.

Problem: Dynamische Inhalte

PDFs mit PHP und XSLT erstellen

Es gibt zahlreiche Szenarien, bei denen die Ausgabe von Web-Inhalten in Form eines PDF-Dokuments vorteilhafter ist als der traditionelle Weg via HTML. Nicht nur der Produzent von solchem Content kann daraus Vorteile ziehen, sondern auch der Nutzer.

Produzenten können in vielen Fällen den Aufwand für die Produktion erheblich reduzieren: Ob Prospekt, Flyer oder technische Dokumentationen, in den meisten Fällen stellt das Werkzeug, mit dem solche Publikationen erstellt wurden, PDF als Ausgabeoption zur Verfügung. Da bedarf es in den meisten Fällen nur eines Mausklicks, um wahlweise das finale Produkt auf einem Drucker oder als PDF-Dokument auszugeben. Das wird dann auf den Server gestellt und auf einer Auswahlseite für den Abruf durch Interessenten korrekt verlinkt.

Dieses Verfahren kann man sowohl mit Power-Desktop-Publishing-Systemen à la Quark Xpress oder mit Office-Tools wie Open Office, in das eine PDF-Export-Funktion integriert ist, realisieren. Bis zu einer bestimmten Größenordnung oder bei einer parallelen Print- und Online-Produktion mag diese einfache Variante auch sehr rationell sein.

Anders sieht es jedoch bei dynamischen Inhalten aus, die aus Datenbanken erst zum Zeitpunkt des Abrufs generiert werden. Ist hier eine Ausgabe als PDF gewünscht, muss die Konvertierung auf dem Server erfolgen.


Konvertierung auf dem Server

PDFs mit PHP und XSLT erstellen

Auch dafür gibt es diverse Werkzeuge, mit denen sich ein solcher Workflow realisieren lässt. Am einfachsten gestaltet sich die Sache, wenn das verwendete Content-Management-System eine Exportfunktion für PDF integriert hat. Das bekannte Open-Source-CMS EZ-Publish zum Beispiel bietet diese Feature.

Daneben gibt es noch eine Lowend-Variante, bei der PDF-Dokumente ad hoc zum Beispiel mit Hilfe von PHP-Klassen oder -Bibliotheken generiert werden, oder Highend-Frameworks wie Cocoon, mit denen sich Formatkonvertierungen im großen Stil mit Hilfe von XML- und XSLT-Technik realisieren lassen.


Die PHP-Variante

PDFs mit PHP und XSLT erstellen

Der Platzhirsch auf diesem Sektor ist die Bibliothek PDFlib (www.pdflib.com), die alle notwendigen API-Funktionen für die PDF-Erstellung zur Verfügung stellt. Es handelt sich dabei um kommerzielles Produkt, für das bei einer kommerziellen Nutzung Lizenzgebühren fällig werden. Es gibt jedoch auch noch mit PDFlib Lite eine Open-Source-Variante, die einen kostenlosen Einsatz unter bestimmten Bedingungen erlaubt, allerdings nur eine Teilmenge der von PDFlib angebotenen Funktionen unterstützt. Wenn die Bibliothek noch nicht installiert ist, kann sie ab PHP 4.3.9 über Pear mit dem Befehl pear install pdflib installiert werden.

Seit der Version 6 bietet PDFlib zusätzlich zum funktionsorientierten API für PHP 4 ein objektorientiertes API für PHP 5. Die Verwendung unterscheidet sich im Wesentlichen in folgenden Punkten:

In PHP 4 müssen Sie sich zunächst eine PDF-Ressource besorgen, zum Beispiel mit dem Funktionsaufruf $p = PDF_new(). Die erhaltene PDF-Ressource verwenden Sie dann als ersten Parameter in allen weiteren Funktionsaufrufen, so zum Beispiel in:

PDF_begin_document($p, "", "").

In PHP 5 dagegen wird dagegen mit dem Funktionsaufruf $p = new PDFlib() ein PDFlib-Objekt erzeugt, das alle PDFlib-API-Funktionen als Methoden enthält. Zudem wurden in PHP 5 Exceptions eingeführt. Diese werden von PDFlib ab Version 6 ebenfalls unterstützt.

Die PDFlib lässt sich in unterschiedlichsten Szenarien einsetzen. Man kann PDF-Dateien zum Beispiel im Server-Filesystem anlegen und für einen späteren Download bereitstellen. Alternativ kann auch ein PDF-Dokument direkt im Arbeitsspeicher erstellt werden und dann sofort an den Browser geschickt werden.


PDFlib – Ein Beispiel

PDFs mit PHP und XSLT erstellen

Das folgende Code-Beispiel realisiert eine einfache »Hello world«-Seite:


$p = PDF_new();
if (PDF_begin_document($p, "", "") == 0) {
die("Error: " . PDF_get_errmsg($p));
}
PDF_begin_page_ext($p, 595, 842, "");
$font = PDF_load_font($p, "Helvetica-Bold", "winansi", "");

PDF_setfont($p, $font, 24.0);
PDF_set_text_pos($p, 50, 700);
PDF_show($p, "Hello world!");
PDF_continue_text($p, "(says PHP)");
PDF_end_page_ext($p, "");
PDF_end_document($p, "");

$buf = PDF_get_buffer($p);
$len = strlen($buf);

header("Content-type: application/pdf");
header("Content-Length: $len");
header("Content-Disposition: inline;
filename=hello.pdf");

print $buf;
PDF_delete($p);
?>

Die Beschreibung für den Inhalt des zu erstellenden Dokuments erfolgt seitenorientiert. Jede einzelne Seite im Dokument muss definiert und mit Daten gefüllt werden. Funktionen für einen automatischen Seitenumbruch gibt es nicht. Bei der Erstellung einer neuen Seite muss deren Breite und Höhe in Punkten angegeben werden.

Eine neue A4-Seite im Hochformat für das PDF-Dokument erstellt man zum Beispiel mit dem Aufruf PDF_begin_page($pdf, 595, 842) und das Seitenende wird mit PDF_end_page($pdf) angezeigt. Mit den Befehlen PDF_setfont($p, $font, 24.0) wird eine Schrifttype gewählt, mit PDF_set_ text_pos($p, 50, 700) die Position des Textes definiert und mit PDF_show($p, “Hello world!”) der eigentliche Text hinzugefügt.


PDF nur ausgeben

PDFs mit PHP und XSLT erstellen

Ein häufiger Anwendungsfall ist die direkte Anzeige des generierten PDF-Dokuments im Browser ohne Speicherung auf dem Server. Hierfür ruft das PHP-Skript die Befehle


$buf = PDF_get_buffer($p);
$len = strlen($buf);
header("Content-type: application/pdf");
header("Content-Length: $len");
header("Content-Disposition: inline; filename=hello.pdf");
print $buf;

auf. Achten Sie darauf, dass kein anderer Befehl zuvor eine Ausgabe an den Browser sendet, da sonst der Header-Befehl fehlschlägt. PDFlib stellt noch eine ganze Reihe weiterer Funktionen für die Erstellung von PDF-Dokumenten zur Verfügung. Bilder in unterschiedlichen Formaten können geladen und in das PDF eingefügt werden, ebenso andere PDF-Dokumente. Mit Hilfe verschiedener Zeichenfunktionen lassen sich Rechtecke und Kreise generieren, wie folgendes Code-Beispiel zeigt:


pdf_setcolor($p, "fill", "rgb", 0.1, 0.9, 0.1, 0.0);
PDF_rect($p, 50, 700, 400, 60);
PDF_fill($p);

Es zeichnet an ein grünes Rechteck mit der vorgegebenen Größe an der vorgegebenen Position.


Links und Lesezeichen

PDFs mit PHP und XSLT erstellen

Auch Links zur besseren Navigation innerhalb des Dokuments sowie auf externe Informationsquellen lassen sich mit PDFlib-Funktionen setzen. Um zum Beispiel einen Link auf eine externe Website in das PDF einzubauen, arbeiten Sie mit der Funktion PDF_add_weblink:

PDF_add_weblink($p, 50, 550, 50, 50, "http://www.testticker.de");

Mit den vier Zahlenwerten wird die Position und die Größe eines Rechtsecks definiert, das im PDF-Dokument dann als Link-Fläche erscheint. Als Bedienerführung sollte der Bereich in jedem Fall noch mit einem Hinweis beschriftet werden.


Freie Alternativen

PDFs mit PHP und XSLT erstellen

Wem die PDFlib nicht zur Verfügung steht, der kann als Alternative zu einem in PHP implementierten Ersatz greifen. Dabei handelt es sich in der Regel um eine Klasse, die dem Web-Entwickler Funktionen ähnlich denen von PDFlib zur Verfügung stellt. Neben einigen funktionalen Mängeln muss man bei dieser Variante eventuell auch mit Performance-Einschränkungen leben. Während es sich nämlich bei PDFlib um eine echte, in C geschriebene PHP-Erweiterung handelt, muss bei einer PDF-Klasse der Interpreter die ganze Arbeit leisten. Das kann bei größeren Umwandlungen dauern.

Neben der freien Verfügbarkeit ohne Lizenzkosten profitiert der Anwender jedoch von der einfacheren Implementierung und Nutzung. Ein Beispiel für eine solche Klasse ist ezPDF, die unter sourceforge.net/projects/pdf-php zum kostenlosen Download zur Verfügung steht.

Installation und Nutzung ist denkbar einfach: Einfach das Archiv entpacken und im gewünschten Server-Verzeichnis ablegen. Die entscheidenden Files sind class.ezpdf.php und class.pdf.php. Wichtig ist auch noch das Verzeichnis mit den Schriften. Zur ersten Orientierung sieht man sich am besten das Skript readme.php an. Es generiert aus einem Textfile das Handbuch zu der Klasse natürlich als PDF.

Das vorige »Hello world«-Beispiel sieht mit der PHP-Klasse ezPDF so aus:


include ('class.ezpdf.php');
$pdf =& new Cezpdf();
$pdf->selectFont('./fonts/Helvetica.afm');
$pdf->ezText('Hello World!',50);
$pdf->ezStream();
?>

Neben dem kompakten Code erfreut ezPDF den Entwickler noch mit ein paar netten Gimmicks: Mit ezTable erzeugen Sie zum Beispiel aus den Werten eines Arrays schnell eine PDF-Tabelle. Dabei können die Array-Werte zum Beispiel mit einem kleinen Skript aus einem CSV-File oder einer Datenbank ausgelesen werden. Man kann wahlweise Bilder einbinden (ezImage) oder mit diversen Zeichenwerkzeugen operieren (line, ellipse, polygon, rectangle). Sogar Bezier-Kurven lassen sich mit ezPDF zeichnen (curve).

Ohne Zweifel ist ezPDF ein einfach zu handhabendes Werkzeug zum Erstellen von PDF-Dokumenten aus einer Web-Anwendung heraus. Wenn sich die Größe und Komplexität des Outputs in Grenzen hält, dürfte es bei der Anwendung auch keine Performance-Probleme geben.


Die große Lösung

PDFs mit PHP und XSLT erstellen

Bis zu einer gewissen Größenordnung reichen die vorgestellten Skript-Lösungen für die PDF-Konvertierung völlig aus. Wenn jedoch Multichannel-Publishing im großen Stil betrieben werden soll, muss man wohl die Sphäre der Skripts und Klassen verlassen und auf spezielle Server-Applikationen umsteigen.

Der technische Unterbau dafür ist XML. Die Abkürzung steht für Extensible Markup Language und ist ein Standard zur Erstellung strukturierter Dateien, die gleichermaßen von Menschen gelesen und von Computern verarbeitet werden können. XML definiert dabei den grundsätzlichen Aufbau solcher Dateien.

Für die konkreten Anwendungsfälle müssen die Details des Dateiaufbaus jedoch weiter spezifiziert werden. Die Namen der einzelnen Strukturelemente eines XML-Dokuments lassen sich frei wählen. Ein Grundgedanke hinter XML ist die Trennung von Daten und ihrer Präsentation. Mit geeigneten Hilfsmitteln lassen sich damit XML-Dokumente mit unterschiedlichem Layout auf verschiedenen Plattformen und in unterschiedlichen Formaten ausgeben.

Ein weiteres Werkzeug, das dafür ins Spiel kommt, ist XSL. Die Extensible Stylesheet Language beschreibt die Darstellung und Behandlung von XML-Daten mit Hilfe von XSL-Stylesheets. XSL als Sprache umfasst sowohl XSLT als Transformationssprache als auch XSLT-FO als Formatierungssprache. Beide sind von XML abgeleitet und folgen damit deren Syntax und Regeln.

XSLT stellt Elemente bereit, die die Transformation (Umwandlung) von XML-Daten in Daten anderen Formats erlauben, zum Beispiel HTML und RTF. XSL-FO seinerseits stellt – ähnlich CSS – wiederum andere Elemente zur Verfügung, mit denen festgelegt werden kann, wie XML-Daten angezeigt werden sollen. Der Weg zum PDF-Dokument führt hier also über XML-Daten als Basis und die Transformation via XSL.


Cocoon-Framwork

PDFs mit PHP und XSLT erstellen

Eine der Lösungen, die diese Theorie in die reale Server-Praxis umgesetzt hat, ist Cocoon (cocoon.apache.org). Cocoon ist ein universelles XML-Publishing-System, mit dessen Hilfe Sie XML-Dokumente in fast jedes gewünschte Zielformat umwandeln und via Webbrowser ausgeben können.

Cocoon basiert auf der Programmiersprache Java und bietet damit eine hohe Plattformunabhängigkeit. Das Framework versetzt den Anwender in die Lage, ein echtes Multichannel-Publishing-System aufzusetzen und aus einem XML-Datenfundus fast jedes gewünschte Ausgabeformat zu produzieren. Dies können zum Beispiel klassische XHTML-Dokumente für das Web ebenso sein wie Formate für Mobile Devices sowie Word-, Open-Office- oder PDF-Dokumente.

Da die Umwandlung eines XML-Dokuments in das jeweilige Ausgabeformat über XSL erfolgt, lässt sich die Formatvielfalt beliebig ausbauen. Daten, Layout und Logik werden bei Cocoon klar getrennt.

Die Sitemap spielt eine zentrale Rolle bei Cocoon. In ihr werden Komponenten und Aufrufe konfiguriert und logische Abläufe modelliert. Hier kann zum Beispiel für einen bestimmten eingehenden URI definiert werden, welche Aktion daraufhin geschehen soll. Bei der Sitemap handelt es sich wiederum um eine XML-Datei, die sich standardmäßig im Wurzelverzeichnis von Cocoon befindet und den Namen sitemap.xmap besitzt. Der Inhalt umfasst drei Hauptbereiche: Der Komponenten-Bereich definiert alle Komponenten, auf die Cocoon Zugriff hat und die eine bestimmte Arbeit verrichten. Die Hauptaufgaben der Komponenten sind das Lesen, Interpretieren und Umwandeln von XML-Dokumenten und das Erzeugen von bestimmten Zielformaten. Auch die Entscheidungslogik wird im Komponentenbereich der Sitemap festgelegt.

Im Bereich Gruppierungen lassen sich gegebenenfalls einzelne Komponenten auf verschiedene Weisen für eine spezielle Aufgabe kombinieren.

Im Pipelines-Bereich erfolgt schließlich die eigentliche Steuerung der Aktionen in Abhängigkeit von den erfolgten Aufrufen. Wünscht sich ein User also die Ausgabe eines Dokuments als PDF in seinem Browser, werden im Pipeline-Bereich der Sitemap die entsprechenden Weichen gestellt.
Die Installation von Cocoon ist nicht ganz trivial. Für ein erstes Kennenlernen auf einem Windows-PC eignet sich das Xampp-Paket mit den entsprechenden Add-ons sehr gut. Für eine intensivere Beschäftigung mit dem Publishing-Framework empfiehlt es sich, die zahlreichen Samples im Verzeichnis /tomcat/webapps/cocoon/samples genauer unter die Lupe zu nehmen.

Dort findet man übrigens auch das »Hello World«-Beispiel, das in den PHP-Beispielen schon einige Male bemüht wurde.


Das FOP-Projekt

PDFs mit PHP und XSLT erstellen

Neben Cocoon als einem universellen Publishing-Framework gibt es noch FOP, ebenfalls im Apache-Projektumfeld angesiedelt (xmlgraphics.apache. org/fop). Vereinfacht kann man FOP als einen Druckertreiber bezeichnen, der auf dem Server installiert wird und XSL-FO-Dokumente in PDF-Dokumente umwandelt. Wie Cocoon ist auch FOP eine Java-Applikation.