URL dieses Artikels:

zu Ausgabe: 03.2002
Die Verpuppung
XML-Anwendungen erstellen mit dem Cocoon 2, Teil 1
Von Matthew Langham und Carsten Ziegeler
Bereits bei der Vorstellung von Cocoon 1.8 Java Magazin war ein zweiter Entwicklungszweig innerhalb des Apache Open Source-Projekts Cocoon vorhanden. Der geistige Vater von Cocoon, Stefano Mazzocchi, begann die Version 2.0 von Cocoon im November 1999. Mit der Freigabe der Version 2.0 Ende letzten Jahres liegt nun eine stabile und leistungsfähige XML-Lösungsplattform vor. Das Cocoon-Projekt hat beschlossen nur noch diesen neuen Entwicklungszweig weiterzuführen, daher wird keine Versionsnummer im Namen geführt. Dieser 2-teilige Artikel stellt die neue Version von Cocoon vor und demonstriert anhand von einigen Beispielen die Einsatzmöglichkeiten. Der erste Teil stellt eine einführende Übersicht dar, der zweite wird sich tiefer mit den zugrundeliegenden Technologien beschäftigen.

Die grundlegenden Ziele und Prinzipien von Cocoon 1.x haben selbstverständlich auch in der neuesten Version Bestand. Die Hauptaufgabe von Cocoon besteht in der einfachen Entwicklung von Web-Anwendungen. Nach wie vor steht die Trennung der Zuständigkeiten bei der Entwicklung von Internet-Anwendungen im Vordergrund: die strikte Trennung von Daten, Logik und Layout. Ein Layouter soll sich nicht mit Datenakquisition beschäftigen müssen und ein Anwendungsprogrammierer nicht mit dem Layout. Gerade diese Trennung unterscheidet Cocoon von anderen Technologien wie beispielsweise ASP oder JSP. Gemein ist allen Ansätzen, dass die angefragten Dokumente - meist HTML-Seiten - dynamisch zur Laufzeit generiert werden. Die Notwendigkeit einer XML/XSL-basierten Plattform um flexible Middleware-Lösungen zu erstellen, lässt sich auf Grund der gewachsenen Anforderungen an Internet-Anwendungen begründen. So gibt es heute eine Vielzahl von internetfähigen Endgeräten. Da diese Geräte und auch die Anwendungen aber unterschiedliche Darstellungsformate erwarten, muss eine flexible Technologie wie XSL eingesetzt werden, um diese Formate dynamisch aus den gleichen Daten zu erzeugen. Es reicht nicht mehr aus, den Inhalt lediglich in HTML darzustellen, sondern es sind vielmehr weitere Formate wie PDF zum Drucken oder WML für mobile Geräte gefragt. Ferner müssen solche Lösungen in der Lage sein, die unterschiedlichsten Datenquellen wie Datenbanken und auch andere Systeme einzubinden. Hier hilft es, dass viele Systeme bereits XML-Schnittstellen und Formate anbieten. Nimmt man zusätzlich Anforderungen wie Personalisierung, Plattformunabhängigkeit und Flexibilität hinzu, kommt man schnell zu einer Lösung, die auf Basis vorhandener Java-Komponenten gebaut werden könnte. Insbesondere die Komponenten der Apache-Projekte, wie der XML-Parser Xerces und XSLT-Processor Xalan bieten bereits die Grundlage einer solchen Anwendung. Genau hier setzt Cocoon an, indem vorhandene Komponenten mittels einer durchdachten und leistungsfähigen Architektur zu einem leistungsfähigen XML Publishing Framework zusammengesetzt werden. Viele Anwendungsszenarien lassen sich durch Cocoon und ohne eine Zeile Java-Programmierung abdecken. Unsere Cocoon-Vorstellung beginnt mit einem Überblick über die Architektur.

Architekturübersicht
Cocoon ist ein Framework mit einer offenen, komponentenbasierten Architektur. Diese Architektur erlaubt die Verwendung von anderen Projekten als austauschbare Komponenten. Hierfür bedient sich Cocoon aus dem großen Fundus anderer Apache Projekte. Zum Beispiel wird Apache Xerces [5] als XML -Parser, Apache Xalan [4] als XSLT-Processor und Apache FOP zur PDF-Generierung eingesetzt; genauso könnten aber auch andere XML-Parser oder XSLT-Processoren verwendet werden. Grundlage für die objektorientierte Architektur ist das Apache-Projekt Avalon [3], ein Java-Ansatz zur komponentenorientierten Softwareentwicklung. Die Arbeitsweise von Cocoon basiert auf dem von Web Servern oder Servlet-Engines bekannten Request-Response-Zyklus. Wenn ein Request vom Client an Cocoon geschickt wird, wird dieser auf dem Server verarbeitet. Cocoon generiert ein Antwort-Dokument und schickt dieses zurück an den Client. Cocoon verwendet für die Beschreibung dieses Zyklus eine Abstraktion, die auf dem Servlet-API basiert. Durch diese Abstraktion ist es möglich, Cocoon in verschiedenen Umgebungen zu verwenden. Die häufigste Verwendungsform ist sicherlich als Servlet. Mittels einer vorhandenen Implementierung kann Cocoon damit in Servlet-Engines oder Application Server eingebunden werden. Allerdings bietet Cocoon auch ein Command-Line-Interface und erlaubt somit z.B. die Ansteuerung aus einem Skript.


Abb. 1: Die Architektur von Cocoon 2

Für die Betrachtung der Funktionsweise von Cocoon ist es unerheblich, in welcher Umgebung Cocoon verwendet wird. Im Folgenden betrachten wir daher die häufigste Form: Cocoon als Servlet. Wir gehen im Weiteren davon aus, dass Cocoon in einer Servlet-Engine läuft und unter http://localhost:8080/cocoon/ der Servlet-Context von Cocoon erreichbar ist. Entsprechende Installationsanweisungen für die gängigen Servlet-Engines, insbesondere für Jakarta Tomcat [6] finden sich in der Distribution [2]. Jede Anfrage an Cocoon liefert eine Antwort bzw. ein Dokument. Ein Dokument erhält immer einen eindeutigen Namen, den man in seinem Browser als URI angeben kann. Alle Informationen in der URI, die cocoon/ folgen, bezeichnen das Dokument. Beispielsweise erreicht man über http://localhost:8080/cocoon/helloworld ein Dokument namens helloworld. Das zentrale Bindeglied zwischen Dokumentnamen und generierter Antwort ist die Sitemap.

Sitemap und Pipelines
Die Sitemap ist ein XML-Dokument, in dem festgelegt wird, welche Arbeitsschritte für eine URI ausgeführt werden. Um ein Dokument zu erzeugen, wird eine sogenannte XML-Pipeline aufgebaut. Eine XML-Pipeline ist eine funktionale Einheit, die aus einer Kombination von verschiedenen Komponenten zusammengesetzt wird. Jede Pipeline beginnt mit genau einem Generator. Ein Generator liefert einen XML-Datenstrom, der von anderen Komponenten in der Pipeline verarbeitet wird. Cocoon enthält beispielsweise Generatoren, um direkt XML- Dokumente von der Festplatte zu lesen oder über eine HTTP-Verbindung zu laden. Die Quelle für einen Generator muss aber nicht unbedingt direkt XML sein; ein Generator kann auch andere Formate nach XML umwandeln, beispielsweise ist ein Generator denkbar, der Daten aus einer relationalen Datenbank holt und diese in XML umwandelt. Nach einem Generator können in der Pipeline sogenannte Transformer folgen. Diese optionalen Komponenten erhalten den XML-Datenstrom aus der vorgelagerten Komponente. Ein Transformer kann den Datenstrom verändern. Es können somit neue XML-Elemente eingefügt, bestehende herausgenommen oder direkt verändert werden. Ein Beispiel hierfür ist ein Stylesheet-Transformer, der ein XSLT Stylesheet verwendet, um den Datenstrom entsprechend umzuformen. Die letzte Komponente in der Pipeline ist ein sogenannter Serializer. Diese erforderliche Komponente wandelt den XML-Datenstrom in das entsprechende Ausgabeformat, setzt den Mime-Type für den Client und erzeugt damit das eigentliche Dokument. Der HTML Serializer erzeugt beispielsweise einen HTML-Textstrom, ein PDF Serializer erzeugt einen PDF-Strom. Ein typisches mit Cocoon generiertes Dokument besteht aus der Aufbereitung von Daten, d.h. ein XML- Dokument mit den Daten wird mit Hilfe eines Stylesheets nach HTML transformiert. Genau das werden wir einmal anhand des obligatorischen HelloWorld-Beispiels durchführen.

Hello World
Das Hello World-Beispiel soll ein XML-Dokument mit dem entsprechenden Text lesen und per Stylesheet nach HTML transformieren. Für die XML-Pipeline benötigen wir also einen Generator, der ein XML-Dokument liest, einen Transformer, der ein Stylesheet auf das XML-Dokument anwendet und dieses nach XHTML konvertiert und einen Serializer, der aus XHTML, das für den Browser verständlichere HTML erstellt. Darüber hinaus muss noch die Verbindung zwischen dem Dokumentnamen und der Pipeline hergestellt werden. Dieses wird über eine weitere Komponente, einem Matcher erreicht. Für jeden Komponententyp bietet Cocoon eine Reihe an verschiedenen Komponenten für unterschiedliche Einsatzgebiete. Der wildcard Matcher vergleicht beispielsweise den vom Client geschickten Dokumentnamen mit einem vorgegebenen Muster. Ist der Vergleich erfolgreich, so werden alle Anweisungen ausgeführt, die in dem entsprechenden XML Element-eingeschachtelt sind. In unserem Beispiel wird auf helloworld als Dokumentname geprüft.


Abb. 2: Cocoon XML Pipeline

Als Generator können wir den file generator verwenden, der ein XML-Dokument von der Festplatte oder aber über HTTP lesen kann. Der xslt transformer liest ein Stylesheet und wendet dieses auf die Daten an. Schlusslicht ist der html serializer, der die Antwort mit dem entsprechenden Mime-Type versieht.

<map:pipeline>
<map:match pattern="helloworld" type="wildcard">
<map:generate src="helloworld.xml" type="file"/>
<map:transform src="helloworld2html.xsl" type="xslt"/>
<map:serialize type="html"/>
</map:match>
</map:pipeline>

Die Sitemap befindet sich direkt in dem Kontextverzeichnis von Cocoon und heißt sitemap.xmap. Suchen Sie innerhalb des Dokumentes das Element map:pipelines und fügen Sie das Listing für unser Beispiel direkt darunter ein. Kopieren Sie sowohl das XML als auch das XSLT-Dokument in das gleiche Verzeichnis wie die Sitemap. Nachdem Sie Cocoon gestartet haben, können Sie das Beispiel über http://localhost:8080/cocoon/helloworld aufrufen. Wie man hieraus bereits erkennen kann, hängt bei Cocoon das Format des Endergebnisses nicht vom Dokumentennamen ab. Anhand dieses kleinen Beispiels wird auch ein großer Unterschied zwischen Version 1.x von Cocoon und der jetzigen Version deutlich: In Version 1.x hatte man keine saubere Trennung zwischen Daten und Layout, da man schon in den XML Dokumenten - also den Daten - per Processing Instructions die Verarbeitung dieses Dokumentes angeben musste, also in der Regel das Stylesheet. Mit der neuesten Version von Cocoon entfällt dieses. Alles lässt sich unabhängig voneinander über die Sitemap definieren. Durch das Zusammensetzen der Pipelines ist eine flexiblere Wartung der Dokumentengenerierung möglich und es erfolgt eine wirklich saubere Trennung zwischen Daten und Layout. Diese Flexibilität wird deutlich, wenn man andere Formate als nur HTML generieren möchte. Beispielsweise soll das Hello World-Beispiel auch über ein mobiles Gerät erreichbar sein. Dafür benötigen wir ein Stylesheet, das aus den Daten WML erstellt. Somit können wir die XML-Pipeline entsprechend abändern: der Transformer liest dieses neue Stylesheet, das WML generiert und ein spezieller Serializer, der wap serializer, erzeugt dann das Antwortdokument.

<map:pipeline>
<map:match pattern="mobile_helloworld" type="wildcard">
<map:generate src="helloworld.xml" type="file"/>
<map:transform src="helloworld2wml.xsl" type="xslt"/>
<map:serialize type="wap"/>
</map:match>
</map:pipeline>

Fügen Sie den Ausschnitt aus der Sitemap direkt unter das erste Beispiel, kopieren Sie das neue Stylesheet in das Verzeichnis und starten Sie Cocoon neu. Danach können Sie das Beispiel über http://localhost:8080/cocoon/mobile_helloworld aufrufen. Wir haben nun zwei verschiedene Pipelines gebaut, die beide Male die gleichen Daten in unterschiedlichen Formaten dargestellt haben, d.h. die HTML-Version für normale Browser erreicht man unter helloworld und die WML-Version unter mobile_helloworld. Cocoon kann aber auch anhand des Requests erkennen, um welches Gerät es sich bei dem Client handelt, d.h. ob es ein Browser oder ein mobiles Gerät ist. Dadurch ist es möglich, dass man sowohl im Browser als auch auf dem Handy lediglich helloworld anfordert und Cocoon dann automatisch das richtige Format generiert. Möglich wird dieses durch einen weiteren Komponententyp, den man in der Sitemap nutzen kann: einem Selector. Ein Selector kann man mit einem if-elseif-else oder mit xsl:choose vergleichen. Er bietet die Möglichkeit einen Parameter auf verschiedene Werte zu testen. Cocoon beinhaltet unter anderem einen Selector, den browser selector, der testet, um welchen Client es sich handelt. Mit Hilfe des browser selectors können wir also aus unseren zwei Pipelines eine einzige machen, die je nach Client ein anderes Stylesheet bzw. Serializer verwendet. Das folgende Beispiel verwendet den browser selector und testet mit Hilfe der map:when -Anweisung, ob es sich um ein WAP-Gerät handelt. Wenn dieses der Fall ist, wird das entsprechende WML Stylesheet mit dem wap serializer verwendet. In allen anderen Fällen (map:otherwise) wird das HTML Stylesheet und der html serializer in die Pipeline mit aufgenommen.

<map:pipeline>
<map:match pattern="helloworld" type="wildcard">
<map:generate src="helloworld.xml" type="file"/>
<map:select type="browser">
<map:when test="wap">
<map:transform src="helloworld2wml.xsl" type="xslt"/>
<map:serialize type="wap"/>
</map:when>
<map:otherwise>
<map:transform src="helloworld2html.xsl" type="xslt"/>
<map:serialize type="html"/>
</map:otherwise>
</map:select>
</map:match>
</map:pipeline>

Entfernen Sie die beiden ersten Beispiele aus der Sitemap und fügen Sie an deren Stelle diesen neuen Ausschnitt ein. Starten Sie Cocoon neu und rufen Sie nun wahlweise das helloworld-Dokument von einem Browser bzw. von einem WML-Gerät auf. Anhand dieses Beispieles ist der Vorteil einer komponentenbasierten Lösung erkennbar. Das bedeutet, dass neue Funktionalität sehr leicht durch Ändern bzw. Hinzufügen einer neuen Komponente möglich ist. Sollen beispielsweise die Daten nicht mehr aus einer statischen Datei gelesen werden, sondern aus einer SQL- Datenbank geholt werden, so muss man lediglich den Generator austauschen. Möchte man ein anderes Layout, tauscht man den Transformer bzw. das Stylesheet aus. Möchte man personalisiertes Layout, so kann man entsprechende Selectoren verwenden, die den Inhalt abhängig von der Uhrzeit oder dem Alter des Benutzers aufbereiten. Für viele dieser Anwendungen bietet Cocoon schon entsprechende Komponenten. In der Tabelle sind ein paar der wichtigsten Komponenten aufgeführt. Benötigt man noch weitergehende Funktionalität, so kann man sehr leicht einen eigenen Generator, Transformer etc. implementieren und dem System hinzufügen. Spätestens hier fällt ein weiterer Unterschied zu Cocoon 1.x auf: die XML Pipelines verwenden das SAX-Modell zur Bearbeitung der XML-Daten. Somit fällt der Speicherbedarf einer Cocoon-Anwendung bedeutend geringer aus als bei der DOM-basierten 1.x Version. Darüber hinaus ist die Abarbeitungsgeschwindigkeit erhöht worden und Cocoon bietet einen intelligenten Caching-Algorithmus, der erneutes dynamisches Generieren von Dokumenten vermeidet.

Sitemap-Flow
Betrachten wir nun die Sitemap etwas genauer. Sie besteht aus mehreren Bereichen, von denen wir in diesem Teil des Artikels zwei genauer beleuchten möchten: die Komponenten und die Pipelines. Innerhalb der Sitemap wird der Namespace http://apache.org/cocoon/sitemap/1.0 mit dem Prefix map verwendet. Alle Elemente tragen diesen Namespace. Unterhalb des Elements map:components finden sich die verschiedenen Komponenttypen und Komponenten. Cocoon kennt die Typen: Generators, Transformers, Serializers, Selectors, Matchers, Readers und Actions. Für jeden einzelnen dieser Typen gibt es einen entsprechenden XML-Block, beispielsweise map:generators oder map:selectors. Innerhalb eines jeden Blocks werden die entsprechenden Komponenten deklariert und konfiguriert. Jede Komponente bekommt einen eindeutigen Namen über das Attribut name und eine zugehörige Java-Klasse über das Attribut src. Diese Klasse bezeichnet die Implementierung der Komponente und der Name dient als Referenz, die man in den XML Pipelines verwenden kann. Um in den Pipelines eine Komponente zu verwenden, benutzt man ein XML-Element, dessen Namen aus dem zum Komponententyp zugehörigem Verb geformt wird. Beispielsweise map:generate um einen Generator zu verwenden, map:select für einen Selector etc. Um zu definieren, welche Komponente man verwenden möchte, spezifiziert man über das Attribut type den eindeutigen Namen der Komponente. Beispielsweise bezieht sich auf einen Generator, der den Namen file trägt. Für jeden Komponententyp existiert ein Default-Eintrag (Attribut default in der Komponentensektion). Dieser Typ wird immer dann verwendet, wenn in den XML Pipelines kein Attribut type angegeben ist. Beispielsweise ist der xslt-Transformer der Default-Transformer. Es ist somit äquivalent zu schreiben oder . Die obige Tabelle mit den gängigsten Komponenten enthält für jeden Komponententyp den Default-Eintrag. Eine Komponente kann darüber hinaus unter Umständen konfiguriert werden, dieses hängt von der Komponente selbst ab. Beispielsweise der wap serializer kann hinsichtlich des verwendeten Encodings etc. konfiguriert werden. Die Konfiguration ist in der Komponentendefinition eingeschachtelt und verwendet nicht den Namespace der anderen Sitemap-Elemente, da die Konfiguration zur Komponente selbst und nicht zur Sitemap gehört. Neben dem Komponentenbereich ist der zweite wichtige Bereich der Pipelines-Bereich. Er wird eingeleitet durch das Element map:pipelines. Unterhalb dieses Elements können ein oder mehrere map:pipeline-Elemente angeordnet werden. Ein einzelnes map:pipeline-Element enthält dann die einzelnen XML Pipelines für die verschiedenen Dokumente. Das heißt ein map:pipeline-Element muss nicht unbedingt genau eine XML Pipeline enthalten, sondern in der Regel umfasst sie eine Menge an Pipelines, die logisch zusammengehören. Die Aufteilung in verschiedene map:pipeline-Bereiche dient somit der Übersicht und hat noch eine weitere Besonderheit: die Fehlerbehandlung. Jeder einzelne map:pipeline-Bereich hat eine eigene Error-Pipeline. Auf diese Fehlerbehandlung werden wir später genauer eingehen. Wenn ein Request an Cocoon gesendet wird, so arbeitet Cocoon die Sitemap oder genauer den map:pipelines-Bereich von oben nach unten ab. Dabei wird jeder einzelne map:pipeline Abschnitt ebenfalls von oben nach unten abgearbeitet. Trifft Cocoon auf ein map:match oder ein map:select wird der entsprechende Test durchgeführt. Ist dieser Test erfolgreich, werden die entsprechenden eingeschachtelten XML-Elemente ebenfalls abgearbeitet. Ist er nicht erfolgreich, wird nach dem schließenden map:match bzw. map:select weiter fortgefahren. Wenn ein map:generate, ein map:transform oder ein map:serialize gefunden wird, so wird die entsprechende Komponente in die XML Pipeline für das Dokument mit aufgenommen. Bei einem map:serialize stoppt die Abarbeitung innerhalb der Sitemap. Dann wird die XML Pipeline ausgeführt und das Dokument generiert. Wird bei der Abarbeitung der Sitemap keine XML Pipeline aufgebaut, zum Beispiel weil das Dokument nicht existiert, so signalisiert Cocoon einen http 404 Status. Damit erkennt der Client, das es das Dokument auf dem Server nicht gibt. Tritt innerhalb der Verarbeitung irgendein Fehler auf, so wird automatisch in eine sogenannte Error-Pipeline gesprungen. Ein Fehler könnte sein, dass eine XML Pipeline keinen Generator hat, oder aber ein XML Dokument oder ein Stylesheet nicht gefunden werden kann etc. Jeder map:pipeline-Abschnitt kann ein map:handle-errors-Element enthalten. Innerhalb dieses Elements kann man eine XML Pipeline definieren, die in einem Fehlerfalle ausgeführt wird. Diese Pipeline kann alle Sitemap-Komponenten, also Serializer, Transformer etc, enthalten, bis auf einen Generator. Die Error-Pipeline enthält implizit den Error-Generator, der den entsprechenden Fehler als XML-Dokument aufbereitet. Die Error-Pipeline kann diesen Fehler optisch aufbereiten, loggen etc. Mit Hilfe dieser Konzepte lassen sich komplette Web-Anwendungen mit Cocoon erstellen. Wir wollen als nächstes weitere Beispiele betrachten, um die Möglichkeiten von Cocoon aufzuzeigen.

Sitemap-Komponenten
Die bisher gezeigten Beispiele verwendeten alle die gleichen Komponenten: den file generator und den xslt transformer. Natürlich bietet Cocoon noch viel mehr Komponenten, die verwendet werden können. Beispielsweise den html generator. Dieser Generator kann eine HTML-Seite lesen und diese nach XHTML umwandeln. Dadurch ist es sehr leicht möglich, bestehende HTML-Auftritte in neue mit Cocoon erstellte Anwendungen zu integrieren. Durch die Bereitstellung der Daten als XML-Strom können beispielsweise neue Stylesheets verwendet werden, um die bestehenden HTML-Auftritte ohne großen Aufwand mit einem neuen Layout zu versehen und in die neue Anwendung einzubetten. Das vierte Beispiel lädt über den html generator die Startseite der Cocoon-Website, extrahiert Textinformationen über den xpath-Parameter aus dieser Seite und versieht die gesamte Seite per Stylesheet mit einem neuen Hintergrund.

<map:pipeline>
<map:match pattern="html" type="wildcard">
<map:generate src="http://xml.apache.org/cocoon" type="html">
<map:parameter name="xpath"
value="/html/body/table[2]/tr/td[2]/table/tr[2]/td/div[1]/table[2]"/>
</map:generate>
<map:transform src="newlayout.xsl" type="xslt"/>
<map:serialize type="html"/>
</map:match>
</map:pipeline>

Fügen Sie den obigen Abschnitt in die Sitemap ein und kopieren Sie das Stylesheet newlayout.xsl in das gleiche Verzeichnis wie die Sitemap. Nach einem Neustart der Servlet-Engine können Sie über http://localhost:8080/cocoon/html das Beispiel aufrufen. Grosse Web Anwendungen bestehen aus vielen Dokumenten. Müsste man für jedes dieser Dokumente eine einzelne XML Pipeline bestehend aus Generator, Transformer und Serializer mit zugehörigem Matcher bauen, so wäre das nicht nur sehr viel Aufwand, sondern die daraus resultierende Sitemap wäre schlichtweg nicht mehr wartbar. Zur Lösung dieses Problems gibt es ein weiteres Konzept innerhalb der Sitemap: die automatische Wertersetzung. Dabei können während der Erstellung der Sitemap Platzhalter verwendet werden, die dann zur Laufzeit durch aktuelle Werte ersetzt werden. In Kombination mit dem wildcard Matcher lässt sich damit eine Pipeline erstellen, die für eine große Anzahl an Dokumenten gültig ist.

<map:pipeline>
<map:match pattern="*" type="wildcatd">
<map:generate src="{1}.xml" type="file"/>
<map:transform src="doc2html.xsl" type="xslt"/>
</map:serialize type="html">
</map:match>
</map:pipeline>

In dem obigen Beispiel wird als Muster für den Matcher das Malzeichen verwendet. Dieses Muster bedeutet, dass jede Anfrage, die keinen Verzeichnistrenner enthält, zutrifft, beispielsweise helloworld oder mein_dokument. Anfragen mit Verzeichnistrenner, wie beispielsweise dokumente/helloworld, treffen nicht zu. Die nachfolgenden Komponenten müssen einen Zugriff auf den tatsächlichen Wert erhalten. Dieses geschieht über die Wertersetzung von Cocoon. Ein Match kann den eingeschachtelten Komponenten Name-Wert-Paare zur Verfügung stellen. Die eingeschachtelten Komponenten können dann anhand des Namens auf den entsprechenden Wert zugreifen. Dieses geschieht dadurch, dass der Name in geschweifte Klammern gesetzt wird. Damit dieser Mechanismus funktioniert, muss die Komponente wissen, welche Namen der Matcher bereitstellt. Im Falle des wildcard Matchers ist der Name die Ziffer eins, somit wird bei der Abarbeitung der Sitemap {1}durch den tatsächlichen Wert des Musters ersetzt. Der file generator ließt beispielsweise die Quelle {1}.xml, d.h. wird das Dokument helloworld angefragt, wird helloworld.xml gelesen usw. Das Muster des wildcard Matchers kann beliebig kompliziert werden. Verwendet man zwei Malzeichen direkt hintereinander, so treffen alle Anfragen zu, d.h. es dürfen auch Verzeichnistrenner vorkommen. Man kann die verschiedenen Muster auch noch mit Konstanten mischen, beispielsweise pattern=benutzer/*/dokumente/**>. Hier treffen alle Anfragen zu, die mit benutzer/ anfangen und danach einen Text ohne Verzeichnistrenner enthalten, gefolgt von /dokumente/ und dann kann ein beliebig tiefer Pfad folgen. Beispielsweise benutzer/matthew/dokumente/rezepte/pizza würde zutreffen, allerdings benutzer/carsten/buecher/dokumente/konzept nicht. Für dieses Muster ist die Wertersetzung etwas komplizierter, da das Muster zwei Platzhalter enthält. Der wildcard Matcher nummeriert diese startend mit eins durch, d.h. über {1} erhält man den tatsächlichen Wert der auf benutzer/ folgt und über {2} erhält man alles nach dokumente/. Die Wertersetzung kann natürlich nicht nur im Generator genutzt werden, sondern in jeder andere Komponente genauso. Das folgende Beispiel nutzt dieses, um ein Stylesheet abhängig vom angefragten Dokument zu verwenden.

<map:pipeline>
<map:match pattern="benutzer/*/dokumente/**" type="wildcard">
<map:generate src="dokumente/{2}.xml" type="file"/>
<map:transform src="stylesheets/{1}.xsl" type="xslt"/>
<map:transform src="stylesheets/doc2html.xsl" type="xslt"/>
</map:serialize type="html">
</map:match>
</map:pipeline>

Bei einer Anfrage von benutzer/matthew/dokumente/rezepte/pizza würde das Dokument dokumente/rezepte/pizza.xml vom Generator gelesen und darauf würde das Stylesheet stylesheets/matthew.xsl und dann das stylesheet/doc2html.xsl angewendet. Die Wertersetzung in Zusammenhang mit dem wildcard Matcher erlaubt somit die Erstellung von komplexen Pipelines, die für mehrere Dokumentanfragen zutrifft und diese Dokumente flexibel generiert.

Ausblick
Gerade diese Flexibilität bei der Zusammensetzung der Pipelines und die einfache Konfiguration über die Sitemap ist ein großer Fortschritt der neuesten Version von Cocoon. Im zweiten Teil unseres Artikels werden wir weitere Möglichkeiten zur Erstellung von Web Anwendungen vorstellen. Beispielsweise werden wir neue Komponenttypen, Actions und Reader, erklären. Mit Hilfe von Actions kann man beliebige Aktionen auf dem Server durchführen; ein Reader erlaubt das Lesen von binären Inhalten wie Bilder oder Filme. Das Repertoire an Standardkomponenten wird ebenfalls erweitert, insbesondere die aus Cocoon 1.x bekannte Möglichkeit, XSP zu verwenden. Abschließend werden weitere Konzepte der Sitemap, Aggregation von Inhalten und das Aufteilen in mehrere Sitemaps, eingeführt. Abgerundet wird der zweite Teil mit Tipps und Tricks zur Konfiguration und neuen Beispielen.

Matthew Langham ist seit 10 Jahren bei der Firma s&n in Paderborn, wo er das Open Source Competence Center leitet. Carsten Ziegeler ist Chef-Architekt und Consultant des Open Source Competence Centers der S&N AG. Er beeinflusste maßgeblich das Design von Cocoon 2 und ist darüber hinaus verantwortlicher Release Manager. Zusammen arbeiten sie zur Zeit an eiemn Buch über Cocoon und XML-Applikationen mit Erscheinungstermin Sommer 2002.

Links und Literatur


© 2004 Software & Support Verlag GmbH. Vervielfältigung nur mit Genehmigung des Verlags. Fragen?