Konvertieren Sie HTML-Inhalte in das PDF-Format
Die Bereitstellung von Webinhalten als PDF ist eine Möglichkeit, die Verbreitung von Inhalten zu erleichtern. In einigen Branchen ist der Zugriff auf druckformatierte Dokumente, z. B. Beschreibungen der Leistungen an Arbeitnehmer, obligatorisch. Das Gesetz schreibt tatsächlich vor, dass zusammenfassende Planbeschreibungen (SPDs) in gedruckter Form zur Verfügung gestellt werden, obwohl der Inhalt online bereitgestellt werden kann. Das Drucken der Webseite reicht nicht aus, da das Druckformat ein Inhaltsverzeichnis mit Seitenzahlreferenzen enthalten muss.
Um einer Webseite solche Funktionen hinzuzufügen, können Entwickler den HTML-Inhalt in das PDF-Format konvertieren. Dieser Artikel zeigt, wie. Die hier dargestellte Methode zur Durchführung der Konvertierung verwendet nur Open-Source-Komponenten. Kommerzielle Produkte unterstützen auch die dynamische Dokumentenerstellung. Adobe verfügt beispielsweise über die Document Server-Produktlinie. Die Kosten sind jedoch erheblich. Durch die Verwendung einer Open Source-Lösung wird der Kostenfaktor verringert und gleichzeitig die Transparenz des Quellcodes erhöht.
Die Konvertierung besteht aus drei Schritten:
- Konvertieren Sie den HTML-Code in XHTML
- Konvertieren Sie das XHTML-Dokument mithilfe eines XSL-Stylesheets und eines XSLT-Transformators in XSL-FO (Extensible Stylesheet Language Formatating Objects)
- Übergeben Sie das XSL-FO-Dokument an einen Formatierer, um das Ziel-PDF-Dokument zu generieren
Dieser Artikel beschreibt, wie die Übersetzungen mithilfe der von den Tools bereitgestellten Befehlszeilenschnittstellen ausgeführt werden, und stellt anschließend ein Java-Programm vor, das die DOM-Schnittstellen (Document Object Model) verwendet.
Komponentenversionen
Der Code in diesem Artikel wurde mit den folgenden Versionen getestet:
Komponente | Ausführung |
JDK | 1.5_06 |
JTidy | r7-dev |
Xalan-J | 2.7 |
GECK | 0,20,5 |
Verwenden der Befehlszeilenschnittstellen
Jeder der drei Schritte besteht darin, eine Ausgabedatei aus einer Eingabedatei zu generieren. Die Ein- und Ausgänge der Schritte sind in der folgenden Abbildung dargestellt.

Die Verwendung der Befehlszeilenschnittstellen der drei Tools ermöglicht einen einfachen Einstieg. Dieser Ansatz ist jedoch aufgrund der temporären Zwischendateien, die auf die Festplatte geschrieben werden, nicht für ein System auf Produktionsebene geeignet. Diese zusätzliche E / A würde zu einer schlechten Leistung führen. Später in diesem Artikel wird das Problem der temporären Dateien behoben, wenn die drei Tools von einem Java-Programm aufgerufen werden.
Schritt 1: HTML zu XHTML
Der erste Schritt besteht darin, die HTML-Datei in eine neue XHTML-Datei zu übersetzen. Wenn der Startpunkt für die Konvertierung bereits XHTML ist, gilt dieser Schritt natürlich nicht.
Ich habe JTidy verwendet, um die Übersetzung durchzuführen. JTidy ist ein Java-Port des Tidy HTML-Parsers. Bei der Übersetzung in XHTML fügt JTidy auch fehlende Close-Tags hinzu, um ein wohlgeformtes XML-Dokument zu erstellen. Ich habe die neueste Version verwendet (r7-dev), die auf der SourceForge-Website aufgeführt ist.
Verwenden Sie zum Ausführen von JTidy das folgende Skript tidy.sh:
#/bin/sh
java -classpath lib/Tidy.jar org.w3c.tidy.Tidy -asxml >
Dieses Skript legt die CLASSPATH
Variable fest und ruft JTidy auf. Um JTidy auszuführen, wird die Eingabedatei als Befehlszeilenargument übergeben. Standardmäßig wird das generierte XHTML auf die Standardausgabe gerichtet. Der -modify
Schalter kann auch zum Überschreiben der Eingabedatei verwendet werden. Der -asxml
Schalter weist JTidy an, wohlgeformtes XML im Gegensatz zu HTML auszugeben.
Das Skript wird wie folgt aufgerufen:
tidy.sh hello.html hello.xml
Die Dateien hello.html (Eingabe) und hello.xml (Ausgabe) werden hier angezeigt:
Hello World
Hello World!
Hello World
Hello World!
Notiere dass der
Tag hat einen Abschluss
Schritt 2: XHTML zu XSL-FO
Als nächstes wird das XHTML in XSL-FO umgewandelt, eine Sprache zum Festlegen des Druckformats von XML-Dokumenten. Um die Transformation zu erreichen, wende ich ein XSL-Stylesheet an, das von einem XSLT-Transformator (Apache Xalan) verarbeitet wird. Das Stylesheet, das ich als Ausgangspunkt verwendet habe, ist xhtml2fo.xsl, bereitgestellt von Antenna House, einem Unternehmen, das einen kommerziellen Formatierer für XSL-FO verkauft.
Das Stylesheet xhtml2fo.xsl gibt an, wie jedes der HTML-Tags in die entsprechende Folge von XSL-FO-Formatierungsbefehlen übersetzt werden soll. Im Fall eines HTML- H2
Tags ist die Übersetzung beispielsweise wie folgt definiert:
Die obige XSLT-Vorlage wird jedes Mal aufgerufen, wenn ein H2
Tag im HTML-Eingabestream auftritt. Das html:
Präfix gibt an, dass sich das H2
Tag im HTML-Namespace befindet. Die Namespaces des Stylesheets werden als Attribute für die xsl:stylesheet
Direktive der obersten Ebene angegeben . Wenn wir uns den Anfang der Datei xhtml2fo.xsl ansehen, sehen wir drei angegebene Namespaces. Eine für jede der Sprachen XSL, XSL-FO und HTML:
...
Die zweite Zeile der Vorlage
bewirkt, dass ein fo:block
Tag ausgegeben wird, wobei das H2
Attribut festgelegt wird, um die Attribute und Werte für das fo:block
Tag zu generieren . Ein XSL-FO-Block ist ein Textbereich, der basierend auf den für die Blockattribute angegebenen Werten gerendert wird.
Der Attributsatz für H2
ist im Stylesheet wie folgt definiert:
10mm 10mm 1em 0.5em x-large bold black
The start-indent
and subsequent attributes above are used to specify the formatted appearance of an H2
block. Using an attribute set makes it easy to change the appearance of all blocks in the PDF document that correspond to the same HTML input tag. Simply change the settings in the attribute set; the output of all translations that use the attribute set will change too.
The next directive in the translation calls the template named "process-common-attributes-and-children":
This template is defined in the stylesheet. Its purpose is to check for some common HTML attributes (i.e., lang, id, align, valign, style) and then generate the corresponding XSL-FO directives. To trigger the translation of any tags nested within the top-level H2
tag, the process-common-attributes-and-children template then calls:
Hence, if the input is
Hello there
the inside the template for
H2
would trigger the invocation of the template that translates the tag.
The output of translating an H2
tag is:
To apply the xhtml2f0.xsl, we invoke the Xalan transformer. The Unix script xalan.sh sets the
CLASSPATH
variable with the required jar files before calling Xalan:
#/bin/sh
export CLASSPATH=".;./lib/xalan.jar;./lib/xercesImpl.jar;./lib/xml-apis.jar;lib/serializer.jar"
java -classpath $CLASSPATH org.apache.xalan.xslt.Process -IN -XSL xhtml2fo.xsl -OUT -tt
Since Xalan requires an XML parser, the Apache Xerces parser and xml-api JARs are referenced in addition to xalan.jar. All of the jar files are bundled with the Xalan distribution.
To create an XSL-FO file by applying the stylesheet to the XHTML input, invoke the script:
xalan.sh hello.xml hello.fo
I like to use the trace option (
-tt
) with Xalan to display a trace of the templates that are applied. The file hello.fo is shown below:
Hello World Hello World
- -
Hello World!
Step 3: XSL-FO to PDF
The third and final step is to pass the XSL-FO document to a formatter that can generate PDF. I used Apache FOP (Formatting Objects Processor). FOP partially implements the XSL-FO standard and best supports the PDF output format. There is nascent support for Postscript, and support for Microsoft's RTF (rich text format) is planned. The FOP distribution contains the shell script fop.sh/fop.bat that takes an XSL-FO file as input and generates the specified PDF output file.
The Unix script can be run, for example, by:
fop.sh hello.fo hello.pdf
The only prerequisite is to set the environment variable used by the script for the FOP home directory's path.
The file hello.pdf contains the output from FOP and is included in this article's source code, which can be downloaded from Resources.
Since FOP doesn't currently fully implement the XSL-FO standard, there are some limitations. The subset of the standard that is supported is described in detail in the compliance section of the FOP Website.
Java program
Utilizing the DOM APIs of the three tools used in the steps above, I'll now present a Java program that requires two command line arguments (HTML input file and stylesheet) and creates a corresponding PDF. No temporary files are created.
First the program creates an
InputStream
for the HTML file. The InputStream
object is then passed to JTidy.
JTidy has method
parseDOM()
, which is called to obtain the output XHTML content as a Document
object:
public static void main(String[] args) {
// open file if (args.length != 2) { System.out.println("Usage: Html2Pdf htmlFile styleSheet"); System.exit(1); }
FileInputStream input = null; String htmlFileName = args[0]; try { input = new FileInputStream(htmlFileName); } catch (java.io.FileNotFoundException e) { System.out.println("File not found: " + htmlFileName); }
Tidy tidy = new Tidy(); Document xmlDoc = tidy.parseDOM(input, null);
XML namespaces are not supported in the JTidy's DOM implementation; hence, the rules in the Antenna House stylesheet must be modified to use the default namespace. For example, instead of
the rule is changed to
This change must be applied to all templates in xhtml2f0.xsl because the
Document
object created by JTidy has as the root tag, as opposed to:
The modified version of xhtml2fo.xsl is included in this article's source code.
Next, the method
xml2FO()
calls Xalan programmatically to apply the stylesheet to the DOM object created by JTidy:
Document foDoc = xml2FO(xmlDoc, args[1]);
Method
xml2FO()
first calls getTransformer()
to obtain a Transformer
object for the specified stylesheet. The Document
that represents the result of the transform is then returned: