Cocoon Logicsheet Tutorial

Autor:
Thomas Bayer
Orientation in Objects GmbH
Thomas Bayer
Thomas Bayer
Datum:September 2002

Dieses Tutorial beschreibt den Einsatz von bestehenden Logicsheets in eXtensible Server Pages und die Entwicklung eigener Logicsheets. An einem Beispiel wird Schritt für Schritt demonstriert, wie Code von einer Server Page in ein Logicsheet verschoben werden kann. Für dieses Tutorial sind grundlegende Cocoon und XSP Kenntnisse notwendig.

Dieses Tutorial beschreibt den Einsatz von bestehenden Logicsheets in eXtensible Server Pages und die Entwicklung eigener Logicsheets. An einem Beispiel wird Schritt für Schritt demonstriert, wie Code von einer Server Page in ein Logicsheet verschoben werden kann. Für dieses Tutorial sind grundlegende Cocoon und XSP Kenntnisse notwendig.

Logicsheets

Für JavaServer Pages gibt es eine Reihe von Bibliotheken mit Tags, die dem Entwickler neben den Standard Tags zur Verfügung stehen. Diese Bibliotheken bezeichnet man in der Java Server Pages Entwicklung kurz als Taglibs. Im Jakarta Project der Apache Software Foundation sind einige unter http://jakarta.apache.org/taglibs zu finden. Es gibt Bibliotheken mit Tags unter anderem für den Zugriff auf Datenbanken, Internationalization und Logging.

Für Apache Cocoon sind ebenfalls Bibliotheken mit Tags für die eXtensible Stylesheet Language kurz XSP verfügbar. Einige dieser Bibliotheken werden als buildin Logicsheets mitgeliefert, weitere kann man sich über das Internet besorgen und integrieren. Die Entsprechung von Taglibs sind bei Cocoon Logicsheets, die mit einem zugehörigen Stylesheet realisiert werden. Ein Logicsheet ist ein Filter in Form eines XSLT Stylesheets, welches benutzerdefinierten Markup in Programmcode übersetzen kann. Logicsheets ermöglichen erst die Trennung der Logik von Präsentation und Inhalt. Autoren, die nicht mit einer Programmiersprache wie Java vertraut sind können mit den Tags eines Logicsheets arbeiten und dynamische Anwendungen realisieren.

Buildin Logicsheets

Es gibt nur wenige grundlegende Tags in XSP. Diese beginnen alle mit dem Prefix xsp. Weitere Tags mit nützlichen Funktionen werden in verschiedenen Bibliotheken den sogenannten Logicsheets angeboten. Wie man selbst Logicsheets erstellen kann wird später in "Erstellen von Logicsheets" behandelt.

Dem Entwickler einer XSP Anwendung steht eine Reihe von buildin Tag Bibliotheken zur Verfügung. Die folgende Auflistung gibt einen Überblick der einzelnen buildin Logicsheets.

action

Diese Bibliothek kann zusammen mit dem Front Controller und Befehlsmuster eingesetzt werden. Ein Redirect kann mit einen Tag ausgelöst und auf eine Result Map kann zugegriffen werden.

capture

In bestimmten Fällen möchte man XML Elemente mit XSP erzeugen, diese jedoch nicht ausgeben sondern in einer Variable für andere Zwecke speichern. Für diesen Einsatz ist das Capture Logicsheet gedacht.

esql

Die esql Taglib ermöglicht den Zugriff auf eine relationale Datenbank mit SQL Statements aus einer Server Page. Für die Zugriffe wird ein Connection Pool verwendet.

form-validator

Mit der FormValidatorAction können die über Formulare eingegebenen Werte validiert werden. Mit Hilfe der form-validator Taglib kann auf das Ergebnis der Validierung zugegriffen werden.

Log

Eine Infrastruktur für Logging ist besonders bei der Entwicklung und dem Betrieb von Web Anwendungen hilfreich.

sendmail

Zum Versenden von eMail mit der Java Mail API.

soap

Mit dem SOAP Logicsheet kann auf Web Services von XSP Seiten komfortabel zugegriffen werden.

Verwendung von Logicsheets

Requests

Die Verwendung von Tags eines bestehenden Logicsheets wird am Beispiel des Request Logicsheets beschrieben.

Für das Auslesen der Daten einer Client-Anfrage kann das Request Logicsheet verwendet werden. Dieses kapselt den Zugriff auf Objekte der Klasse HttpServletRequest aus dem Servlet API. Die häufigste Verwendung des Logicsheets ist das Auslesen von Forumlarinhalten.

Bevor ein Logicsheet verwendet werden kann, muss Cocoon mitgeteilt werden, daß auf einer Seite die Bibliothek eingesetzt werden soll. Dies geschieht über die Angabe eines Namespace im xsp:page Element. Wir ordnen die URI http://apache.org/xsp/request/2.0 dem Prefix xsp-request zu, wie aus Beispiel 1.1 ersichtlich. Nach der Deklaration des Namespaces können wir in unserer XSP Seite eine Reihe von Tags für das Auslesen verschiedener Informationen aus dem Request verwenden.

Beispiel 1.1. Parameter "benutzer" auslesen

<?xml version="1.0" encoding="UTF-8"?>
  <xsp:page language="java"
            xmlns:xsp="http://apache.org/xsp"
            xmlns:xsp-request="http://apache.org/xsp/request/2.0">
    <seite>
      <para> Hi <xsp-request:get-parameter name="benutzer"/> </para>
    </seite>
</xsp:page>

Im Beispiel lesen wir mit xsp-request:get-parameter den über das Attribut name angegebenen Parameter "benutzer" aus. Dieser Parameter könnte von einem Formular übergeben worden sein. Faul wie Programmierer sind, testen wir die XSP Seite zunächst ohne Formular. Wir können in die URL kodiert einen Parameter übergeben:

http://localhost:8080/cocoon/seminar/request-demo.xsp?benutzer=Joe

Mit diesem Aufruf sollte jetzt Joe gegrüßt werden.

Erstellen von eigenen Logicsheets

Im folgenden werden wir erfahren, wie man selbst Logicsheets erstellen kann. Wir betrachten zunächst Beispiel 1.2. Eine normale XSP mit einen Logik Block und einer Expression. Eine Zufallszahl im Bereich von 0 bis 100 wird erzeugt und ausgegeben. In dieser XSP wird Logik in Form des Logic Blockes und der Expression mit Inhalt z.B. dem seite-Tag vermischt. Logik und Inhalt können wir später durch die Verwendung eines Logicsheets trennen.

Beispiel 1.2. XSP mit Zufallszahl

<?xml version="1.0" encoding="UTF-8"?>
<xsp:page language="java"
          xmlns:xsp="http://apache.org/xsp">
    <seite>
        <xsp:logic>int groesse = 100;</xsp:logic>
        <xsp:expr>Math.round((Math.random() * groesse))</xsp:expr>
    </seite>
</xsp:page>

Hätten wir ein Logicsheet mit einem zufall:zahl Tag könnten wir dieses für die Erzeugung der Zufallszahl verwenden. Beispiel 1.3 zeigt die XSP unter Verwendung eines solchen Logicsheets. Die XSP enthält jetzt keine Logik mehr. Inhalt und Logik wurden getrennt. Mit mächtigen Logicsheets können ohne Programmierung Anwendungen erstellt werden.

Damit ein Logicsheet innerhalb einer XSP verwendet werden kann, muss zusätzlich zum Namespace Prefix xsp ein weiterer Prefix und eine zugehörige URI spezifiziert werden. In unserem Fall, das Prefix zufall und die URI http://oio.de/zufall.

Beispiel 1.3. Tag für Zufallszahlen

<?xml version="1.0" encoding="UTF-8"?>
<xsp:page language="java"
          xmlns:xsp="http://apache.org/xsp"
          xmlns:zufall="http://oio.de/zufall">
    <seite>
        <zufall:zahl groesse="10" />
    </seite>
</xsp:page>

Die Logik können wir in ein Logicsheet verbannen. Ein solches Logicsheet finden Sie in Beispiel 1.4. Es handelt sich um ein XSLT Stylesheet, welches die Tags in Logik Blöcke und Ausdrücke übersetzt. Im Stylesheet wird wieder der Prefix zufall der URI http://oio.de/zufall zugewießen. Ein Template mit dem Matchpattern zufall:zahl übersetzt den Tag der XSP in einen Ausdruck, der die Zufallszahl erzeugt. Die maximale Größe der Zufallszahl übergeben wir mit einem Attribut und bauen dieses in die Berechnung der Zufallszahl ein. Das Zweite Template sorgt dafür, daß alle übrigen Tags einfach in die Ausgabe kopiert werden. Würde dieses Template fehlen, so würden alle Tags, die nicht von diesem Logicsheet verarbeitet werden einfach ausgefiltert.

Beispiel 1.4. Logicsheet für Zufallszahlen

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xsp="http://apache.org/xsp" xmlns:zufall="http://oio.de/zufall">
    <xsl:template match="zufall:zahl">
        <xsp:expr>
            Math.round( (Math.random() *
            <xsl:value-of select="@groesse" />
            ) )
        </xsp:expr>
    </xsl:template>
    <xsl:template match="@*|*|text()|processing-instruction()">
        <xsl:copy>
            <xsl:apply-templates select="@*|*|text()|processing-instruction()" />
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

Bevor wir das Logicsheet einsetzen können, müssen wir es Cocoon bekanntmachen. Dafür nehmen wir einen Eintrag in der Datei cocoon.xconf vor. Wir finden diese Datei in COCOON_HOME/WEB-INF. Beispiel 1.5 zeigt einen Auszug aus cocoon.xconf. Dort finden wir auch Angaben zu den buildin Logichsheets session, request, sel oder esql. Wir können diese als Vorlage verwenden, wenn wir selbst ein Logicsheet eintragen. Im Gegensatz zu den buildin Logicsheets verweisen wir meist nicht auf ein JAR Archiv, sondern direkt auf eine Datei. Mit dem Pseudoprotokoll "context" können wir auf COCOON_HOME verweisen. Im Beispiel befindet sich das Logicsheet in context://taglib/zufall.xsl. Im Filesystem entspricht dies der Datei COCOON_HOME/taglib/zufall.xsl.

Beispiel 1.5. Auszug aus cocoon.xconf

</xsp-language>
  <target-language>
    <builtin-logicsheet>
      <parameter name="prefix" value="zufall" />
      <parameter name="uri" value="http://oio.de/zufall" />
      <parameter name="href" value="context://taglib/zufall.xsl" />
    </builtin-logicsheet>
  </target-language>
</xsp-language>

Die maximale Größe der Zufallszahl möchten wir nicht hart in die XSP codieren sondern dynamisch zur Laufzeit bestimmen. Wir könnten die Größe als Request Parameter übergeben. In die URL codiert sähe das so aus:

http://localhost:8080/cocoon/cd/zufall.xsp?groesse=1000

Leider können wir mit Attributen nicht dynamisch erzeugte Werte an unser Logicsheet übergeben. Die Verwendung von xsp:attribute funktioniert leider nicht, da das Core Logicsheet xsp.xsl, welches die eigentlichen xsp Tags übersetzt erst nach unserem eigenen Logicsheet aufgerufen wird. Ein Schachteln von Tags verschiedener Librarys wie in Beispiel 1.6 würde das Problem lösen.

Beispiel 1.6. Zufall XSP

<zufall:zahl>
    <groesse>
        <xsp-request:get-parameter name="groesse" />
    </groesse>
</zufall:zahl>

Generell sollten die Elemente eines Logicsheets beide Arten der Parameterübergabe unterstützen. Die Übergabe per Attribut für eine komfortable kurze Schreibweise und die Übergabe per Kindelement für errechnete, dynamische Parameter. Damit wir Parameter auf die eine oder andere Weise übergeben können führen wir eine Variable für jeden Parameter ein. In unserem Beispiel in Beispiel 1.7 die Variable "groesse". Der Wert der Variable wird durch die Auswertung des Inhaltes des Elementes xsl:variable bestimmt. Im xsl:choose Block prüft das erste xsl:when, ob es ein Attribut "groesse" gibt. Ist dies der Fall wird der Wert des Attributes für die Variable "groesse" verwendet. Falls es ein Kindelement mit dem Namen "groesse" gibt, wir das named-Template get-nested-content aufgerufen, welches den Wert anhand des Inhaltes des Elementes "groesse" bestimmt. Wie das named-Template get-nested-content funktioniert, wird im nächsten Abschnitt beschrieben.

Beispiel 1.7. Auslesen von Parametern

<xsl:template match="zufall:zahl">
    <xsl:variable name="groesse">
        <xsl:choose>
            <xsl:when test="@groesse">
                "
                <xsl:value-of select="@groesse" />
                "
            </xsl:when>
            <xsl:when test="groesse">
                <xsl:call-template name="get-nested-content">
                    <xsl:with-param name="content" select="groesse" />
                </xsl:call-template>
            </xsl:when>
        </xsl:choose>
    </xsl:variable>
    <xsp:expr>
        Math.round( (Math.random() * Integer.parseInt(
        <xsl:value-of select="$groesse" />
        )) )
    </xsp:expr>
</xsl:template>

Nachdem wir den Wert der Variablen "groesse" bestimmt haben, können wir die Variable in der Expression für die Erzeugung der Zufallszahl einsetzten. Der Inhalt der Variablen "groesse" bekommen wir als String in Anführungszeichen eingebettet zurück. Beispielsweise:

"1000"

Für unsere Berechnung benötigen wir jedoch einen Integer. Mit der Wrapper Klasse Integer und der Methode parseInt können wir den String mit der Größe in einen int umwandeln. Für die Ausführung unseres Beispiels fehlt uns nur noch das named Template get-nested-content.

Das get-nested-content Template

Die Logicsheets werden nacheinander angewandt. Logicsheets können so gestaltet werden, daß eine Verschachtelung von Tags verschiedener Libraries wie Beispiel 1.8 zeigt möglich ist. Der Parameter groesse des Zufalls Tags wird vom xsp-request:get-parameter Tag der request Taglib errechnet. Die Implementierung des zufall:zahl Tags muß damit dies möglich wird, verschachtelten Inhalt unterstützen. In verschiedenen buildin Libraries wird für diesen Zweck ein spezielles Template verwendet. Wir können dieses Template in unser Logicsheet kopieren und ebenfalls verwenden.

Beispiel 1.8. Zufall XSP

<zufall:zahl>
    <groesse>
        <xsp-request:get-parameter name="groesse" />
    </groesse>
</zufall:zahl>

Bevor wir das Template untersuchen, betrachten wir zunächst, was Apache Cocoon mit einem verschachtelten Tag macht. Der Quellcode einer XSP wird mit einem Stylesheet, welches hier Logicsheet genannt wird von einem XSLT Prozessor umgewandelt. Nehmen wir an, daß das erste Stylesheet in unserem Beispiel zufall.xsl ist. Nach der Umwandlung erhalten wir folgenden Markup:

Beispiel 1.9. Nach der Anwendung von zufall.xsl

<xsp:expr>
    Math.round( (Math.random() * Integer.parseInt(
    <xsp-request:get-parameter name="groesse" />
    )));
</xsp:expr>

Das Logicsheet request.xsl wird als nächstes angewandt. Nach der Ausführung erhalten wir folgendes Ergebnis:

Beispiel 1.10. Nach der Anwendung von request.xsl

<xsp:expr>
    Math.round( (Math.random() * Integer.parseInt(
    <xsp:expr>
        (XSPRequestHelper.getParameter( objectModel, "groesse", null, null, null))
    </xsp:expr>
    )));
</xsp:expr>

Jetzt muss das core Logicsheet xsp.xsl angewandt werden, welches sich um die xsp Tags kümmert. Danach wurde das zufall:zahl Tag vollständig in Java Code umgewandelt, der jetzt in etwa so aussieht:

Beispiel 1.11. Erzeugter Code

XSPObjectHelper.xspExpr(
    contentHandler, Math.round(
        Math.random() * Integer.parseInt(
            XSPRequestHelper.getParameter(objectModel, "groesse", null, null, null)
        )
    )
);

Betrachten wir das Template get-nested-content in Beispiel 1.13, welches das Schreiben von Tags mit Übergabeparametern erleichtert. Das Template besitzt anstatt eines match ein name Attribute. Man bezeichnet es daher als named Template. Mit xsl:call-template können wir named Templates aufrufen. Beim Aufruf übergeben wir als Parameter den Knoten, der den verschachtelten Inhalt enthält.

Beispiel 1.12. Call Template

<xsl:call-template name="get-nested-content">
  <xsl:with-param name="content" select="groesse" />
</xsl:call-template>

Im Template wird geprüft, ob dieser Knoten Kindknoten enthält. Ist dies nicht der Fall, wird einfach der Inhalt des Knotens in Text umgewandelt und ausgegeben. Enthält der Knoten Kindknoten, so wird für diese Kindknoten passende Regeln gesucht.

Beispiel 1.13. get-nested-content Template

<xsl:template name="get-nested-content">
    <xsl:param name="content" />
    <xsl:choose>
        <xsl:when test="$content/*">
            <xsl:apply-templates select="$content/*" />
        </xsl:when>
        <xsl:otherwise>
            "
            <xsl:value-of select="$content" />
            "
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

Da wir im Stylesheet zufall.xsl kein spezielles Template für ein Element xsp-request:get-parameter haben, greift die Regel für das Kopieren von unbekannten Elementen, die wir in jedes Logicsheet einbauen sollten. Das in Beispiel 1.14 abgebildete Template kopiert Attribute, Knoten, Text und Prozessing Instruktionen einfach in das Ergebnis.

Beispiel 1.14. Kopieren unbehandelter Elemente

<xsl:template match="@*|*|text()|processing-instruction()">
    <xsl:copy>
        <xsl:apply-templates select="@*|*|text()|processing-instruction()" />
    </xsl:copy>
</xsl:template>

Beispiel 1.15 zeigt das vollständige Logiksheet zufall.xsl. Wir haben jetzt eine einfache Taglibrary erstellt. Schon bei diesem relativ kleinen Logicsheet fällt auf, dass die Vermischung von Java Code mit XSLT schnell unübersichtlich werden kann. Hilfsklassen helfen, Java Code von XSLT zu trennen.

Beispiel 1.15. zufall Logicsheeet

<?xml version="1.0"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:xsp="http://apache.org/xsp" xmlns:zufall="http://oio.de/zufall">
        <xsl:template match="zufall:zahl">
            <xsl:variable name="groesse">
                <xsl:choose>
                    <xsl:when test="@groesse">
                        "
                        <xsl:value-of select="@groesse" />
                        "
                    </xsl:when>
                    <xsl:when test="groesse">
                        <xsl:call-template name="get-nested-content">
                            <xsl:with-param name="content" select="groesse" />
                        </xsl:call-template>
                    </xsl:when>
                </xsl:choose>
            </xsl:variable>
            <xsp:expr>
                Math.round( (Math.random() * Integer.parseInt(
                <xsl:value-of select="$groesse" />
                )) )
            </xsp:expr>
        </xsl:template>
        <xsl:template name="get-nested-content">
            <xsl:param name="content" />
            <xsl:choose>
                <xsl:when test="$content/*">
                    <xsl:apply-templates select="$content/*" />
                </xsl:when>
                <xsl:otherwise>
                    "
                    <xsl:value-of select="$content" />
                    "
                </xsl:otherwise>
            </xsl:choose>
        </xsl:template>
        <xsl:template match="@*|*|text()|processing-instruction()">
            <xsl:copy>
                <xsl:apply-templates select="@*|*|text()|processing-instruction()" />
            </xsl:copy>
        </xsl:template>
    </xsl:stylesheet>

Hilfsklassen

Mit XSLT lassen sich sehr mächtige Code Generatoren erstellen. Ein Logicsheet stellt auch eine Art Code Generator dar, der aus dem Markup Code einer XSP Java Code erzeugt. Der Java Code ist im Logicsheet in xsp:logic und xsp:expr Tags enthalten. Schon einfache Logicsheets werden schnell unübersichtlich und sind schwer zu warten. Wir sollten möglichst viel Java Code aus dem Logicsheet in separate Java Klassen auslagern. Diese Klassen werden Hilfsklassen genannt.

Die Parameter eines Tags, in Form von Attributen und Kindelementen können an eine statische Methode einer Hilfsklasse übergeben werden.

Bereits das einfache Template für die Zufallszahlen wird übersichtlicher durch die Verwendung einer Hilfsklasse. Wir lesen wie zuvor den Parameter groesse aus und übergeben diesen an die Hilfsklasse ZufallHelper. Auf diese Weise können auch mehrere Parameter übergeben werden. Pro Parameter wird eine Variable mit dem choose Block und dem Aufruf von get-nested-content benötigt.

Beispiel 1.16. zufall.xsl mit Hilfsklasse

<xsl:template match="zufall:zahl">
    <xsl:variable name="groesse">
        <xsl:choose>
            <xsl:when test="@groesse">
                "
                <xsl:value-of select="@groesse" />
                "
            </xsl:when>
            <xsl:when test="groesse">
                <xsl:call-template name="get-nested-content">
                    <xsl:with-param name="content" select="groesse" />
                </xsl:call-template>
            </xsl:when>
        </xsl:choose>
    </xsl:variable>
    <xsp:expr>
        de.oio.zufall.ZufallHelper.zahl(
        <xsl:value-of select="$groesse" />
        )
    </xsp:expr>
</xsl:template>

Die Hilfsklasse ZufallHelper ist eine normale Java Klasse mit der statischen Methode "zahl". Der Parameter groesse wird als String übergeben und in der Methode "zahl" in einen Integer umgewandelt. Wir ersparen uns damit die Umwandlung im Logicsheet. Wir können in einer Hilfsklasse mehrere Methoden für mehrere Templates unterbringen oder für jedes Template eine eigene Klasse verwenden.

Beispiel 1.17. Hilfsklasse ZufallHelper

package de.oio.zufall;
public class ZufallHelper {
  public static long zahl( String groesse) {
    return Math.round(
      (Math.random() * Integer.parseInt(groesse))
    );
  }
}

Hilfsklassen stellen normale Java Klassen dar, die wir in einer beliebigen Java Entwicklungsumgebung erstellen, kompilieren, testen und debuggen können. Wir vermeiden damit unnötige und mühselige Fehlersuche im Logicsheet. Hilfsklassen ermöglichen uns überdies eine bessere Trennung von Markup und Java Code.

Cocoon muss in der Lage sein, die übersetzte Hilfsklasse zu laden. Wir haben dafür verschiedene Möglichkeiten. Entweder wir legen die Class Datei ins Verzeichnis COCOON_HOME/WEB-INF/classes oder wir packen das Class File in ein Jar Archiv und legen dieses ins Verzeichnis COCOON_HOME/WEB-INF/lib.

Innerhalb eines Logicsheets sollten so wenig wie möglich Java Variablen verwendet werden. Es besteht die Gefahr, daß eine Variable mit dem selben Namen in der XSP oder in anderen Logicsheets ebenfalls verwendet wird, was zu einem Übersetzungsfehler des generierten Java Codes führen kann, sofern die Variablen sich nicht in separaten Blöcken befinden. Die Verwendung von Hilfsklassen kann die Zahl der notwendigen Java Variablen im Logicsheet reduzieren.

Im Template zufall:zahl stört die Angabe des kompletten Klassennames de.oio.zufall.ZufallHelper. Statt dessen soll ein import Statement verwendet werden. Wie man import Statements, Instanzvariablen und Methoden über ein Logicsheet in den resultierenden XSP Generator einbaut, beschreibt der nächste Abschnitt.

Klassenebene

Der aus einer XSP generierten Generator Klasse können Instanzvariablen, Methoden und Import Statements hinzugefügt werden. Beispiel 1.18 zeigt den Aufbau einer XSP und wie man an bestimmten Stellen der generierten Klassen Code hinzufügt. Über ein Logicsheet kann ebenfalls Code auf Klassenebene oder Import Statements hinzugefügt werden.

Wir möchten de.oio.zufall.* in der Generator Klasse importieren, damit wir die Klassen dieses Packages im Logicsheet verkürzt angeben können. Ferner bauen wir die Instanzvariable "letzteZufallszahl" und eine passende getter Methode ein. Ein Template für xsp:page im Logicsheet ermöglicht Code an den entsprechenden Stellen einzufügen. Beispiel 1.18 zeigt ein solches Template für das bisher beschriebene zufall.xsl Logicsheet.

Wir müssen beachten, dass unser Logicsheet nicht das einzigste ist, welches die Entwickler einsetzen möchten und dass in der XSP selbst xsp:structure und xsp:logic im benutzerdefinierten root Element verwendet werden. Aus diesen Gründen müssen einige Punkte bei der Erstellung des Templates beachtet werden. Damit nach der Anwendung des Logicsheets das xsp:page Element noch vorhanden ist, legen wir für die Ausgabe ein neues xsp:page Element an. Da das ursprüngliche xsp:page Tag möglicherweise einige Attribute wie Namespace Deklarationen bessen hat, müssen wir diese Attribute in das neu erzeugt xsp:page Element kopieren. Das folgende apply-templates erledigt dies für uns.

<xsl:apply-templates select="@*" />

Für die Attribute werden Templates gesucht. Das Standard Kopie Template aus Beispiel 1.14, welches wir bereits betrachtet haben, erledigt das Kopieren für uns. Neben Attributen kann das ursprüngliche xsp:page Element auch Kindelemente enthalten. Diese werden am Ende unseres Templates mit einem einfachen apply-templates zusammen mit dem Kopier Template übernommen. Für das Kopieren von Elementen und Attributen, die wir nicht verarbeiten und nicht ausfiltern dürfen, müssen wir in jedem Logicsheet das Kopier Template einbauen.

Diese Massnahmen sogen dafür, dass das Template für xsp:page keinen Schaden durch das Ausfiltern benötigter Tags und Attribute anrichtet. Im Template für xsp:page können dem Element xsp:page vom Logicsheet weitere Kindelemente hinzugefügt werden. Im Beispiel ist dies ein xsp:structure Block für den Import von de.oio.zufall.* und ein Logik Block mit der Instanzvariablen "letzteZufallszahl" und der Methode "getLetzteZufallszahl".

Beispiel 1.18. Template für xsp:page

<xsl:template match="xsp:page">
    <xsp:page>
        <!-- Übernehmen von bisherigen Attributen
            von xsp:page-->
        <xsl:apply-templates select="@*" />
        <xsp:structure>
            <xsp:include>de.oio.zufall.*</xsp:include>
        </xsp:structure>
        <xsp:logic>
            private long letzteZufallszahl; public long getLetzteZufallszahl() { return
            letzteZufallszahl; }
        </xsp:logic><!-- Übernehmen des bisherigen Inhaltes von xsp:page -->
        <xsl:apply-templates />
    </xsp:page>
</xsl:template>

Die Auswirkungen auf die Generator Klasse zeigt Beispiel 1.19. Wir finden den Import, die Instanzvariable sowie die Methode im erzeugten Code.

Beispiel 1.19. Erzeugter Code

...
/* User Imports */
import de.oio.zufall.*;

/** * Generated by XSP. Edit at your own risk, :-) */
public class zufall_xsp extends XSPGenerator {
    ...
    /* User Class Declarations */
    private long letzteZufallszahl;
    public long getLetzteZufallszahl() {
        return letzteZufallszahl;
    }
    ...
}

Zusammenfassung

Erst Logicsheets ermöglichen eine saubere Trennung von Inhalt und Logik. Die Übergabe von Parametern an Tags eines Logichsheets sollten per Attribut und Kindelement möglich sein. Werden Kindelemente für die Parameterübergabe verwendet, sollten String Konstanten und Ausdrücke in Form von xsp:expr oder Tags anderer Logicsheets möglich sein.

Ich hoffe, der Artikel hat Ihnen gefallen. Über ein Feedback von Ihnen würde ich mich freuen.

Zum Geschaeftsbreich Competence Center
Artikel
Das Tutorial XSP Einführung führt in die Entwicklung mit XSP ein