Proseminar XML Wintersemester 2000/01 Cocoon, eine Einführung Sebastian Wassen
Inhalt: 1. Was ist Cocoon [3] 2. Installation von Cocoon [3] Installation von Jakarta-Tomcat [3] Installation von Cocoon 1.8 [3] 3. Erste Schritte mit Cocoon [4] Beispiel 1: XML und XSL [4] Beispiel 1: SQL [5] Beispiel 1: XSP [8] 4. Der Weg eines Xml-Documentes [11] 5. Die Interfaces [11] 6. Die Processor [12] SQL-Processor [12] LDAP-Processor [13] DCP-Processor [14] XSP- Processor [14]
1. Was ist Cocoon Cocoon ist eine XML-Publishing Framework. Es ermöglicht Daten in XML bereitzustellen. Diese können während einer Anfrage statisch oder dynamisch generiert werden. Die erzeugten XML-Daten werden von verschiedenen Prozessoren aufbereitet und schließlich entsprechend der Anfrage in unterschiedliche Ausgabeformate formatiert (HTML+CSS, XSL(FO), SVG, WML, VoxML VRML, etc.). Cocoon verwendet dazu insbesondere XML, XML Namespaces, XSLT und Xpath als Schlüsseltechnologien. Cocoon ist 100% pure Java und ist somit auf einer Vielzahl von Plattformen verfügbar. Cocoon wird hauptsächlich über die Servlet-Api von Sun angesprochen es ist jedoch leicht möglich eigen Connectoren zu implementieren. Bei der Entwicklung von Cocoon wurde versucht Methoden bereitzustellen die Autoren ermöglicht den Inhalt eines XML-Dokumentes von seiner Logic und von der gewünschten Darstellung zu trennen. So können diese mitunter sehr verschiedenen Aufgaben unabhängig von einander gelöst werden, was Kosten und Entwicklungszeit spart. Die dynamische Generierung von Daten wird über eine eigene XML-Sprache XSP (extensible Server Pages) realisiert. Außerdem stellt Cocoon bereits einige Möglichkeiten zur Verfügung um SQL-Anfragen zu stellen oder über XML-Forms auf XML-Dateien zuzugreifen. Cocoon bietet darüber hinaus eine sehr klare interne Struktur mit vielen Interfaces die es leicht machen eigene Wünsche und Vorstellungen bezüglich Logik und dynamischer Generierung von Daten schnell zu realisieren. 2. Installation von Cocoon (Minimal-) Installation von Jakarta-Tomcat (unter Windows, JDK1.3): jakarta-tomcat.tar.gz in das gewünschte Installationsverzeichnis (z.b.: C:\tomcat\) entpacken. Tomcat läßt sich mit Hilfe der Batch-Dateien startup.bat und shutdown.bat im Verzeichnis C:\tomcat\bin\ starten und stoppen. Eventuell muß man im Eigenschafts-Dialog für die Batch-Dateien die Größe der Umgebungsspeichers verändern, damit Variablen gesetzt werden können. Hat man Tomcat erfolgreich gestartet kann man mit Hilfe eines Web-Browsers die Tomcat-Startseite aufrufen: http://localhost:8080/index.html (Minimal-) Installation von Cocoon 1.8 (unter Windows, JDK1.3, Tomcat) cocoon-1.8.zip in das gewünschte Installationsverzeichnis (z.b.: C:\cocoon\) alle Dateien aus dem C:\cocoon\lib\ nach C:\tomcat\lib\ kopieren die Datei C:\cocoon\bin\cocoon.jar nach C:\tomcat\lib\ kopieren öffne die Datei C:\tomcat\conf\server.xml und füge das Element: <Context path="/cocoon" docbase="webapps/cocoon" debug="0" reloadable="true"> </Context> ein. erstelle die Verzeichnisse C:\tomcat\webapps\cocoon und C:\tomcat\webapps\cocoon\WEB-INF kopiere C:\cocoon\src\WEB-INF\web.xml nach C:\tomcat\webapps\cocoon\WEB-INF kopiere C:\cocoon\conf\cocoon.properties nach C:\tomcat\webapps\cocoon\WEB-INF öffne C:\tomcat\webapps\cocoon\WEB-INF\web.xml und ändere den Value des Init-Parameters properties nach WEB-INF/cocoon.properties kopiere C:\cocoon\samples nach C:\tomcat\webapps\cocoon lösche C:\tomcat\lib\jaxp.jar und C:\tomcat\lib\parser.jar oder sorge dafür das C:\tomcat\lib\xerxes_1_2.jar am Anfang des classpath steht nach einem Neustart von Tomcat kann man sich nun unter http://localhost:8080/cocoon/index.xml die Beispielseiten von Cocoon anschauen Zu Installation unter anderen System gibt es für eine ganze Reihe von Anleitungen in der Dokumentation. Die sind mehr oder weniger gut sind. Ein bißchen Spaß am Basteln sollte man aber schon mitbringen.
3. Erste Schritte mit Cocoon Beispiel 1: XML und XSL Ist Cocoon soweit installiert kann man sofort anfangen. Am besten man legt sich erst einmal ein Verzeichnis an in dem man seine Beispiele speichert: C:\tomcat\webapps\cocoon\beispiele\ Mit einem einfachen Beispiel das nur XSL benutzt fangen wir an: C:\tomcat\webapps\cocoon\beispiele\beispiel1.xml <?xml version="1.0"?> <!-- das StyleSheet das verwendetet werden soll --> <?xml-stylesheet href="beispiel1.xsl" type="text/xsl"?> <!-- der Processor der verwendet werden soll --> <?cocoon-process type="xslt"?> <!-- ein paar Daten in einer XML-Struktur --> <seite> <titel>erste Schritte mit Cocoon</titel> <abschnitt name="diese Seite wurde mit Hilfe des XSL-Processors von Cocoon transformiert." /> <abschnitt name="kontoauszug ;-) (wurde mit einem extenen StyleSheet treansformiert)" > <kontoauszug> <transaktion> <betrag>-250,00</betrag> <verwendungszweck>miete Studentenwohnheim</verwendungszweck> </transaktion> <transaktion> <betrag>-65,00</betrag> <verwendungszweck>telefonrechnung</verwendungszweck> </transaktion> <transaktion> <betrag>+400,00</betrag> <verwendungszweck>gehalt</verwendungszweck> </transaktion> </kontoauszug> </abschnitt> </seite> C:\tomcat\webapps\cocoon\beispiele\beispiel1.xsl <?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/xsl/transform"> <!-- lädt ein externes StyleSheet --> <xsl:import href="kontoauszug.xsl"/> <xsl:template match="seite"> <!-- fügt eine processing-instruction ein damit Cocoon das Dokument anschließend nach text/html formatiert --> <xsl:processing-instruction name="cocoon-format"> type="text/html" </xsl:processing-instruction> <html> <head> <title> <xsl:value-of select="titel"/> </title> </head> <body bgcolor="#ffffff"> </body> </html>
<xsl:template match="titel"> <h1 align="center"> </h1> <xsl:template match="abschnitt"> <p align="center"> <i> <xsl:value-of select="@name"/> </i> </xsl:stylesheet> C:\tomcat\webapps\cocoon\beispiele\kontoauszug.xsl <?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/xsl/transform"> <xsl:template match="kontoauszug"> <p align="left"> <big>kontoauszug:</big> <xsl:template match="transaktion"> <p align="left"> Transaktion: </xsl:stylesheet> Ausgabe nach Transformation mit dem StyleSheet beispiel1.xsl http://localhost:8080/cocoon/beispiele/beispiel1.xml Man kann also durch einfaches Anlegen der entsprechenden XML- und XSL-Datei Inhalt und Darstellung getrennt beschreiben und publizieren. Beispiel 2: SQL Das zweite Beispiel zeigt die Möglichkeit mit Hilfe des SQL-Prozessors von Cocoon auf Datenbanken zuzugreifen und deren Inhalt als XML-Daten zu betrachten und weiterzuverarbeiten. C:\tomcat\webapps\cocoon\beispiele\beispiel2.xml <?xml version="1.0"?>
<?xml-stylesheet href="beispiel2.xsl" type="text/xsl"?> <?cocoon-process type="xslt"?> <?cocoon-process type="sql"?> <beispiel2> <!-- definiert eine Datenbankverbindung, die Datenbank sollte existieren ;-) --> <connectiondefs> <connection name="testconnection"> <driver>org.gjt.mm.mysql.driver</driver> <dburl>jdbc:mysql://mysql.test.de/testdatabase</dburl> <username>testuser</username> <password>testpassword</password> </connection> </connectiondefs> <!-- definiert Regeln für das Verhalten des Processors bei einer Suche --> <querydefs name="test" doc-element="preisliste" row-element="sorte" connection="testconnection" /> <!-- die normale Beschreibung der Daten --> <seite> <titel>erste Schritte mit Cocoon</titel> <abschnitt name="diese Seite wurde mit dem XSL-Processor nach HTML transformiert" / > <abschnitt name="preisliste wurde mit dem SQL-Procesor aus einer Datenbank geladen." > <!-- das nächste tag wird durch das Ergebnis der Suche ersetzt --> <query defs="test"> select ware,preis from preisliste where sorte="obst" order by ware </query> </abschnitt> </seite> </beispiel2> Man beachte das dieses Beispiel natürlich eine Datenbank braucht. In diesem Fall die durch testconnection definierte. Es wird außerdem erwartet das in der Datenbank ein Tabelle preisliste vorhanden ist in der Werte (sorte, ware, preis) abgespeichert sind. z.b ( Obst, Birnen, 5,99 ) Auch dieses Beispiel benötigt eine Transformation mit XSL um die Daten in HTML Form zu bringen: C:\tomcat\webapps\cocoon\beispiele\beispiel2.xsl <?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/xsl/transform"> <xsl:template match="seite"> <xsl:processing-instruction name="cocoon-format"> type="text/html" </xsl:processing-instruction> <html> <head> <title> <xsl:value-of select="titel"/> </title> </head> <body bgcolor="#ffffff"> </body> </html>
<xsl:template match="titel"> <h1 align="center"> </h1> <xsl:template match="abschnitt"> <p align="center"> <i> <xsl:value-of select="@name"/> </i> <xsl:template match="preisliste"> <p align="center"> <big>preisliste:</big> <table border="1" align="center" cellpadding="2"> <tbody> <tr> <td bgcolor="#cccccc">ware:</td> <td bgcolor="#cccccc">preis</td> </tr> </tbody> </table> <xsl:template match="sorte"> <tr> </tr> <xsl:template match="ware"> <td> </td> <xsl:template match="preis"> <td> </td> </xsl:stylesheet> Hat man alle Dateien und eine entsprechende Tabelle in einer Datenbank erstellt kann es losgehen:
Wieder wurden die Daten und die Darstellung getrennt beschrieben und die Daten dabei aus einer Datenbank geholt. Beispiel 3: XSP Das dritte Beispiel soll die Fähigkeit von Cocoon zur dynamischer Generierung von XML-Daten am Beispiel von XSP anschneiden. Dazu wieder eine kleine XML Datei. C:\tomcat\webapps\cocoon\beispiele\beispiel3.xml <?xml version="1.0"?> <?cocoon-process type="xsp"?> <?cocoon-process type="xslt"?> <?xml-stylesheet href="beispiel3.xsl" type="text/xsl"?> <xsp:page language="java" xmlns:xsp="http://www.apache.org/1999/xsp/core"> <xsp:logic> static private int counter = 0; private synchronized int count() { return counter++; } private String normalize(string string) { if (string == null) return ""; else return string; } </xsp:logic> <seite> <titel>erste Schritte mit Cocoon</titel> <abschnitt name="diese Seite wurde mit Hilfe des XSL-Processors von Cocoon transformiert." /> <abschnitt name="der folgende Inhalt wurde zum Teil dynamisch mit XSP generiert." > <item> Diese Seite ist bereits <xsp:expr>count()</xsp:expr> mal aufgerufen worden. </item> <elementlist> <element name="request method"> <xsp:expr>normalize(request.getmethod())</xsp:expr> <element name="request URI"> <xsp:expr>normalize(request.getrequesturi())</xsp:expr> <element name="request protocol"> <xsp:expr>normalize(request.getprotocol())</xsp:expr> <element name="servlet path"> <xsp:expr>normalize(request.getservletpath())</xsp:expr> <element name="path info"> <xsp:expr>normalize(request.getpathinfo())</xsp:expr> <element name="path translated"> <xsp:expr>normalize(request.getpathtranslated())</xsp:expr> <element name="query string"> <xsp:expr>normalize(request.getquerystring())</xsp:expr> <element name="content length"> <xsp:expr>request.getcontentlength()</xsp:expr>
<element name="content type"> <xsp:expr>normalize(request.getcontenttype())</xsp:expr> <element name="server name"> <xsp:expr>normalize(request.getservername())</xsp:expr> <element name="server port"> <xsp:expr>request.getserverport()</xsp:expr> <element name="remote user"> <xsp:expr>normalize(request.getremoteuser())</xsp:expr> <element name="remote address"> <xsp:expr>normalize(request.getremoteaddr())</xsp:expr> <element name="remote host"> <xsp:expr>normalize(request.getremotehost())</xsp:expr> <element name="authorization scheme"> <xsp:expr>normalize(request.getauthtype())</xsp:expr> </elementlist> </abschnitt> </seite> </xsp:page> und die entsprechende XSL-Datei für die HTML-Ausgabe: C:\tomcat\webapps\cocoon\beispiele\beispiel3.xsl <?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/xsl/transform"> <xsl:template match="seite"> <xsl:processing-instruction name="cocoon-format"> type="text/html" </xsl:processing-instruction> <html> <head> <title> <xsl:value-of select="titel"/> </title> </head> <body bgcolor="#ffffff"> </body> </html> <xsl:template match="titel"> <h1 align="center"> </h1> <xsl:template match="abschnitt"> <p align="center"> <i> <xsl:value-of select="@name"/> </i> <xsl:template match="item"> <p align="left">
<xsl:template match="elementlist"> <table border="1" cellpadding="2"> <tbody> </tbody> </table> <xsl:template match="element"> <tr> <td> <xsl:value-of select="@name"/> </td> <td> </td> </tr> </xsl:stylesheet> Ausgabe unter http://localhost/cocoon/beispiele/beispiel3.xml:
4. Der Weg eines Xml-Documentes In der Regel wird Cocoon über eine Implementierung der Sun-Servlet-Api angesprochen. Kernstück ist dabei die CocoonEngine org.apache.cocoon.engine. Diese Engine wird häufig (,und so haben auch wir das bei unseren Beispielen gemacht,) über ein spezielles Servlet angesprochen, welches die Methode handle(httpservletrequest request, HTTPServletResponse response) mit seinen eigenen Eingabedaten aufruft. Die Engine kapselt dabei den Arbeitsweise der anderen Elemente von Cocoon vor der Außenwelt. Innerhalb der CocoonEngine durchläuft der Request das sogenannte Reaktormodel Die Engine wählt einen Producer entsprechenden eines Attributes des Requests. Der Producer hat die Aufgabe ein XML-Document in DOM-Struktur zu erzeugen. Zum Beispiel liest er Dateien vom Dateisystem, wie in den Beispielen. Aber auch andere Quellen sind denkbar. Die Engine überprüft dann ob in dem Dokument eine processing-instruction cocoon-process vorhanden ist und ruft entsprechend des type Attributes einen Processor auf der das XML-Dokument weiter verarbeitet. Dies geschieht so lange bis keine processinginstruction cocoon-process mehr im Dokument vorhanden sind. Dann wird nach einer processing-instruction cocoon-format gesucht und das Dokument und das Response Objekt an den spezifizierten Formatter übergeben. Der übersetzt das Dokument in die gewünschte Sprache und füllt damit die Response. 5. Die Interfaces Cocoon bietet für die drei Kernelement von Cocoon, Producer, Processor und Formater, einfache und kleine Interfaces. So kann man eigene für spezielle Aufgaben angepaßte Teilstücke schreiben, sollte das notwendig werden. (Zwar lassen sich in XSP fast alle denkbaren Logikbausteine ausdrücken, leider aber ist XSP nicht sehr schnell, so das eine direkte Implementation wünschenswert/notwendig sein kann.) Die Ausschnitte aus den Interfaces soll die Übergabe der Objekte innerhalb von Cocoon und die obige Ablaufbeschreibungen verdeutlichen. org.apache.cocoon.producer: public org.w3c.dom.document getdocument(httpservletrequest request) org.apache.cocoon.processor: public org.w3c.dom.document process(org.w3c.dom.document document, java.util.dictionary parameters) (die der Engine übergebenen request und response Objekte sind im Dictionary parameters referenziert) org.apache.cocoon.formater: public void format(org.w3c.dom.document document, java.io.writer writer, java.util.dictionary parameters) public java.lang.string getencoding() public java.lang.string getmimetype() (die der Engine übergebenen request und response Objekte sind im Dictionary parameters referenziert)
6. Die Processor SQL-Processor <?cocoon-process type="sql"?> Der SQL-Processor erlaubt es, wie bereits im Beispiel 2 gesehen, Daten aus Tabellen einer Datenbank dynamisch in ein XML-Dokument einzubinden. Dazu benötigt der SQL-Processor zuerst eine Beschreibung wie er die gewünschte Datenbank erreichen kann. Dazu ist die connectiondefs Tag-Gruppe zuständig. <connectiondefs> <connection name="foo_connection"> <driver>org.gjt.mm.mysql.driver</driver> <dburl>jdbc:mysql://mysql.example.com/foo_database</dburl> <username>foo_user</username> <password>foo_password</password> </connection>...andere connections... </connectiondefs> Jede Verbindung zu einer Datenbank muß einen eindeutigen Namen haben. Des weiteren werden unbedingt ein Treiber und die Url unter der die Datenbank zu erreichen ist benötigt. Username und Password nur dann, wenn spezielle Rechte beim Zugriff auf eine Tabelle notwendig werden. Die querydefs erlauben es allgemeine Definitionen für SQL-Anfragen festzulegen: <querydefs name="standard" doc-element="options" row-element="option" connection="foo"/> <query defs="standard"/> Auf diese Definitionen kann man dann bei Anfragen zurückgreifen und spart sich das tippen. Die definierbaren Attribute entsprechen denen bei der Anfrage selbst. Die Anfrage an die Datenbank selbst steht im query tag: <query connection="foo_connection"> select name,number,message from foo_table where id={@id} order by name </query> Der SQL-Processor generiert aus der Antwort eine XML-Element das ROWSET: <ROWSET> <ROW ID="0"> <NAME>Donald Ball</NAME> <NUMBER>23</NUMBER> <MESSAGE> The Illuminati do not exist. This message paid for by the Illuminati.</MESSAGE> </ROW>... other rows... </ROWSET> Das Verhalten des Processors kann über die Attribute der query bzw. der querydefs beeinflußt werden: doc-element: bezeichnet den Tagnamen des Doc-Element der Antwort (default: ROWSET) row-element: bezeichnet den Tagname eine Zeile der Antwort (default: ROW) tag-case: legt fest ob die Spaltennamen groß oder klein geschrieben werden (preserve, upper, lower) null-indicator: legt fest ob ein Attribut NULL= YES eingefügt wird soll wenn ein Spaltenelement leer war id-attribute: legt den Namen des ID-Attributes für eine Zeile fest max-rows-attribute: wie viele Zeilen sollen zurück gegeben werden skip-rows-attribute: wie viele Zeilen sollen übersprungen werden count-attribute: welches Attribut des Doc-Element soll die Anzahl der zurückgegebenen Zeilen enthalten query-attribute: welches Attribut des Doc-Element soll SQLQuery enthalten
error-element: wie soll der ErrorTag heißen error-message-attribute: wie heißt das error-message-attribute error-message-element: wie heißt das error-message-element error-stacktrace-attribute: wie heißt das error-stacktrace-attribute error-stacktrace-element: wie heißt das error-stacktrace-element error-message-text: wie ist die Default-Fehlermeldung LDAP-Processor <?cocoon-process type="ldap"?> Der LDAP-Processor erlaubt es Fragen an einen LDAP-Dienst zu stellen und die Fragen im XML-Dokument durch die Antwort zu ersetzen. Die Arbeitsweise ist in etwa analog zu der des SQL-Processors. Wieder muß zunächst eine Definition des Verbindung zu dem LDAP-Server erfolgen, die ldapdefs: <ldap-defs> <ldap-server name=foo_server"> <initializer>com.sun.jndi.ldap.ldapctxfactory</initializer> <ldap-serverurl>ldap://ldap.weber.edu</ldap-serverurl> </ldap-server> </ldap-defs> Auf LDAP-Dienste greift man in Java über einen Context zu. Es ist also notwendig eine entsprechende ContextFactory zu spezifizieren. Auch für LDAP-Anfragen kann man querydefs festlegen: <querydefs name="standard" doc-element="options" row-element="option" server="foo_server"/> <ldap-query defs="standard"/> Die ldap-query: <ldap-query server="foo_server"> sn=*green* </ldap-query> und das Ergebnis einer solchen Anfrage: <ldapsearch> <searchresult ID="CN=DGREEN,OU=TBE,OU=AST,OU=ACAD,O=WSU"> <telephonenumber>801-626-6821</telephonenumber> <facsimiletelephonenumber>801-626-6650</facsimiletelephonenumber> <title>professor/telecommunications AND BUSINESS EDUCATION</title> <givenname>diana</givenname> <sn>green</sn> <l>b2 218</l> <ou>telecom & BUSINESS ED </ou> <mail>dgreen@weber.edu</mail> <initials>j</initials> <cn>dgreen</cn> <objectclass>newpilotperson</objectclass> <objectclass>organizationalperson</objectclass> <objectclass>person</objectclass> <objectclass>top</objectclass> </searchresult> </ldapsearch> Die möglichen Anfrage-Parameter sind: doc-element row-element id-attribute variable-left-delimiter variable-right-delimiter und die selben Error Parameter wie beim SQL- Processor
DCP Processor Der DCP-Processor stellt den ersten Versuch des Cocoon-Teams da die Programmlogik mit in das XML- Dokument einzufügen. Das Ziel war: multilanguage Support, automatischem Nachladen und einfache Wiederverwendbarkeit von Programmcode. Bis jetzt sind Java und Javascript implementiert und mehr wird es wahrscheinlich auch nicht werden. Nach der Entwicklung von XSP wird DCP nur noch zum Testen von Bruchstücken von XSP verwendet und wird außer Bug Fixing auch nicht mehr weiter entwickelt. DCP wird komplett über processing-instructions realisiert, es wird also kein spezieller Eintrag am Anfang des Dokumentes benötigt. Ein kleines Beispiel: <?xml version=1.0?> <?xml-stylesheet href= sample.xsl type= text/xsl?> <page> <!-- Scriptdateiname ist relative zum Dokumentpfad --> <?dcp-object name= util language= javascript code= test.js?> <title>eine dynamisch erzeugte Javascript Cocoon Seite</title> <p> Hi, Ich bin eine Javascript Seite die am <?dcp-content method= util.getsystemdate format= dd.mm.yyyy?> dynamisch von <em>cocoon</em> erzeugt wurde. <p> Ich wurde bereits <?dcp-content method= util.getcount?> mal aufgerufen. <p><?dcp-content method= util.getparameters?> </page> XSP Processor: (extensible Server Pages) <?cocoon-process type="xsp"?> XSP ist die mächtigste Lösung zur Contentgenrierung von Cocoon. Mit XSP lassen sich theoretisch fast alle Programmiersprachen nahtlos in ein XML-Dokument einbetten. Implementiert ist XSP im XSP-Processor jedoch zuerst nur für Java und Javascript. XSP bietet verschieden Möglichkeiten Progammlogik im XML- Dokument aufzurufen. Entweder direkt: <p> Good <xsp:logic> String timeofday=(new SimpleDateFormat("aa")).format(new Date()); if (timeofday.equals("am")){ <xsp:content>morning</xsp:content> } else { <xsp:content>afternoon</xsp:content> } </xsp:logic>! oder mit TagLibs: <p>good <util:time-of-day/>! Die eigentliche Syntax und Funktionsweise wird im Vortrag/Ausarbeitung XSP detailliert behandelt und so wird hier nur auf eine paar TagLibs eingegangen. Dies sind Programmbibliotheken für XML. Wird ein tag der zum Namespace einer solchen Bibliothek gehört gefunden, so wird er mit Hilfe von XSL durch XSP-Code ersetzt. Das veränderte Dokument wird dann mit dem XSP-Processor weiter verarbeitet.
SQL-TagLib Mit Hilfe der SQL-TagLib kann man genauso wie mit dem SQL-Processor Anfragen an Datenbanktabellen stellen. Zurerst jedoch muß der Namespace im XML-Dokument bekannt gemacht werden. <xsp:page language="java" xmlns:sql="http://www.apache.org/1999/sql" xmlns:xsp="http://www.apache.org/1999/xsp/core">... </xsp:page> dann kann man die tags aus dem sql namespace verwenden: <sql:execute-query> <sql:driver>com.informix.jdbc.ifxdriver</sql:driver> <sql:dburl> jdbc:informix-sqli://localhost:1526/database:informixserver=server </sql:dburl> <sql:username>dbuser</sql:username> <sql:password>dbpass</sql:password> <sql:skip-rows>0</sql:skip-rows> <sql:max-rows>50</sql:max-rows> <sql:null-indicator>y</sql:null-indicator> <sql:count-attribute>bob</sql:count-attribute> <sql:doc-element>rowset</sql:doc-element> <sql:row-element>row</sql:row-element> <sql:tag-case>preserve</sql:tag-case> <sql:id-attribute>id</sql:id-attribute> <sql:query> SELECT last_name, first_name, initials FROM EMPLOYEE</sql:query> </sql:execute-query> Auf den ersten Blick kann man viele Dinge wiedererkennen, die auch für den SQL-Processoer notwendig waren. Darüber hinaus kann man jedoch auch mit einem Connection Pool arbeiten: <sql:execute-query> <sql:use-connection>helpdesk</sql:use-connection>... </sql:execute-query> Die Definition eines Connection Pools erfolgt in der Datei cocoon.properties: # ORACLE processor.xsp.pool.database.helpdesk.driver=oracle.jdbc.driver.oracledriver processor.xsp.pool.database.helpdesk.url=jdbc:oracle:thin:@localhost:1521:dldf processor.xsp.pool.database.helpdesk.username=dnuser processor.xsp.pool.database.helpdesk.password=dbpass # Die maximale Anzahl der offenen Connections im Pool processor.xsp.pool.database.helpdesk.maxconnections=3 Ein weiterer Vorteil der SQL-TagLib ist: Vom jdbc-treiber zurückgegebene Daten kann man formatieren, bevor sie in das XML-Dokument eingefügt werden: <sql:column-format> <sql:name>my_date</sql:name> <sql:class> <!--muß java.text.format extenden--> java.text.simpledateformat </sql:class> <sql:parameter>mm/dd/yyyy</sql:parameter> </sql:column-format>
FP TagLib Die FP TagLib ermöglicht den Umgang mit XML-Forms. So kann man XML-Dokumente bearbeiten ohne das sie am eigentlichen Request/Response Vorgang beteiligt sind. Wieder muß zuerst der namespace der Bibliothek bekannt gemacht werden. <xsp:page language="java" xmlns:fp="http://apache.org/cocoon/xsp/fp/1.0" xmlns:xsp="http://www.apache.org/1999/xsp/core" >... </xsp:page> Und dann kann man die Tags verwenden: <fp:resource id= some_id > <fp:resource-file>dateiname</fp:resource-file> <fp:resource-node>ein XPath</fp:resource-node> <fp:default-mode>replace, insert-before, inser-after</fp:default-mode> </fp:resource> <fp:read from = fp:resource select= Xpath(kann auf mehrere Nodes zeigen) as = string(liest alle TextNodes), node(liest alle Nodes) /> <fp:write to = fp:resource select= Xpath(sollte nur auf eine Node zeigen) as = string(überschreibt TextNodes), node(überschreibt Nodes) > zu schreibender Inhalt </fp:write> <!--Child-Elemente werden nur bei einem Post-Request verarbeitet--> <fp:if-post>...</fp:if-post> <!--Child-Elemente werden nur bei einem Get-Request verarbeitet--> <fp:if-get>...</fp:if-get> <!-- User wird zu URL umgeleitet wenn alle anderen FP Befehle fehlerlos abgearbeitet sind und eine Post-Request vorliegt?-) --> <fp:redirect>url</fp:redirect>