XHTML Seite als PDF mit korrekten Seitenzahlen (via CSS3) exportieren

Thomas Darimont

Erfahrenes Mitglied
Hallo,

die Anleitung unter:
http://today.java.net/pub/a/today/2007/06/26/generating-pdfs-with-flying-saucer-and-itext.html
ist leider etwas veraletet, deshalb hier mal ein kleines Beispiel wie man mit itext und xhtmlrenderer eine XHTML Seite als PDF exportieren kann. Dieser Ansatz erlaubt durch das einfache Styling von Reports über HTML und CSS schnell sehr ansprechende PDF Dokumente zu generieren. Da eine große HTML Seite in der Regel auf mehrere PDF Seiten umgebrochen wird generieren wir die Angabe zur Aktuellen Seitenzahl und der Gesamtzahl an Seiten in den Fuß jeder Dokumentseite. Dies müssen wir nicht ausprogrammieren sondern lassen wir einfach vom xhtmlrenderer mit CSS3 Anweisungen generieren.

Java:
package de.tutorials.training;

import java.awt.Desktop;
import java.io.File;
import java.io.FileOutputStream;

import org.xhtmlrenderer.pdf.ITextRenderer;

public class RenderHtmlToPdfExample {
  public static void main(String[] args) throws Exception{
    
    File pdfFile = new File("c:/temp/page.pdf");
    ITextRenderer renderer = new ITextRenderer();
    renderer.setDocument(new File("c:/temp/page.html"));
    renderer.layout();
    renderer.createPDF(new FileOutputStream(pdfFile),true);
    Desktop.getDesktop().open(pdfFile);
  }
}

Hier unsere HTML Seite (page.html). Man beachte die CSS3 Anweisung @bottom-center
HTML:
<?xml version="1.0" encoding="ISO-8859-1"?>
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
        <title>Test</title>
		
		<style type="text/css">
			@page {
				size: A4 portrait;
				@bottom-center { /* @top-center */
					content: "Seite " counter(page) " von " counter(pages); 
				}
			}
		</style>
    </head>
    <body>
        <table>
            <tr>
                <tr>
                    <td>
                        0
                    </td>
                </tr>
                <tr>
                    <td>
                        1
                    </td>
                </tr>
                <tr>
                    <td>
                        2
                    </td>
                </tr>
                <tr>
                    <td>
                        3
                    </td>
                </tr>
                <tr>
                    <td>
                        4
                    </td>
                </tr>
                <tr>
                    <td>
                        5
                    </td>
                </tr>
                <tr>
                    <td>
                        6
                    </td>
                </tr>
                <tr>
                    <td>
                        7
                    </td>
                </tr>
                <tr>
                    <td>
                        8
                    </td>
                </tr>
                <tr>
                    <td>
                        9
                    </td>
                </tr>
                <tr>
                    <td>
                        10
                    </td>
                </tr>
                <tr>
                    <td>
                        11
                    </td>
                </tr>
                <tr>
                    <td>
                        12
                    </td>
                </tr>
                <tr>
                    <td>
                        13
                    </td>
                </tr>
                <tr>
                    <td>
                        14
                    </td>
                </tr>
                <tr>
                    <td>
                        15
                    </td>
                </tr>
                <tr>
                    <td>
                        16
                    </td>
                </tr>
                <tr>
                    <td>
                        17
                    </td>
                </tr>
                <tr>
                    <td>
                        18
                    </td>
                </tr>
                <tr>
                    <td>
                        19
                    </td>
                </tr>
                <tr>
                    <td>
                        20
                    </td>
                </tr>
                <tr>
                    <td>
                        21
                    </td>
                </tr>
                <tr>
                    <td>
                        22
                    </td>
                </tr>
                <tr>
                    <td>
                        23
                    </td>
                </tr>
                <tr>
                    <td>
                        24
                    </td>
                </tr>
                <tr>
                    <td>
                        25
                    </td>
                </tr>
                <tr>
                    <td>
                        26
                    </td>
                </tr>
                <tr>
                    <td>
                        27
                    </td>
                </tr>
                <tr>
                    <td>
                        28
                    </td>
                </tr>
                <tr>
                    <td>
                        29
                    </td>
                </tr>
                <tr>
                    <td>
                        30
                    </td>
                </tr>
                <tr>
                    <td>
                        31
                    </td>
                </tr>
                <tr>
                    <td>
                        32
                    </td>
                </tr>
                <tr>
                    <td>
                        33
                    </td>
                </tr>
                <tr>
                    <td>
                        34
                    </td>
                </tr>
                <tr>
                    <td>
                        35
                    </td>
                </tr>
                <tr>
                    <td>
                        36
                    </td>
                </tr>
                <tr>
                    <td>
                        37
                    </td>
                </tr>
                <tr>
                    <td>
                        38
                    </td>
                </tr>
                <tr>
                    <td>
                        39
                    </td>
                </tr>
                <tr>
                    <td>
                        40
                    </td>
                </tr>
                <tr>
                    <td>
                        41
                    </td>
                </tr>
                <tr>
                    <td>
                        42
                    </td>
                </tr>
                <tr>
                    <td>
                        43
                    </td>
                </tr>
                <tr>
                    <td>
                        44
                    </td>
                </tr>
                <tr>
                    <td>
                        45
                    </td>
                </tr>
                <tr>
                    <td>
                        46
                    </td>
                </tr>
                <tr>
                    <td>
                        47
                    </td>
                </tr>
                <tr>
                    <td>
                        48
                    </td>
                </tr>
                <tr>
                    <td>
                        49
                    </td>
                </tr>
                <tr>
                    <td>
                        50
                    </td>
                </tr>
                <tr>
                    <td>
                        51
                    </td>
                </tr>
                <tr>
                    <td>
                        52
                    </td>
                </tr>
                <tr>
                    <td>
                        53
                    </td>
                </tr>
                <tr>
                    <td>
                        54
                    </td>
                </tr>
                <tr>
                    <td>
                        55
                    </td>
                </tr>
                <tr>
                    <td>
                        56
                    </td>
                </tr>
                <tr>
                    <td>
                        57
                    </td>
                </tr>
                <tr>
                    <td>
                        58
                    </td>
                </tr>
                <tr>
                    <td>
                        59
                    </td>
                </tr>
                <tr>
                    <td>
                        60
                    </td>
                </tr>
                <tr>
                    <td>
                        61
                    </td>
                </tr>
                <tr>
                    <td>
                        62
                    </td>
                </tr>
                <tr>
                    <td>
                        63
                    </td>
                </tr>
                <tr>
                    <td>
                        64
                    </td>
                </tr>
                <tr>
                    <td>
                        65
                    </td>
                </tr>
                <tr>
                    <td>
                        66
                    </td>
                </tr>
                <tr>
                    <td>
                        67
                    </td>
                </tr>
                <tr>
                    <td>
                        68
                    </td>
                </tr>
                <tr>
                    <td>
                        69
                    </td>
                </tr>
                <tr>
                    <td>
                        70
                    </td>
                </tr>
                <tr>
                    <td>
                        71
                    </td>
                </tr>
                <tr>
                    <td>
                        72
                    </td>
                </tr>
                <tr>
                    <td>
                        73
                    </td>
                </tr>
                <tr>
                    <td>
                        74
                    </td>
                </tr>
                <tr>
                    <td>
                        75
                    </td>
                </tr>
                <tr>
                    <td>
                        76
                    </td>
                </tr>
                <tr>
                    <td>
                        77
                    </td>
                </tr>
                <tr>
                    <td>
                        78
                    </td>
                </tr>
                <tr>
                    <td>
                        79
                    </td>
                </tr>
                <tr>
                    <td>
                        80
                    </td>
                </tr>
                <tr>
                    <td>
                        81
                    </td>
                </tr>
                <tr>
                    <td>
                        82
                    </td>
                </tr>
                <tr>
                    <td>
                        83
                    </td>
                </tr>
                <tr>
                    <td>
                        84
                    </td>
                </tr>
                <tr>
                    <td>
                        85
                    </td>
                </tr>
                <tr>
                    <td>
                        86
                    </td>
                </tr>
                <tr>
                    <td>
                        87
                    </td>
                </tr>
                <tr>
                    <td>
                        88
                    </td>
                </tr>
                <tr>
                    <td>
                        89
                    </td>
                </tr>
                <tr>
                    <td>
                        90
                    </td>
                </tr>
                <tr>
                    <td>
                        91
                    </td>
                </tr>
                <tr>
                    <td>
                        92
                    </td>
                </tr>
                <tr>
                    <td>
                        93
                    </td>
                </tr>
                <tr>
                    <td>
                        94
                    </td>
                </tr>
                <tr>
                    <td>
                        95
                    </td>
                </tr>
                <tr>
                    <td>
                        96
                    </td>
                </tr>
                <tr>
                    <td>
                        97
                    </td>
                </tr>
                <tr>
                    <td>
                        98
                    </td>
                </tr>
                <tr>
                    <td>
                        99
                    </td>
                </tr>
            </tr>
        </table>
    </body>
</html>

Hier noch die Maven Dependency
XML:
<dependency>
			<groupId>org.xhtmlrenderer</groupId>
			<artifactId>core-renderer</artifactId>
			<version>R8</version>
		</dependency>

Gruß Tom
 

Anhänge

  • page.pdf
    2,1 KB · Aufrufe: 54
Zuletzt bearbeitet von einem Moderator:
Danke für den Link und deine Ausführungen!
Ich arbeite schon seit ein paar Tagen mit xhtmlrenderer und dabei ist mir aufgefallen, dass er bei sehr vielen Fehlern und neuen Tags die Anzeige/Verarbeitung der Seite abbricht und eine Fehlermeldung wirft. Schade eigentlich. Dafür ist die Darstellung von xhtmlrenderer verhältnismäßig gut (ok, sie kommt noch nicht an die großen Browser heran). Mal sehen, ob sich daraus ein Browser programmieren lässt ;)
 
Hallo,

Ich arbeite schon seit ein paar Tagen mit xhtmlrenderer und dabei ist mir aufgefallen, dass er bei sehr vielen Fehlern und neuen Tags die Anzeige/Verarbeitung der Seite abbricht und eine Fehlermeldung wirft.
Ja die Fehlermeldungen sind leider oftmals ziemlich nutzlos (welches Element verursachte nochmal den Fehler****?). Eine weitere Schwäche ist, dass über CSS referenzierte Bilder nicht gegen die gesetzte BaseUrl aufgelöst werden. Hier bleibt nur der Workaround mit img-Tags (dort werden die href Pfade relativ zur gesetzten BaseUrl aufgelöst).

Dafür ist die Darstellung von xhtmlrenderer verhältnismäßig gut
Jo besser als alles was ich bisher in dieser Richtung gesehen habe... auf jedenfall besser als ITexts HTMLWorker...

Gruß Tom
 
Eine weitere Schwäche ist, dass über CSS referenzierte Bilder nicht gegen die gesetzte BaseUrl aufgelöst werden.
Kann man beheben, wenn man der Klasse ScalableXHTMLPanel als Konstruktor-Argument ein Objekt einer Klasse übergibt, die das Interface UserAgentCallback implementiert.

Es gibt übrigens noch eine andere HTML-Rendering-Engine für Java: http://lobobrowser.org/java-browser.jsp
Die Entwickler haben das Projekt aber scheinbar aufgegeben und mit xhtmlrenderer kann der auch nicht mithalten. XHTMLRenderer wird aber noch aktiv entwickelt.
 
Hallo,

Kann man beheben, wenn man der Klasse ScalableXHTMLPanel als Konstruktor-Argument ein Objekt einer Klasse übergibt, die das Interface UserAgentCallback implementiert.
Das habe ich heute auch herausgefunden. Trotzdem ist das Verhalten, dass relative Pfade mal und mal nicht gegen die BaseUrl aufgelöst werden für mich ein Bug :)


Gruß Tom
 

Neue Beiträge

Zurück