CGI-Wrapper und Server Pages bieten die Sicht eines Dokumentes auf eine
dynamische HTML-Seite. Diese lassen sich daher prinzipiell mit HTML-Editoren
bearbeiten. Nachteile von beiden sind die Abhängigkeit von bestimmten
Web-Servern oder speziellen Erweiterungen, teilweise benutzen sie eigene
Programmiersprachen und bieten je nach Anbindung eine schlechtere Performanz.
Zum einen muß für die Implementation der Methode keine eigenen Programmiersprache entwickelt werden. Eine eigene Programmiersprache läuft immer Gefahr, im Vergleich zu anderen existierenden Sprachen unvollständig zu sein. Sie muß gewartet und weiterentwickelt werden.
Zum anderen kann der Anwender der Methode die Programmiersprache auswählen, die seinen Anforderungen entspricht:
Eine einfache Anwendung und leicht verständlichen Konzepte sind entscheidend bei der Abschätzung des zusätzlichen Aufwandes zur Implementierung dynamischer HTML-Seiten.
Aus einem Html-Dokument, in dem dynamische Teile explizit markiert sind und das Programmfragmente einer beliebigen Sprache enthalten kann, erzeugt er Programmtext in der verwendeten Programmiersprache. Diesen kann man übersetzen und das Programm über die CGI-Schnittstelle ausführen. Die Ausgabe des Programms entspricht dem gewünschten dynamischen Html-Dokument.
reiner Html-Text | Reinen Html-Text muß der Präcompiler in Funktionsaufrufe der Zielsprache umgewandeln, die die Ausgabe des Textes bewirken. |
Variablen der Zielsprache | Um innerhalb von Html-Deklarationen z.B. in einer Zelle einer Tabelle
dynamische Werte anzuzeigen, habe ich ein Variablenersetzungs-Konzept realisiert.
Die Verwendung einer Variablen hat folgende Bedeutung: Gib an der Stelle
des Vorkommens den Wert der Variablen der verwendeten
Programmiersprache aus.Variablen werden von einem Html-Editor als normaler Html-Text angesehen und können direkt bearbeitet werden. Der Präcompiler ersetzt eine Variable durch einen Funktionsaufrufe, der ihren Wert ausgibt. |
Html-Muster (Pattern) | Pattern ermöglichen den Zugriff auf dynamische Teile des Html-Dokumentes, die in bestimmten Abhängigkeiten oder wiederholt auftauchen sollen. Sie sind eine Art Textbaustein, die innerhalb des Html-Dokumentes definiert und durch einen Bezeichner identifiziert werden. Sie werden somit bei der Bearbeitung des Html-Dokumentes mit einem Html-Editor an der Stelle ihrer Deklaration angezeigt und können bearbeitet werden. Das resultierenden Programm erzeugt an dieser Stelle keine Ausgabe, sondern muß einen explizierten Zugriff auf dieses Pattern realisieren. Sie können je nach verwendeter Zielsprache in Funktionen, Methoden oder Objekten bzw. in einer Hashtable abgebildet werden. |
eingebetteter Programmtext der Zielsprache | Je nach Einbettung kann der Programmtext im HTML-Editor angezeigt und bearbeitet werden. Der Präcompiler kann ausgelagerten Programmtext inkludieren. Somit kann man diesen auch mit anderen Tools bearbeiten. In das resultierende Programm übernimmt er ihn ohne weitere Bearbeitung. |
|
|
|
atBegin | keine | wird beim Start des Präcompilers aufgerufen |
atEnd | keine | wird bei Beendigung des Präcompilers aufgerufen |
beforeFile | wird vor dem Parsieren einer neuen Datei aufgerufen | |
Dateiname | Name der Datei die parsiert wird | |
afterFile | wird nach dem Parsieren einer neuen Datei aufgerufen | |
Dateiname | Name der Datei die parsiert wurde | |
atPattern | wird beim Auftreten eines Patterns aufgerufen | |
Identifier | Bezeichner des Patterns | |
ParamList | Liste der Parameter | |
Text | Html-Text des Pattern | |
atHTML | wird beim Auftreten von Html-Text aufgerufen | |
Text | Html-Text | |
atVariable | wird beim Auftreten einer Variablen aufgerufen | |
Variable | Bezeichner der Variablen | |
atProgramText | wird beim Auftreten von eingebettetem Programmtext aufgerufen | |
Identifier | Bezeichner des Programmtextes | |
Text | eingebetteter Programmtext |
Programmfragmente werden wie folgt gekennzeichnet:
<!-- exec [#begin|#end]
Programmtext
-->Eine Eigenschaft des Netscape Composer und wahrscheinlich auch anderer Html-Editoren ist es, keine Html-Kommentare vor dem <body>-Tag zuzulassen. Vom Netscape Composer wurde ein solcher Kommentar jedenfalls hinter das <body>-Tag verschoben. Dadurch ist eine besondere Kennzeichung der Fragmente erforderlich, die zu Beginn und am Ende des erzeugten Programms ausgeführt werden sollen.
<!-- exec #begin
Programmtext zu Beginn des Programms
-->
<!-- exec #end
Programmtext am Ende des Programms
-->
$Variable$Variablen sind syntaktisch nicht auf den Variablennamen beschränkt. Angenommen, es existiert ein Java-Objekt 's' der Klasse Stack, dann würde $s.pop()$ nach System.out.print(s.pop()) umgesetzt, wodurch das letzte Objekt des Stacks 's' ausgegeben wird. Es sind also, abhängig von der verwendeten Sprachumsetzung, komplexere Ausdrücke möglich.
<!-- pattern patternname [(Parameterliste)] -->
Html-Text des Pattern
<!-- /pattern -->In der exemplarischen Java-Umsetzung wird aus dem Pattern eine separate Methode erzeugt:
print_patternname(Parameterliste) {
System.out.print("Html-Text des Pattern");
}Diese Methode kann nun an beliebiger Stelle des Programms aufgerufen werden. Natürlich werden auch in den Pattern (wie oben beschrieben) Variablen ersetzt. Um die Ausgabe von lokalen Variablen zu realisieren, ist die Definition einer Parameterliste möglich, die unbearbeitet in die resultierende Methodendeklaration übernommen wird. Ihre Syntax ist also abhängig von der verwendeten Zielsprache.
Durch die Eigenschaft, daß Html-Editoren Kommentar-Tags in bestimmten Deklarationen verschiebt, ist es u.U. notwendig, ein Pattern größer zu definieren als eigentlich erforderlich. Dazu ein Beispiel: Sollen in einer Tabelle die aktuellen Kurswerte der DAX-Aktien angezeigt werden, reicht es eigentlich aus, die Deklaration des Tabellensatzes als Pattern zu definieren, da dies der sich wiederholende Teil der Tabelle ist:
<table>
<!-- pattern tablerecord (String var) -->
<TR> ... $var$ ... </TR>
<!-- /pattern -->
</table>Der Html-Editor verschiebt die <pattern>-Tags allerdings zum <table>-Tag, so daß die Definition des Pattern zerstört wird.
<!-- split tag1 [tag2 ... tagn] : teilpatternname1 teilpatternname2 [ ... teilpatternnamem] -->Dieses Tag muß innerhalb eines <pattern>-Tags definiert sein und bedeutet: zerlege das Pattern in Teilpattern patternname1bis patternnamem, die durch die Tags tag1oder tag2 oder tagngekennzeichnet sind. Im obigen Beispiel sieht die Lösung wie folgt aus.
<!-- pattern table1 (String var) -->
<!-- split TR : first# record last# -->
<table>
<TR> ... $var$ ... </TR>
</table>
<!-- /pattern -->In der exemplarischen Java-Implementation wird dies wie folgt umgesetzt:
print_table1_first() {
System.out.print("<table>\n");
}
print_table1_record(String var) {
System.out.print("<tr> ... ");
System.out.print(var);
System.out.print("... </tr>\n");
}
print_tabler1_last() {
System.out.print("</table>\n");
}Es werden also Methoden für den Zugriff auf die einzelnen Teilpattern erzeugt. In einem nachfolgenden Programmfragment kann die Tabelle wie folgt gedruckt werden:
<!-- exec
String var;
...
print_table1_first();
for (...;...;...) {
var = ...;
print_table1_record(var);
}
print_table1_last();
-->Die Anzahl der Namen der Teilpattern muß mit der Anzahl der Teilpattern übereinstimmen, die letztendlich angesprochen werden sollen. Werden die Teilpattern durch verschiedene Tags gekennzeichnet, können mehrere Separatoren im split-Tag angegeben werden.
<!-- #include file = "filename" -->
Das Modul uni.pm ist konfigurierbar, so daß keiner in Perl einsteigen muß, um die Erzeugung der Programmtextes entsprechend der gewählten Zielsprache anzupassen.
Der Sprachbezeichner gibt die Zielsprache des Erzeugungsmusters an und ist frei wählbar. Beim Aufruf des Präcompilers gibt die Option -l die Zielsprache an. Der Aufruf 'maxi.pl -l java test.html' legt beispielsweise Java als Zielsprache fest. Ist die Option nicht angegeben, bestimmt der Typ der Programmdatei (Option -f) die Zielsprache. Durch den Aufruf 'maxi.pl -f test.java test.html' wird also ebenfalls Java als Zielsprache festgelegt.[Sprachbezeichner.]Bezeichner_des_Erzeugungsmuster : Erzeugungstext
Ein Erzeugungsmuster bestimmt, welcher Programmtext generiert
werden soll. Erzeugungsmuster besitzen Bezeichner, von denen einige fest
zugewiesen sind. Das Modul uni.pm benutzt die Erzeugungsmuster zur Umsetzung
der oben beschriebenen Bestandteile eines dynamischen HTML-Dokuments.
Die Erzeugungsmuster haben Perl-Strings, der in seiner Sonderzeichenbehandlung
vergleichbar mit C oder Java ist.
|
|
text | reiner HTML-Text |
variable | Variablen
( $variable$ ) |
document | Umsetzung des gesamten HTML-Dokuments |
pattern | HTML-Muster
( <!-- pattern ... --> ) |
call | eingebettetes Programmfragment mit Bezeichner ohne Programmtext interpretiert
uni.pm als Methoden- / Funktionsaufruf
( <!-- exec method --> ) |
procedure | eingebettetes Programmfragment mit Bezeichner und mit Programmtext
( <!-- exec method statements --> ) |
comment | verwendet uni.pm für Generierungsanweisungen |
java.text : \tout.print(\"#text#\");\n
java.variable : \tout.print(#variable#);\n java.document : \npublic void printPage(PrintWriter out) {\n#text#\n}\n java.pattern : \npublic void print_#name#(PrintWriter out) {\n#text#\n}\n java.call : \t#name#(out);\n java.procedure : \npublic void #name# () {\n#text#\t}\n java.comment : \/\/ #text# \n body : #text# c.text : \tprintf(\"#text#\");\n c.variable : \tprintf(#variable#);\n c.document : \nvoid printPage() {\n#text#\n}\n c.pattern : \nvoid print_#name#() {\n#text#\n}\n c.call : \t#name#();\n c.procedure : \nvoid #name# () {\n#text#\t}\n c.comment : \/\* #text# \*\/\n |
|
|
|
#text# | text | reiner HTML-Text |
document | alle Statements zur Erzeugung des dynamischen HTML-Dokuments | |
pattern | alle Statements zur Erzeugung eines HTML-Musters | |
procedure | alle Statements eines <!-- exec name statements --> - Bereiches | |
comment | Kommentartext | |
#name# | pattern | Bezeichner des HTML-Musters |
call | Bezeichner eines <!-- exec name --> - Bereiches | |
procedure | Bezeichner eines <!-- exec name statements --> - Bereiches | |
#variable# | variable | Bezeichner einer Variablen ($variable$) bzw. Text zwischen den $-Zeichen |
In der Beispielkonfiuration wird zu den fest zugeordneten Erzeugungsmustern ein Erzeugungsmuster 'body' definiert. Dieses generiert nur den durch #text# erzeugten Text.
Beispiel
|
HTML-Text
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <meta name="Author" content="Oliver Boehm"> <meta name="GENERATOR" content="Mozilla/4.5 [de] (Win98; I) [Netscape]"> <title>Beispiel einer dynamischen HTML-Seite</title> </head> <body> <h1>Beispiel</h1>
|
Diese HTML-Seite habe ich im Netscape Composer erstellt. Sie definiert vier HTML-Muster (table_begin, table_head, table_row, table_end) und enthält ein <!-- exec -->- Bereich, der die Semantik eines Funktionsaufrufes hat, da er zwar einen Bezeichner besitzt, aber keine eigenen Statements definiert.
Die Programmdatei sieht initial wie folgt aus:
import java.io.*;
import java.util.*; public class Example extends Object { private Hashtable ht = null;
// Konstruktor
// "Daten"
public static void main(String args[]) { // Erzeugung des Objektes
// Methode zum Drucken der Tabelle
print_table_begin(out); print_table_head(out); for ( Enumeration e = ht.keys(); e.hasMoreElements();) { key = (String) e.nextElement();
print_table_end(out); } // ### generate document } |
Diese Programmdatei enthält eine Generierungsanweisung. Diese hat
folgendes Format:
Die Generierungsanweisung ist ein Java-Kommentar, damit das Programm
syntaktisch korrekt bleibt.
Die Anweisung '### generate document' bewirkt
die Umsetzung des gesamten HTML-Dokuments unter Verwendung des Erzeugungsmusters
document
und aller HTML-Muster unter Verwendung des Erzeugungsmusters pattern.
Das Ergebnis des Generierungsprozesses sieht wie folgt aus:
Die Anweisung '### generate document' wird durch den Programmtext für die Erzeugung des gesamten HTML-Dokuments (Methode printPage()) und der Pattern (table_begin, table_head, table_row, table_end) ersetzt.
Beginn eines Generierungsschrittes:
HTML-Muster : ist der
Bezeichner des generierten HTML-Musters
document : gibt
die Generierung des reinen HTML-Textes (Methode printPage()) an.
Erzeugungsmuster : bezeichnet das verwendete Erzeugungsmuster.
Diese Angabe des Erzeugungsmusters ist optional. Standard sind die fest zugeordneten Erzeugungsmuster.
Ende eines Generierungsschrittes:
Das Modul uni.pm hat die Methode print_table_row() entsprechend
des Erzeugungsmusters pattern mit einer anderen Schnittstelle
generiert:
Die Methodendeklaration kann man direkt in der Programmdatei ändern
und durch die Anpassung der Generierungsanweisungen bewirken, daß
diese bei zukünftigen Generierungen erhalten bleibt.
public void print_table_row(PrintWriter out, String wert1, String
wert2) {
// ### begin generation of table_row as body out.print("\t<tr>\n");
// ### end generation
|
Durch das Erzeugungsmuster 'body' generiert das Modul uni.pm wird in Zukunft nicht mehr die gesamte Methodendeklaration, sondern nur die erzeugenden Statements. So ist die Schnittstelle einer HTML-Muster erzeugenden Methode in der Programmdatei frei definierbar und bedarf keiner sprachabhängiger Deklarationen in der HTML-Datei.
Die Programmdatei kann man nun kompilieren. Die Ausführung des Programms bewirkt die Erzeugung des dynamischen HTML-Dokuments.
Beispiel
|
// ### config output : #html_base#\.#prog_ext#
import java.io.*;
import javax.servlet.http.*; // ### begin evaluation
// Bearbeitung des HTTP-Request
// Anfrage aufbereiten und
Daten aus einer Datenbank auslesen
// Ergebnis darstellen
} // ### generate document } |
Möchte man in einer Internet-Anwendung mittels einer Datenbank
Anfragen beantworten und das Ergebnis über einen Web-Server als HTML-Seite
repräsentieren, könnte man eine initiale Programmdatei, wie oben
gezeigt, für die Aufbereitung der Anfrage, den Zugriff auf die Datenbank
und das Bereitstellen der Ergebnismenge vorbereiten.
Aus objektorientierter Sicht würde man sicher eine Basisklasse
für diese Funktionalität bereitstellen. Um dieses Beispiel sprachübergreifend
zu gestalten, habe ich diesen Aspekt ignoriert.
Diese initiale Programmdatei könnte als einheitliche Grundlage
für die Verarbeitung unterschiedlicher Anfragen mit verschiedenen
Ergebnisaufbereitungen benutzt werden.
Dadurch kann der Prozeß zur Erstellung eines neuen dynamischen
Dokuments erheblich beschleunigt und vereinheitlicht werden.
Die Anweisung '### config output : #html_base#\.#prog_ext#' bewirkt eine Veränderung der Konfiguration des Moduls uni.pm aus der Programmdatei heraus.
Konfigurationsanweisungen haben folgende Syntax:
Es gibt zwei feste Bezeichner 'output' für den Namen
der Ausgabedatei (entspricht der Angabe der Option -f) und 'language'
für die Zielsprache (wird entsprechend der Option -l oder
des Typs der Programmdatei gesetzt). Alle anderen Konfigurationseinträge
ergeben sich aus der Konfigurationsdatei und können in der Programmdatei
überschrieben werden. Erzeugungsmuster kann man also überschreiben
oder neu erzeugen.
Im obigen Beispiel setze ich den Namen der Ausgabedatei neu, da sonst
die initiale Programmdatei überschrieben würde. Das Modul uni.pm
evaluiert den gesetzten Wert, wie ich es schon bei den Erzeugungsmustern
beschrieben habe. Zusätzlich verwende ich vier Platzhalter:
Ein Dateiname 'example.html' setzt sich laut dieser Beschreibung
aus dem Basisnamen 'example' (#html_base#) und dem Dateityp 'html'
(#html_ext#) zusammen.
Mit der Anweisung '### config output : #html_base#\.#prog_ext#' wird der Name der Ausgabedatei aus dem Basisnamen der HTML-Seite und dem Dateityp der Programmdatei zusammengesetzt (z.B. example.java).
Der Klassen-Name im obigen Beispiel ist gleich dem Basisnamen der HTML-Seite. Dies erreiche ich, indem ich uni.pm durch '### begin evaluation' anweise, den nachfolgenden Programmtext auszuwerten und mögliche Platzhalter zu ersetzen. Das Ende dieses Bereiches kennzeichne ich mit '### end evaluation'.
Es ist also möglich Vorlagen oder Templates bei der Generierung von dynamischen HTML-Dokumenten zu verwenden und im Ergebnis eine spezielle Programmdatei zu erzeugen.
[perl] maxi.pl [-m Spracherweiterung]
[-l Zielsprache]
[-c Konfigurationsdatei]
[-f Programmdatei] [-v] HTML-Datei
Der explizite Aufruf von Perl ist abhängig von der Ausführungsumgebung.
Unter Windows-Systemen wird er meisten benötigt.
Die Option -m gibt das Modul der Spracherweiterung an. Standard
ist uni.pm aus dem Verzeichnis des Präcompilers.
Die Optionen -l, -c und -f verarbeitet nur das Modul
uni.pm.
Ist die Option -l nicht angegeben, ermittelt uni.pm die Zielsprache
aus dem Dateitypen der Programmdatei.
Bei fehlender Angabe der Konfigurationsdatei (Option -c) verwendet
das Modul die Konfigurationsdatei 'uni.cfg' aus dem Verzeichnis des Präcompilers.
Ist keine Programmdatei angegeben (Option -f) benutzt das
Modul die Standardausgabe.
Die Option -v berwirkt die Ausgabe der Konfiguration.
Im Beispiel 'perl maxi.pl -f example.java example.html' wird
die HTML-Datei 'example.html' zur Definition der HTML-Ausgabe
verwendet und der erzeugende Programmtext in die Programmdatei 'example.java'
generiert. Der Präcompiler verwendet das Modul 'uni.pm' zur Generierung
des Programmtextes und dies benutzt die Erzeugungsmuster der Zielsprache
Java aus der Standardkonfiguration 'uni.cfg'.