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



## Thomas Darimont (12. Januar 2011)

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.


```
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

```
<?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

```
<dependency>
			<groupId>org.xhtmlrenderer</groupId>
			<artifactId>core-renderer</artifactId>
			<version>R8</version>
		</dependency>
```

Gruß Tom


----------



## genodeftest (12. Januar 2011)

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


----------



## Thomas Darimont (12. Januar 2011)

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


----------



## genodeftest (12. Januar 2011)

> 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.


----------



## Thomas Darimont (12. Januar 2011)

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


----------



## genodeftest (12. Januar 2011)

…melden 
http://code.google.com/p/flying-saucer/issues/list


----------

