Trennung von Struktur und Inhalt bei dynamisch erzeugten Seiten

Fragestellung

Seit einiger Zeit ist es auch für Betreiber privater Websites erschwinglich, Webspace zu mieten, der die Benutzung von serverseitigen Skriptsprachen und Datenbankanbindung gewährt. Somit wird auch vermehrt der Inhalt solcher Seiten dynamisch eingebunden. Damit ist gemeint, dass der Inhalt nicht mehr statisch in der HTML-Seite vorliegt, wie es beim puren Einsatz von HTML der Fall wäre. Vielmehr werden die Texte, zumeist handelt es sich um solche, extern in einer Datenbank oder zum Beispiel in Textdateien vorgehalten.

Dies hat den Vorteil, dass Änderungen an den betreffenden Texten schnell und nur an ihnen vollzogen werden können. Dabei kommt zum Beispiel ein Formular im Administrationsbereich der Seite zur Anwendung.

Um die Texte zur Anzeige zu bringen, wird eine serverseitige Skriptsprache benutzt. Dies kann beispielsweise Perl, PHP, Python oder auch ASP sein. Mit den entsprechenden Funktionen dieser Programmiersprachen werden die Texte in die Datenbank oder Textdatei geschrieben und auch wieder ausgelesen, um sie auf der Seite anzuzeigen.

Beim Auslesen zur Darstellung werden die Texte in den HTML-Quelltext eingefügt. Das Ergebnis dieses Vorgangs wird dann an den Anwender geschickt und im Browser angezeigt. Um einen Text für diese Darstellung aufzubereiten, bieten einige der Sprachen fertige Funktionen an, bei anderen Sprachen schreibt man sich diese selbst.

Bei allen diesen Funktionen, um die es hier geht, dreht es sich im Endeffekt darum, Zeilenumbrüche so umzuwandeln, dass sie auch mit HTML funktionieren, Sonderzeichen zu maskieren und Ähnliches.

Beispiel 1

Der folgende Quelltextschnipsel einer Textdatei zeigt einen Text, der keine Maskierungen für Umlaute enthält, sowie Zeilenumbrüche, die nicht dargestellt würden.

Dieser Text enthält Umlaute
und Zeilenumbrüche, wie Sand
am sprichwörtlichen Meer.

Die Zeilenumbrüche sind, so wie sie eingegeben wurden zwar vorhanden, wirken sich aber nicht auf die Darstellung im Browser aus. Die Umlaute sollten im deutschen Sprachraum ordnungsgemäß angezeigt werden, da wir davon ausgehen können, dass in diesem Raum die installierten Schriftarten auch über diese Zeichen verfügen. Trotzdem sollten sie maskiert werden, wie dies im maskierten Beispiel dieses Textes zu sehen ist. Die maskierung erfolgt mittels der PHP-Funktion htmlentities.

Dieser Text enth&auml;lt Umlaute<br>
und Zeilenumbr&uuml;che, wie Sand<br>
am sprichw&ouml;rtlichen Meer.

Die Maskierung ist wie folgt zu lesen: mit dem kaufmännischen UND & (Ampersand) beginnt die Maskierung, mit dem Semikolon ; endet sie. Dazwischen befindet sich ein Schlüsselwort, mit welchem dem Browser mitgeteilt wird, um welches Zeichen es sich handelt. Für die deutschen Umlaute und Sonderzeichen handelt es sich um folgende Werte.

Eine umfassendere Liste der Maskierungen von Sonderzeichen finden Sie in der Zeichenreferenz von SelfHTML. Wundern Sie sich jedoch nicht, falls Ihr Browser nicht alle der gezeigten Zeichen darstellen kann. Dies liegt an dessen Fähigkeiten und betrifft nicht nur den immer wieder gescholtenen MS Internetexplorer.

Jetzt sind nicht nur die Umlaute maskiert, auch die Zeilenumbrüche werden so, wie gewollt, angezeigt.

Beispiel 2

Einige typische BB-Codes und ihre HTML-Entsprechungen.

[b]Text[/b] = <b>Text</b>
[i]Text[/i] = <i>Text</i>
[link]http://www.example.com/[/link] = <a href="http://www.example.com/">http://www.example.com/</a>

Bei der programmiertechnischen Umsetzung dieser Vorgänge kommt es bei manchen Seitenbastlern zu logischen Fehlern. So meinen einige, der Einfachheit halber, die im Formular verfassten Texte sofort in einer HTML-Datei speichern zu wollen. Andere benutzen für im Text enthaltene HTML-Elemente BB-Codes, wie zum Beispiel für Links oder Formatierungen und wandeln diese bereits beim Speichern in die HTML-Entsprechungen um.

Von diesen Fehlern und ihrer Vermeidung soll im Folgenden die Rede sein.

Die Fehler und ihre Auswirkungen

Die obigen Fehler, insbesondere in Verbindung mit dem Bemühen, bei der Darstellung keine Fehler machen zu wollen, führen zu einem fehlerhaften Quelltext und daraus resultierend zu fehlerhafter Darstellung. Auch die spätere Änderung der Texte im Administrationsbereich wird dadurch wahrscheinlich erschwert.

Bei den im Folgenden beschriebenen Fällen gehe ich davon aus, dass die Inhalte über ein Formular in einem Administrationsbereich eingegeben wurden. Als Programmiersprache der Beispiele kommt PHP zum Einsatz.

Fall 1

Die eingegebenen Texte werden beim Speichern in eine HTML Vorlage eingefügt. Vordergründig ergibt sich der scheinbare Vorteil, dass die resultierende Seite "fertig" ist. Falls es sicher ist, dass diese Seite nicht mehr bearbeitet werden muss, ergeben sich keine Nachteile. Dann könnte die Seite aber auch offline erstellt werden und, fertig, wie sie ist, auf den Webspace übertragen werden. Wenn das Nichtbearbeitenmüssen aber nicht sichergestellt ist, wird es haarig.

Um den Text als Solches ändern zu wollen, muss er aus der Seite extrahiert werden. Dies bedeutet einen gewissen Aufwand bei der Programmierung der Administration. Schließlich muss genau dieser Text in der HTML-Datei gefunden werden und nach der Bearbeitung an der gleichen, alten Stelle wieder eingefügt werden.

richtiges Vorgehen: Der Text wird extra, ohne Maskierungen, abgelegt.

Fall 2

Der Text wird zwar extra gespeichert, es sind aber HTML-Elemente, zumBeispiel durch Umwandlung von BB-Code, enthalten. Auch dies ist grundsätzlich kein Problem. Wird der Text jedoch bearbeitet, werden die HTML-Elemente im Textfeld des Formulars mit angezeigt. Auch gleich beim Speichern vorgenommene Maskierungen von Sonderzeichen kommen beim Bearbeiten zur Anzeige. Der Umgang damit ist machbar, kann aber unbequem und unübersichtlich sein.

richtiges Vorgehen: Der Text wird roh, also mit den BB-Codes und (immernoch) ohne Maskierungen abgelegt.

Beide Fehler können auch in Kombination gemacht werden. Oder es kommen nur einzelne Elemente dieser Fehler vor. Zum Beispiel könnten BB-Codes in HTML überführt, aber Sonderzeichen nicht maskiert worden sein. Wenn jetzt noch Funktionen zum Einsatz kommen, die diese Maskierungen einfügen, sind die Auswirkungen, nun ja, verheerend für die Anzeige.

Beispiel 3

Der Text wird mit HTML-Elementen, resultierend aus BB-Code, aber ohne Maskierungen abgespeichert. Letztere sollen bei der Anzeige hinzugefügt werden.

Dies ist ein Text mit einem Link
zu einer <a href="http://www.example.com/">schönen Seite</a>.

Beim Aufruf der Seite wird der Text eingefügt und Sonderzeichen maskiert.

<?php
$text = "Dies ist ein Text mit einem Link
zu einer <a href=\"http://www.example.com/\">schönen Seite</a>.";

echo nl2br(htmlentities($text)); // erst maskieren dann Zeilenumbruch hinzufuegen
?>

So soll es nachher aussehen:

Dies ist ein Text mit einem Link
zu einer schönen Seite.

Die Funktion htmlentities maskiert jedoch nicht nur die Umlaute, sondern auch die Spitzen Klammern (<>), die HTML-Tags umschließen. Dies ist hier aber nicht gewollt. Die Funktion nl2br versieht ihren Dienst wie gewollt und wandelt den im Text enthaltenen Zeilenumbruch in den dafür vorgesehenen HTML Tag um. Die Funktion richtet sich dabei nach der XHTML-Syntax. Daher der Schrägstrich vor dem Ende des Tags. Würde die Funktion nl2br übrigens zuerst aufgerufen werden, würde auch der daraus resultierende HTML-Umbruch maskiert werden.

<!-- Ausgabe des Quelltextes: -->
Dies ist ein Text mit einem Link<br />
zu einer &lt;a href=\"http://www.example.com/\"&gt;sch&ouml;nen Seite&lt;/a&gt;.

Auf der Seite zu sehen ist somit:

Dies ist ein Text mit einem Link
zu einer <a href=\"http://www.example.com/\">schönen Seite</a>.

Es wird also der HTML-Quelltext des Links zu der "schönen Seite" angezeigt. Der Link ist somit unbenutzbar. So würde im Übrigen auch die Anzeige im Textfeld der Administration aussehen. Wenn dann mehr als nur dieser eine Satz bearbeitet werden soll, und sich mehrere, vielleicht auch längere HTML-Tags im Text tummeln, wird es schnell unübersichtlich.

Dieses Beispiel beinhaltet Teile beider oben angeführter Fehler. Es soll nur einige der möglichen Auswirkungen zeigen.

Konsequenzen

Um in diesem Zusammenhang diese und andere Stolperfallen zu vermeiden bietet sich praktisch nur ein Weg an. Die vollständige Trennung von Layout und Inhalt, soweit dieser veränderlich ist. Wenn die Texte roh, also unbehandelt, in der Datenbank oder Datei liegen, sind sie ohne Aufwand zu bearbeiten, weil keine Maskierungen und HTML-Elemente zu beachten oder auch umzuwandeln sind. So wie sie sind, kann man sie im Textfeld des Formulars der Administration aufrufen und wieder speichern. Und dies inclusive etwaiger BB-Codes, mit denen man einfach umgehen kann, da sie sehr verbreitet sind.

Erst bei der Aufbereitung zur Anzeige, also wenn das Dokument, in dem diese Inhalte eingefügt werden, durch einen Browser angefordert wird, werden Umwandlungen und Maskierungen vorgenommen.

echo parse_string(nl2br(htmlentities($text)));

Die Anweisungen werden von innen nach außen ausgeführt. Zuerst werden Sonderzeichen, wie die deutschen Umlaute und das ß, maskiert. Danach werden mittels nl2br Zeilenumbrüche in das HTML-Pendant, und dann im Text vorhandene BB-Codes in HTML-Code umgewandelt. Hier dient dazu die Funktion parse_string, die auf www.mylittlehomepage.net herunterladen kann.