Von HTML zu XML

Im vorherigen Kapitel wurde gezeigt, wie strukturierte Textdateien zu XML-Dateien konvertiert werden können. Hier geht es nun darum, HTML-Dokumente in eine bestimmte XML-Struktur zu bringen. HTML ist die wichtigste Auszeichnungssprache im Web. Praktisch alle Webseiten sind in HTML codiert.

Wie bereits verdeutlich, ist HTML genau so eine Auszeichnungssprache wie XML. Es ist deshalb möglich, HTML-Dokumente nach bestimmten Regeln in eine XML-Struktur zu überführen.

Achtung: Dieses Kapitel gehört zu den anspruchsvollsten Kapiteln des ganzen Einführung in die Korpuslinguistik! Trotzdem habe ich mich bemüht, Schritt für Schritt alles genau zu erklären und ich empfehle deswegen auch allen Zaudernden, sich dieses Kapitel zu Gemüte zu führen. Auch wer anschließend nicht unbedingt in der Lage ist, selber XSLT-Stylesheets zu schreiben und anzuwenden, weiß danach wenigstens, was möglich ist und was die Grundgedanken sind.

HTML und XHTML

Allerdings genügt HTML nicht den strengen Syntaxregeln von XML. So müssen beispielsweise öffnende Tags nicht zwingend geschlossen werden:

<p>Hier ist ein Absatz.
<p>Und hier folgt ein zweiter Absatz.

Nach XML-Standard wäre dies nicht wohlgeformt. Um eine XML-kompatible Auszeichnungssprache fürs Web zu haben, wurde XHTML entwickelt. XHTML ist eine Art Übersetzung von HTML, um den Regeln von wohlgeformtem XML zu genügen. Das HTML-Beispiel oben müsste in XHTML lauten:

<p>Hier ist ein Absatz.</p>
<p>Und hier folgt ein zweiter Absatz.</p>

Manchmal sind Webseiten in XHTML codiert, so dass sie im Prinzip direkt weiterverarbeitet werden können. Darauf sollte man sich jedoch nicht verlassen. Deshalb gibt es Programme, die HTML-Dokumente in XHTML übersetzen und dabei auch eine Reihe von gängigen syntaktischen Fehlern, die in HTML-Dokumenten in der freien Wildbahn vorkommen, korrigieren.

Ich empfehle die Verwendung von TagSoup. Es handelt sich dabei um eine Java-Anwendung, die über die Kommandozeile aufgerufen werden muss. Alternativ kann ein XML-Editor wie Oxygen (kommerziell) verwendet werden.

Konvertierung mit TagSoup

Für TagSoup muss Java auf dem Rechner installiert sein. Hier gibt es ausführliche Informationen zur Installation von Java auf verschiedenen Betriebssystemen. Zudem wird TagSoup über die Kommandozeile (Eingeabeaufforderung, Terminal) bedient. Grundlegende Informationen dazu finden sich für den Mac und Unix-Systeme hier, für Windows z.B. hier.

  1. Alle HTML-Dateien, die konvertiert werden sollen, müssen sich in einem Verzeichnis befinden. In unserem Beispiel liegen diese alle im Verzeichnis html/.
  2. Nun muss die TagSoup-Datei mit der Endung .jar aufgerufen werden. Dies geschieht über Programme -> Dienstprogramme -> Terminal (Mac) bzw. Start -> Alle Programme -> Zubehör -> Eingabeaufforderung (Windows). Der Aufruf lautet nun:
    java -jar <Pfad zum TagSoup-Verzeichnis>/tagsoup-1.2.1.jar --files 
    --encoding=utf8 <Pfad zum html-Verzeichnis>/*
    Um die Pfade nicht eintippen zu müssen, kann man meist die tagsoup-Datei und das html-Verzeichnis auf das Kommandozeilen-Fenster schieben, dann wird der Pfad automatisch an der Stelle des Cursors eingetragen.
  3. Wenn alles gut geht, konvertiert TagSoup nun alle html-Dateien im html-Verzeichnis. Zu jeder Datei gibt es dann zusätzlich eine mit der Endung .xhtml.

Konvertierung mit Oxygen

In Oxygen Editor können HTML-Dateien über das Menü Datei -> Import -> HTML-Datei... importiert werden. Dabei werden sie automatisch in XHTML konvertiert. Anschließend kann die Datei abgespeichert werden. Zudem kann gleich auch in Oxygen das XSLT-Stylesheet erstellt und angewendet werden (siehe Ausführungen dazu unten).

XSLT-Transformation von XHTML zu XML

Nun kommt der eigentliche Schritt der Transformation. Eine wohlgeformte XML-Datei (und XHTML ist XML) kann mittels Transformationsregeln in eine andere XML-Struktur (und andere Formate) konvertiert werden. Die Idee ist diese: Mittels eines Stylesheets werden Regeln der Art definiert:

Zuerst muss also die XHTML-Datei analysiert werden, um herauszufinden, wo die gewünschten Informationen stecken. Schauen wir uns ein konkretes Beispiel an:

Wir schauen uns nun Stück für Stück das XSLT-Stylesheet an, mit dem die oben genannten Informationen aus der XHTML-Datei extrahiert werden können.

Zunächst benötigen wir ein paar Kopfzeilen, die spezifizieren, dass selbst das Stylesheet ein XML-Dokument ist (Zeile 1), aber eine XSLT-Stylesheet ist (Zeile 2) und die Ausgabe der damit zu bearbeitenden XHTML-Datei XML sein soll (Zeile 3):

Wir definieren nun für verschiedene Elemente, die wir in der XHTML-Datei antreffen, Transformationsregeln. Eine solche Regel ist ein sog. "Template" für ein bestimmtes Element (oder eine Gruppe von Elementen). Eine solche Regel wird mit folgender Syntax beschrieben:

Wir beginnen mit dem Wurzelknoten <html> (in der XHTML-Datei in Zeile 2). Immer wenn dieses angetroffen wird, erzeugen wir in unserer XML-Datei ein <text>-Element:

Das Attribut match oben hat den Wert xhtml:html: Es soll also auf das Element <html> zutreffen. Wir müssen zusätzlich noch den sog. Namensraum spezifzieren – es handelt sich alles um xhtml-Elemente. Deswegen steht davor noch xhtml:.

Die Anweisung <xsl:apply-templates/> bedeutet, dass die XHTML-Datei weiter prozessiert werden soll, da unterhalb des html-Knotens ja noch weitere Elemente kommen.

Da wir gerade dabei sind, können wir gleich noch ein paar Metadaten zum Blog holen. Wir modifizieren deshalb das Stylesheet und haben nun Folgendes:

Wir setzen also innerhalb von text noch die Elemente blogtitle, blogtagline und blogurl. Die Inhalte dafür kriegen wir über die XPath-Pfade, die wir oben aufgrund der Analyse der XHTML-Datei bereits gefunden haben:

Genau diese XPath-Ausdrücke verwenden wir nun in drei XSLT-Ausdrücken der Art:

Um wiederum den XHTML-Namensraum explizit zu benennen, setzen wir in den XPath-Ausdrücken vor jedem Elementnamen noch xhtml: hin, so dass alles komplett folgendermaßen aussieht:

Nun definieren wir weitere Templates. Als Nächstes definieren wir ein Template, das den eigentlichen Textinhalt des Blogs finden und in ein content-XML-Element setzen soll:

Der XPath-Ausdruck sucht also nach einem beliebigen div-Element mit einer Attribut class, die den Wert entry-content beinhaltet. Mit <xsl:apply-templates/> geben wir an, dass hier noch kein Elementinhalt eingesetzt werden soll, sondern die XHTML-Datei einfach weiter prozessiert werden soll (da ja noch weitere Elemente innerhalb des div kommen).

In diesem Zusammenhang definieren wir gleich noch ein Template für p-Elemente, die auch in unserem XML-Dokument als p-Elemente gekennzeichnet sein sollen:

Beachte: Wir nehmen nur p-Elemente, die ein Elternelement div mit den bereits gekannten Einschränkungen (class = 'entry-content'). Mit <xsl:value-of select="."/> sagen wir, dass, wenn ein solches p-Element gefunden wird, genau dessen Inhalt (Punkt als XPath-Ausdruck) verwendet werden soll. Zusätzlich benutzen wir noch die XPath-Funktion normalize-space(), mit der allfälliger überflüssiger Leerraum entfernt wird.

Jetzt holen wir noch den Titel des Blogeintrags:

Eine kleine Besonderheit gibt es mit dem Datum. Im Prinzip können wir das einfach holen:

Unschön dabei ist, dass wir es dann im Format "1. Januar 2014" haben. Deshalb wollen wir das etwas umformatieren und schreiben dazu ein eigenes Template. Um dies zu verstehen, benötigt man etwas Programmier-Kenntnisse – ich zeige es mal in der kommentierten Version unten und erkläre es nur andeutungsweise:

Dieses Template nimmt ein beliebiges Datum im Format "1. Januar 2014" auf (Zeile 72), zerlegt es in die Komponenten Tag, Monat und Jahr (Zeilen 77-87), ändert den Monat in eine Zahl um (Zeilen 93-106) und gibt das Datum neu formatiert zurück: 2014-01-01.

Wir können nun im Template, das die Datumsangabe findet, dieses Template "FormatDate" aufrufen:

Damit haben wir alle benötigten Regeln beisammen. Hier finden sich die Dateien zum Download:

Mit dem XSL-Stylesheet können die XHTML-Dateien nun mit einem XSL-Parser transferiert werden. Dafür gibt es mehrere Möglichkeiten:

Die XHTML-Datei Testdatei1.xhtml wird mittels des XSLT-Stylesheet oben in folgende XML-Datei überführt: