XMLidP2000

Sitemap

Sitemap

1 Einführung
1.1 Warum mehr weniger ist
1.2 Warum mehr mehr ist
1.3 Wohin die Reise geht
2 Was sind Dokumente?
2.1 Eine kurze Geschichte der Textverarbeitung
2.2 Bestandteile eines Dokumentes
2.3 Die neue, alte Idee: Strukturorientiert schreiben
2.4 Die Entwicklung des Hypertextes
2.5 Textformate im Web
2.6 Das SGML-Konzept: Generic Markup
2.7 Dokumente versus Daten
3 XML im Web
3.1 XML bei der Verwaltung von Websites
3.2 Clientseitige XML-Interpretation
3.2.1 XML mit CSS
3.2.2 XML mit XSL(T)
3.3 XML auf dem Server
3.4 Linking-Möglichkeiten von XML
3.5 XML als Datenaustauschformat
4 XML Quick Start
4.1 Dokumenttyp-Definition (DTD) und Instanzen
4.2 Verarbeitung der Dokumente
4.2.1 Beispiel: Verarbeitung mit Cost/TCL
4.2.2 Beispiel: Verarbeitung mit XSLT
4.2.3 Beispiel: XML/XSLT im Internet Explorer
4.2.4 Fazit
5 XML-DTDs: Die verständliche Beschreibung
5.1 Ein Wort zur Notation
5.2 Dokumente
5.3 Elemente
5.4 Zeichen, Namen und Zeichendaten
5.5 Kommentare
5.6 Processing Instructions
5.7 Wo bleibt Multimedia?
5.8 Dokumenttyp-Definition (DTD)
5.8.1 Elementtyp-Deklaration
5.8.2 Attributlisten-Deklaration
5.8.3 Möglichkeiten, die DTD zu gestalten und zu gliedern
5.8.4 Notation-Deklaration
6 Namensräume in XML
7 XPath: Adressierung von XML-Dokumentteilen
7.1 Zu Grunde liegendes Datenmodell
7.2 Zugriff auf den Datenbaum
7.3 Hilfe von Operatoren
7.4 Kernfunktionen für den Datenzugriff
8 XML: Linking
8.1 Notwendige Begriffe
8.2 XLink: einfache und erweiterte Links
8.2.1 Einfache Verweise
8.2.2 Erweiterte Links
8.2.3 XLink in der Praxis
8.3 XPointer: Verweise in Dokumente hinein
8.3.1 XPath-Erweiterungen in XPointer
9 Überblick über Stylesheet-Sprachen
9.1 Cascading Style Sheets
9.1.1 Wertzuweisungen
9.1.2 Formatierungsmodell
9.1.3 CSS und XML
9.1.4 Ein Beispiel: XML im Mozilla
9.2 Document Style Semantics and Specification Language
9.2.1 Flow Objects
9.2.2 Verarbeitungs-Modus
9.2.3 DSSSL praktisch
9.2.4 Langer Marsch von DSSSL nach HTML
9.3 Extensible Stylesheet Language (XSLT und XSL)
9.3.1 Verhältnis von XSLT zu XSL
9.3.2 Formatierung mit XSL
10 XSL-Transformationen
10.1 Grundsätzliches über Templates
10.2 Ergänzungen zum Datenmodell von XPath
10.3 Struktur von XSLT-Stylesheets
10.4 Den Ergebnisbaum erzeugen
10.4.1 Diverse Basiselemente
10.4.2 Formatierte Nummerierung
10.4.3 Schleifen und bedingte Verarbeitung
10.4.4 Sortieren
10.4.5 Variable und Parameter
10.4.6 Zusätzliche Funktionen
10.4.7 XSLT-Erweiterungen
10.4.8 message, output
11 XSLT in Web-Anwendungen
11.1 XSLT im Internet Explorer
11.2 Linklisten erzeugen
11.3 Details einer Literaturgeschichte
11.3.1 Sortierte Überblicksseiten
11.3.2 Kalender: einzelne Tage ausgeben
12 XML-Editoren
12.1 Übersicht
12.1.1 Emacs + PSGML (mit XML-Unterstützung)
12.1.2 XML Notepad
12.1.3 XML Spy
12.1.4 XMetal
12.1.5 Epic
12.1.6 MarkupKit (für MS Word)
12.1.7 WordPerfect Office2000
12.2 Emacs und PSGML (mit XML-Unterstützung)
12.3 XML-Notepad
12.4 XML Spy
12.5 XMetal
12.6 Epic
12.7 MarkupKit (für MS Word)
12.8 WordPerfect Office2000
12.9 Fazit
13 Entwicklung einer DTD
13.1 Auswahl einer Mehrzweck-DTD
13.2 Entwurf einer DTD
13.2.1 Dokumentanalyse
13.2.2 Tipps und Tricks
13.3 Instanzen ohne DTD
14 Herstellung dieses Buches
14.1 Zielsetzung und Randbedingungen
14.2 Definition der DTD
14.2.1 Schritt 1: Die Grobstruktur
14.2.2 Schritt 2: Elemente auf Zeichenebene
14.2.3 Schritt 3: Die Details
14.3 Formatieren des Manuskriptes
14.3.1 Konvertierung in HTML
14.3.2 Aufbereitung für den Ausdruck
14.4 Erfahrungen mit der zweiten Auflage
15 Anwendungsbeispiel Literatur
15.1 Vorüberlegungen
15.2 En détail: die Autoren in der DTD
15.3 Wie die Daten ins Web gelangen
15.3.1 Inhaltsverzeichnis generieren
15.3.2 Ausgabe der Autorendaten
15.4 Vollständige Listings
15.4.1 DTD für die Literaturgeschichte
15.4.2 DSSSL-Listing: Inhaltsverzeichnis
15.4.3 DSSSL-Listing: Ausgabe eines einzelnen Autors
15.4.4 Perl-Code für Ausgabe einzelner Autoren
16 Verteilte Softwareverwaltung mit XML
16.1 Aufgabenbeschreibung
16.2 XML als Datenbasis
16.3 Bilden von DTD-Hierarchien
16.4 Zusammentragen von verteilten XML-Fragmenten
16.5 Fazit
16.6 Stylesheet zur Transformation in HTML
17 E-Commerce mit XML
17.1 B2B-E-Commerce
17.1.1 Die Rolle von XML
17.1.2 Technische Aspekte
17.2 BMEcat
17.3 Electronic Business XML (ebXML)
17.3.1 Arbeitsgruppen
17.3.2 Zeitplan des Projekts
17.4 XML und EDIFACT
18 XML und Apache
18.1 XML-Transformation per CGI
18.1.1 Konfiguration des Servers
18.1.2 CGI-Skript: xmlhandler.cgi
18.1.3 Beispiel: von HTML nach HTML mit DSSSL oder XSLT
18.2 Cocoon
18.2.1 Extensible Server Pages (XSP)
18.2.2 Beispiel: Formatierung in PDF mit XSL
18.2.3 Beispiel: Simuliertes XLink mit Dynamic HTML/JavaScript
18.2.4 Installation
19 XHTML: Neues HTML 4 — erweiterbar
19.1 Status quo: HTML neu definiert
19.2 Modulare Zukunft
20 Transformation von XML in WML und HTML
20.1 Erzeugen der WML-Dateien
20.2 Erzeugen der HTML-Dateien
21 Ausblick
21.1 XML Schema
21.2 Programmierung mit XML-Daten
21.3 XML und Java
21.4 Resource Description Framework
21.5 Die Zukunft
A Extensible Markup Language (XML) 1.0
A.1 Einleitung
A.1.1 Herkunft und Ziele
A.1.2 Terminologie
A.2 Dokumente
A.2.1 Wohlgeformte XML-Dokumente
A.2.2 Zeichen
A.2.3 Allgemeine syntaktische Konstrukte
A.2.4 Zeichendaten und Markup
A.2.5 Kommentare
A.2.6 Processing Instructions
A.2.7 CDATA-Abschnitte
A.2.8 Prolog und Dokumenttyp-Deklaration
A.2.9 Standalone-Dokumentdeklaration
A.2.10 Behandlung von Leerraum
A.2.11 Behandlung des Zeilenendes
A.2.12 Identifikation der Sprache
A.3 Logische Strukturen
A.3.1 Start-Tags, End-Tags und Leeres-Element-Tags
A.3.2 Elementtyp-Deklarationen
A.3.3 Attributlisten-Deklaration
A.3.4 Bedingte Abschnitte
A.4 Physikalische Strukturen
A.4.1 Zeichen- und Entity-Referenzen
A.4.2 Entity-Deklarationen
A.4.3 Analysierte Entities
A.4.4 Behandlung von Entities und Referenzen durch einen XML-Prozessor
A.4.5 Konstruktion des Ersetzungstextes von internen Entities
A.4.6 Vordefinierte Entities
A.4.7 Notation-Deklarationen
A.4.8 Dokument-Entity
A.5 Konformität
A.5.1 Validierende und nicht-validierende Prozessoren
A.5.2 Benutzen von XML-Prozessoren
A.6 Notation
A.7 Anhang A: Referenzen
A.7.1 Normative Referenzen
A.7.2 Weitere Referenzen
A.8 Anhang B: Zeichenklassen
A.9 Anhang C: XML und SGML (nicht normativ)
A.10 Anhang D: Expansion von Entity- und Zeichenreferenzen (nicht normativ)
A.11 Anhang E: Deterministische Inhaltsmodelle (nicht normativ)
A.12 Anhang F: Automatische Erkennung von Zeichenkodierungen (nicht normativ)
A.13 Anhang G: XML-Arbeitsgruppe des W3C (nicht normativ)
B Verknüpfen von Style Sheets mit XML-Dokumenten Version 1.0
B.1 Die xml-stylesheet-Processing-Instruction
B.2 Anhang A: Referenzen
B.3 Anhang B: Begründung
C Verhältnis von XML zu SGML und HTML
C.1 XML und SGML
C.2 XML und HTML
D Übersichten
D.1 Cascading Style Sheets
D.1.1 CSS-Eigenschaften und -Werte
D.1.2 CSS-Muster
D.2 DSSSL: Flow Objects
D.3 Syntax der XSLT-Elemente
D.4 DTD-Fragment für XSLT-Stylesheets (nicht normativ)
D.5 Relevante Spezifikationen und Organisationen
D.5.1 International Organization for Standardization
D.5.2 World Wide Web Consortium
D.5.3 Organization for the Advancement of Structured Information Standards
D.5.4 Internet Society und Internet Engineering Task Force
D.5.5 ISO-639-Sprachcodes
D.5.6 ISO-3166-Ländercodes
D.5.7 Zeichensatz ISO-Latin-1
D.5.8 Sonderzeichen
D.6 XML-1.0-Regeln

18.2.1 Extensible Server Pages (XSP)

Die Idee der Extensible Server Pages ist nicht neu: Innerhalb von XML-Seiten wird Programmcode untergebracht, der in dem Moment ausgeführt wird, in dem ein Web-Browser darauf zugreift. Es ist das gleiche Prinzip wie bei Server Side Includes (SSI), PHP oder auch bei serverseitigem JavaScript. Diese Vorgehensweise verletzt die strikte Trennung von Inhalt, Strukur und Verarbeitung, die eine wesentliche Eigenschaft von SGML und XML sein sollte. Wir werden später an einem ausführlichen Beispiel zeigen, wie man seine XML-Dokumente frei hält von dem eingebetteten Programmcode und dennoch die Vorteile von XSP nutzt.

Um die Funktionsweise von Cocoons XSP-Prozessor zu veranschaulichen, beginnen wir aber mit einigen kleinen Beispielen aus der XSP-Dokumentation. Das folgende Beispiel zeigt eine erste XSP-Seite, die eine HTML-Seite mit dynamisch generiertem Inhalt erzeugt.

Beispiel
<?xml version="1.0"?>
<?cocoon-process type="xsp"?>
<xsp:page language="java" xmlns:xsp="http://www.apache.org/1999/XSP/Core">
 <xsp:structure>
  <xsp:include>java.text.SimpleDateFormat</xsp:include>
 </xsp:structure>
 <html>
  <head><title>Hallo</title></head>
  <body>
  <p>Guten
    <xsp:logic>
       String timeOfDay = (
              new SimpleDateFormat("aa")
              ).format(new Date());

       if (timeOfDay.equals("AM")) {
         <xsp:content>Morgen</xsp:content>
       } else {
         <xsp:content>Tag</xsp:content>
       }
    </xsp:logic>!
  </p>
  </body>
 </html>
</xsp:page>

Je nach der momentanen Tageszeit erzeugt diese Seite entweder die Ausgabe Guten Morgen! oder Guten Tag!. Der wesentliche Teil steht dabei innerhalb von <xsp:logic> und </xsp:logic>. Darin befindet sich (in diesem Beispiel) ein kleines Java-Programm, das entweder den Text Morgen oder Tag ausgibt. Eingebettet ist die gesamte Seite in das Element xsp:page. Das Element xsp:include importiert die hier benötigte Java-Bibliothek java.text.SimpleDateFormat. Es muss innerhalb eines xsp:structure-Elements stehen. Als Ergebnis des obigen Beispiels ergibt sich (nachmittags) folgende HTML-Seite:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN"
                      "http://www.w3.org/TR/REC-html40/strict.dtd">
<html>
  <head><title>Hallo</title></head>
  <body>
  <p>Guten
    Tag!
  </p>
  </body>
 </html>


<!-- This page was served in 6282 milliseconds by Cocoon 1.6.1 -->

Die abschreckende Zeitangabe entstand auf einer Sun Ultra 10 mit einer 299 MHz UltraSPARC-IIi CPU mit 128 MByte Hauptspeicher. Trotz dieser Hardware brauchte Cocoon so lange, weil aus der XSP-Seite ein Java-Class-File compiliert wurdeFussnoteUnter dem Gesichtspunkt der Geschwindigkeit ist hier auch noch von Interesse, dass die Dateien auf eine Platte geschrieben wurden, auf die per NFS zugegriffen wurde. Insgesamt war die Testumgebung also nicht performance-optimiert.. Ist diese Arbeit einmal getan, laufen spätere Zugriffe schneller ab.

18.2.1.1 XSP-Elementtypen

Das folgende Listing zeigt die DTD für XSP, wobei angenommen wird, dass der Leser in der Lage ist, DTDs zu lesen. Es schließt sich eine Beschreibung der momentan brauchbaren Elemente an. Die DTD stammt aus dem XSP Working Draft von der Apache-Site. Er beschreibt auch geplante, zukünftige Eigenschaften der XSP. Aus diesem Grund enthält die DTD auch noch einige ungenutzte und undokumentierte Elementtypen. Des Weiteren ist in der aktuellen Situation zu beklagen, dass eine Validierung gar nicht möglich ist, da in XSP wie auch in XSLT Gebrauch von den Namensräumen gemacht wird. Der Begriff der Gültigkeit von Multi-DTD- oder Multi-Namensraum-Instanzen ist aber erst einmal gar nicht definiert; XML 1.0 kennt ihn nicht. In diesem Bereich werden die Bemühungen der Schema-Arbeitsgruppe hoffentlich eine Lösung liefern.

Referenz
<!ENTITY % elements "xsp:expr | 
                     xsp:element | 
                     xsp:pi | 
                     xsp:comment">

<!ELEMENT xsp:page (xsp:structure?, xsp:logic?, xsp:content)>
<!ATTLIST xsp:page
  language CDATA #REQUIRED
  indent-result (yes|no) "no"
  xmlns:xsp CDATA #FIXED "http://www.apache.org/1999/XSP/Core"
  xml:space (default|preserve) "preserve"
>

<!ELEMENT xsp:structure (xsp:dtd?, xsp:include*)>

<!ELEMENT xsp:dtd (#PCDATA)>
<!ELEMENT xsp:include (#PCDATA)>

<!ELEMENT xsp:content (#PCDATA | xsp:logic | %elements;)*>

<!ELEMENT xsp:logic (#PCDATA | xsp:content | %element;)*>
<!ATTLIST xsp:logic xml:space (default|preserve) "preserve">

<!ELEMENT xsp:element
          (#PCDATA | 
          xsp:attribute | 
          xsp:element | 
          xsp:logic)*>
<!ATTLIST xsp:element
          name CDATA #REQUIRED>

<!ELEMENT xsp:attribute (#PCDATA)>
<!ATTLIST xsp:attribute 
          name CDATA #REQUIRED
          xml:space (default|preserve) "preserve">

<!ELEMENT xsp:pi (#PCDATA | xsp:expr>
<!ELEMENT xsp:comment (#PCDATA | xsp:expr)>
<!ELEMENT xsp:expr (#PCDATA)>  

Beschreibung der wichtigsten Elementtypen:

xsp:page

Das Element xsp:page ist das Wurzelelement einer XSP-Instanz. Es verlangt zwingend die Angabe einer Programmiersprache; im Fall von Cocoon wird java unterstützt. Der XSP-Namensraum muss in der angegebenen Weise auch in der Instanz stehen, weitere Namensraumangaben dürfen natürlich ergänzt werden.

Direkte Nachfahren des Typs xsp:logic enthalten Programmcode auf Ebene einer Klasse, das heißt die Deklaration von Feldern und Methoden.

Processing Instructions der obersten Ebene bleiben bei der Verarbeitung durch den XSP-Prozessor erhalten. Dies ist für eine nachfolgende Verarbeitung, etwa durch die XSLT-Maschine, nützlich.

xsp:structure und xsp:include

Dieses Element nimmt die Elemente vom Typ xsp:include auf, die dazu dienen, in einer sprachunabhängigen Weise, Sprachbibliotheken zu laden. Folgende Java-Pakete werden automatisch geladen:

  • java.io.*;
  • java.util.*;
  • org.w3c.dom.*;
  • org.xml.sax.*;
  • javax.servlet.*;
  • javax.servlet.http.*;
  • org.apache.cocoon.parser.*;
  • org.apache.cocoon.producer.*;
  • org.apache.cocoon.framework.*;
  • org.apache.cocoon.processor.xsp.*;
xsp:logic und xsp:content

xsp:logic enthält Programmcode, der wörtlich in das generierte und später ausgeführte Programm übernommen wird. Das Element xsp:content dient dazu, Inhalt des umgebenden Stylesheets in xsp:logic einzubetten. Die Wirkung ist die gleiche als ob vor xsp:content das Element xsp:logic geschlossen würde, dann käme der Inhalt des Content-Elements und anschließend würde ein neues Logic-Element beginnen.

xsp:element und xsp:attribute

Diese Elementtypen dienen dazu, Elemente und Attribute, deren Namen über das gleichnamige Attribut angegeben wird, in einer Instanz zu erzeugen. Der Nutzen ist momentan noch beschränkt. In Zukunft sollen Ausdrücke wie der folgende möglich sein:

<xsp:element name='{ordered ? "ol" : "ul"}'>
  <li>Item 1</li>
  <li>Item 2</li>
  <li>Item 3</li>
</xsp:element>

Zurzeit bietet die XSP-Dokumentation einzig eine programmgesteuerte Alternative an, die folgendermaßen aussieht:

<xsp:logic>
  String tagName = null;
  if (ordered) {
    tagName = "ol";
  } else {
    tagName = "ul";
  }
  xspParentElement = xspCurrentElement;
  xspNodeStack.push(xspParentElement);
  xspCurrentElement = document.createElement(tagName);
</xsp:logic>

  <li>Item 1</li>
  <li>Item 2</li>
  <li>Item 3</li>

<xsp:logic>
  xspCurrentElement = (Node) xspNodeStack.pop();
</xsp:logic>
xsp:expr
Dieses Element enthält einen Ausdruck (Expression), dessen Wert als Text-Knoten in das resultierende Dokument (bzw. dessen DOM-Struktur) eingefügt wird. Innerhalb eines anderen XSP-Elements wird der Wert von xsp:expr als Wert, nicht als Text-Knoten behandelt. Eine Ausnahme ist natürlich xsp:content, da darin enthaltene Werte grundsätzlich Text-Knoten erzeugen.

18.2.1.2 XSP-Bibliotheken

Die Bezeichnung für die XSP-Bibliotheken lautet in der Original-Dokumentation Tag Libraries. Dahinter verbirgt sich die Möglichkeit, Elementtypen mit einer bestimmten Funktion zu belegen und diese Funktion extern zu definieren. Zur Veranschaulichung folgendes Beispiel als Zitat aus der Dokumentation:

Beispiel
<?xml version="1.0"?>
<?cocoon-process type="xsp"?>
<?cocoon-process type="xslt"?>
<?xml-stylesheet href="sample.xsl" type="text/xsl"?>

<xsp:page
  language="java"
  xmlns:xsp="http://www.apache.org/1999/XSP/Core"
  xmlns:example="http://www.plenix.com/DTD/XSP/Example"
>
  <page title="Time of Day">
    <p>
      To the best of my knowledge, it's now
      <!-- Substitute time of day here -->
      <example:time-of-day format="yy/MM/dd hh:mm:ss aa"/>
    </p>
  </page>
</xsp:page>

In diesem Beispiel wird ein neuer Namensraum example deklariert. Verwendet wird die Bibliothek in Form des Elements example:time-of-day. Für die Realisierung der Bibliothek gibt es nicht etwa eine eigene Sprache; stattdessen kommt einmal mehr XSLT zum Einsatz. Ein Stylesheet hat die Aufgabe, das Element example:time-of-day mit Leben zu füllen. Dazu muss das Stylesheet einerseits die aktuelle Uhrzeit als Wert des Elements einfügen (und dazu benötigten Programmcode ebenfalls), andererseits aber auch alle Ursprungselemente in obigem Listing unverändert lassen. Diese Aufgabe erfüllt das folgende Listing, ebenfalls aus der XSP-Dokumentation zitiert:

<?xml version="1.0"?>
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xsp="http://www.apache.org/1999/XSP/Core"
  xmlns:example="http://www.plenix.com/DTD/XSP/Example">
  <xsl:template match="xsp:page">
    <xsp:page>
      <xsl:copy>
        <xsl:apply-templates select="@*"/>
      </xsl:copy>
      <xsp:structure>
        <xsp:include>java.util.Date</xsp:include>
        <xsp:include>java.text.SimpleDateFormat</xsp:include>
      </xsp:structure>
      <xsp:logic>
        /* "Example" Class Level Logic */
        private static String formatDate(Date date, String pattern) {
          if (pattern == null || pattern.length() == 0) {
            pattern = "yyyy/MM/dd hh:mm:ss aa";
          }
          return (new SimpleDateFormat(pattern)).format(date);
        }
      </xsp:logic>
      <xsl:apply-templates/>
    </xsp:page>
  </xsl:template>
  <xsl:template match="example:time-of-day">
    <xsp:expr>
      formatDate(new Date(), "<xsl:value-of select="@format"/>")
    </xsp:expr>
  </xsl:template>
  <xsl:template match="@*|node()" priority="-1">
    <xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy>
  </xsl:template>
</xsl:stylesheet>

Wie Sie sehen können, die Einsatzmöglichkeiten von XSLT sind innerhalb von Cocoon sehr vielfältig und erlauben eine sehr flexible Aufgabenlösung.

18.2.1.3 Ein XSP-Beispiel

In diesem Abschnitt möchten wir Ihnen ein XSP-Beispiel im Detail zeigen. Das Beispiel ist von der Java-Programmierung betrachtet sehr simpel, aber es verdeutlicht, wie XSP eingesetzt werden kann, ohne das XML-Dokument mit Programmcode zu verunreinigen. Den Ausgangspunkt bildet die folgende XML-Instanz mit eingebetteter DTD.

Beispiel
<?xml version="1.0"?>
<?xml-stylesheet href="notiz2html.xslt" type="text/xsl"?>
<?cocoon-process type="xslt"?>
<!DOCTYPE notiz [
  <!ELEMENT notiz   
            (titel, autor, datum, absatz+) >
  <!ELEMENT titel   (#PCDATA)             >
  <!ELEMENT autor   (#PCDATA)             >
  <!ELEMENT datum   (#PCDATA)             >
  <!ELEMENT absatz  (#PCDATA | wichtig)*  >
  <!ELEMENT wichtig (#PCDATA)             >
]>
<notiz>
 <titel>Termine</titel>
 <autor>Weihnachtsmann</autor>
 <datum>24. Dezember</datum>
 <absatz>Nicht vergessen:
    <wichtig>Geschenke austeilen</wichtig>
 </absatz>
 <absatz>    ... </absatz>
</notiz>

Das Beispiel ist so einfach, dass man es kaum erklären muss. Wir haben hier einen Dokumenttyp für eine Notiz, die aus einem Titel, einem Autor, einem Datum sowie einem oder mehreren Absätzen besteht. Innerhalb der Absätze können Textstellen als wichtig markiert werden.

Um solche Notizen nun im Web-Browser darstellen zu können, brauchen wir ein XSLT-Stylesheet, das den XML-Code in HTML wandelt. Die für Cocoon wichtigen Processing Instructions sind im Dokument bereits vorhanden. Die Stylesheet-PI verknüpft die Instanz mit notiz2html.xslt, das im folgenden Listing zu sehen ist:

<?xml version="1.0" encoding="ISO-8859-1"?>

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<!-- © 2000 Stefan Mintert -->




<!-- ====================================================== -->
<!-- Template fuer Root-Element 'notiz' -->

<xsl:template match="notiz">
<xsl:processing-instruction name="cocoon-format">type="text/html"</xsl:processing-instruction>
<html>
 <head>
  <title>Notiz</title>
  <style type="text/css">
  &lt;!--
	body {
		text-align: center;
		background: #cccccc;
	}
	table {
		padding: 1ex;
	}
	div.framed {
		margin-left:  20%;
		margin-right: 20%;
		margin-top:   4ex;
		background:   white;
		border:	      solid medium black;
	}
	span.titel {
		font-size: 200%;
	}
	.autor {
		color: #0000cc;
		font-weight: bold;
	}
	.datum {
		color: #00cc00;
		text-weight: bold;
	}
	.wichtig {
		color: white;
		background: red;
	}
	address {
		margin-top: 2ex;
	}

  --&gt;
  </style>
 </head>
 <body>
 
  <div class="framed">
    <table>
        <xsl:apply-templates/>
    </table>
  </div>
 
 <address>
   Copyright © 2000 <a href="http://www.mintert.com/">Stefan Mintert</a>.<br />
   <a href="http://www.mintert.com/xml/">XML in der Praxis</a><br />
 </address>
 </body>
</html>
</xsl:template>
<!-- ====================================================== -->




<!-- ====================================================== -->
<!-- Template fuer Elementtyp 'titel' -->

<xsl:template match="titel">
 <tr>
  <th colspan="2">
   <span class="titel"><xsl:apply-templates/></span>
  </th>
 </tr>
</xsl:template>
<!-- ====================================================== -->




<!-- ====================================================== -->
<!-- Template fuer Elementtyp 'autor' -->

<xsl:template match="autor">
 <tr>
  <td align="right">von</td>
  <td>
   <span class="autor"><xsl:apply-templates/></span>
  </td>
 </tr>
</xsl:template>
<!-- ====================================================== -->




<!-- ====================================================== -->
<!-- Template fuer Elementtyp 'datum' -->

<xsl:template match="datum">
 <tr>
  <td align="right">für den</td>
  <td>
   <span class="datum"><xsl:apply-templates/></span>
  </td>
 </tr>
</xsl:template>
<!-- ====================================================== -->




<!-- ====================================================== -->
<!-- Template fuer Elementtyp 'restzeit' -->

<xsl:template match="restzeit">
 <tr>
  <td align="right">in</td>
  <td>
   <span class="restzeit"><xsl:apply-templates/></span>
  </td>
 </tr>
</xsl:template>
<!-- ====================================================== -->




<!-- ====================================================== -->
<!-- Template fuer Elementtyp 'absatz' -->

<xsl:template match="absatz">
 <tr>
  <td></td>
  <td>
    <p class="absatz">
	   <xsl:apply-templates/>
    </p>
  </td>
 </tr>
</xsl:template>
<!-- ====================================================== -->




<!-- ====================================================== -->
<!-- Template fuer Elementtyp 'wichtig' -->

<xsl:template match="wichtig">
 <span class="wichtig"><xsl:apply-templates/></span>
</xsl:template>
<!-- ====================================================== -->


</xsl:stylesheet>

Das Stylesheet macht aus der Notiz eine einfache Tabellenform, die mittels eines eingebetteten CSS optisch noch ein wenig aufbereitet wird. In einer richtigen Anwendung sollten die CSS-Anweisungen besser in einer externen Datei stehen, damit die gleichen Daten nicht mehrfach vom Browser geladen werden müssen. Für Demonstrationszwecke können wir diesen Punkt aber vernachlässigen. Das Resultat der Cocoon-Verarbeitung ist im nächsten Listing und in Abbildung 69 zu sehen.

Die XML-Notiz nach der Wandlung und
    Darstellung im Navigator

Abbildung 69: Die XML-Notiz nach der Wandlung und Darstellung im Navigator

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN"
                      "http://www.w3.org/TR/REC-html40/strict.dtd">
<html><head><title>Notiz</title><style type="text/css">
  <!--
	body {
		text-align: center;
		background: #cccccc;
	}
	table {
		padding: 1ex;
	}
	div.framed {
		margin-left:  20%;
		margin-right: 20%;
		margin-top:   4ex;
		background:   white;
		border:	      solid medium black;
	}
	span.titel {
		font-size: 200%;
	}
	.autor {
		color: #0000cc;
		font-weight: bold;
	}
	.datum {
		color: #00cc00;
		text-weight: bold;
	}
	.wichtig {
		color: white;
		background: red;
	}
	address {
		margin-top: 2ex;
	}

  -->
  </style></head><body><div class="framed"><table>
 <tr><th colspan="2"><span class="titel">Termine</span></th></tr>
 <tr><td align="right">von</td><td><span class="autor">Weihnachtsmann</span></td></tr>
 <tr><td align="right">für den</td><td><span class="datum">24. Dezember</span></td></tr>
 <tr><td></td><td><p class="absatz">Nicht vergessen:
    <span class="wichtig">Geschenke austeilen</span>
 </p></td></tr>
 <tr><td></td><td><p class="absatz">    ... </p></td></tr>
   </table></div><address>
   Copyright © 2000 <a href="http://www.mintert.com/">Stefan Mintert</a>.<br><a href="http://www.mintert.com/xml/">XML in der Praxis</a><br></address></body></html>

<!-- This page was served in 3445 milliseconds by Cocoon 1.6.1 -->

Soweit ist die Verarbeitung ganz einfach, XSP war noch nicht im Spiel. Um nun eine dynamische Generierung von Daten vorzuführen, muss einmal mehr das Datum mitspielen. Wir wollen nun nicht nur den Inhalt des Datum-Elementes anzeigen, sondern zusätzlich berechnen, wie viele Tage bis zu diesem Termin noch vor uns liegen. Hier stellt sich zunächst das Problem, dass die Angabe 24. Dezember aus obiger Instanz nicht sehr aussagekräftig ist, weil die Jahresangabe fehlt. Wir verlangen deshalb, dass das Datum in der Form TT.MM.JJJJ angegeben wird. In einer DTD lässt sich diese Bedingung nicht formal aufschreiben. Es sei nur erwähnt, dass dies in einem XML-Schema möglich ist. Im nachfolgenden XML-Dokument steht das Datum nun in der gewünschten Form. Außerdem haben wir auf die DTD verzichtet, weil mit Hilfe von XSP gleich auch noch Transformationen durchgeführt werden, die dazu führen, dass die Instanz nur noch wohlgeformt sein wird.

<?xml version="1.0"?>
<?cocoon-process type="xslt"?>
<?xml-stylesheet href="notiz-xsp.xslt" type="text/xsl"?>
<notiz>
 <titel>Termine</titel>
 <autor>Weihnachtsmann</autor>
 <datum>24.12.2000</datum>
 <absatz>Nicht vergessen:
    <wichtig>Geschenke austeilen</wichtig>
 </absatz>
 <absatz>    ... </absatz>
</notiz>

Man beachte, dass zur Verarbeitung nun das Stylesheet notiz-xsp.xslt benutzt wird. Wie der Name schon verrät, kommt an dieser Stelle XSP zum Einsatz. Bevor wir Ihnen das Listing zeigen, möchten wir den Ablauf, der durch das Stylesheet realisiert wird, im Überblick darstellen. Die Schritte wie folgt:

Genug der Vorrede, hier ist das Stylesheet notiz-xsp.xslt für Schritt 1:

<?xml version="1.0" encoding="ISO-8859-1"?>

<xsl:stylesheet 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xsp="http://www.apache.org/1999/XSP/Core">


<!-- © 2000 Stefan Mintert -->


<!-- ====================================================== -->
<!-- Default-Template: Kopieren der Elemente -->

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

<!-- ====================================================== -->



<!-- ====================================================== -->
<!-- 
     Template fuer Element "datum":
     Kopieren des Elements und Einfuegen von
     XSP-Logic mit Java-Programmcode
-->

<xsl:template match="datum">
  <datum>
	<xsl:value-of select="text()"/>
  </datum>
  <restzeit>
    <xsp:logic>
	Date jetzt = new Date();
	DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT,Locale.GERMANY); 
 
	String terminS = "<xsl:value-of select="text()"/>";
	Date termin = new Date();
	termin = df.parse(terminS);
	long tage = (termin.getTime() - jetzt.getTime()) / 1000 / 60 / 60 / 24;
    </xsp:logic>
    <xsp:expr>tage</xsp:expr>
    <xsl:text> Tagen</xsl:text>
  </restzeit>
</xsl:template>
<!-- ====================================================== -->



<!-- ====================================================== -->
<!-- Template fuer Root-Element 'notiz' -->

<xsl:template match="notiz">

 <!-- Ausgeben der PIs fuer weitere Verarbeitung: 
      Erst XSP, dann XSLT
   -->
 <xsl:processing-instruction name="cocoon-process">type="xsp"</xsl:processing-instruction>
 <xsl:processing-instruction name="cocoon-process">type="xslt"</xsl:processing-instruction>
 <xsl:processing-instruction name="xml-stylesheet"> href="notiz2html.xslt" type="text/xsl"</xsl:processing-instruction>



 <!-- Ausgeben des neuen Root-Elements 'xsp:page' -->
 <xsp:page language="java" 
           xmlns:xsp="http://www.apache.org/1999/XSP/Core">


    <!-- Laden der benoetigten Java-Bibliotheken -->
    <xsp:structure>
	<xsp:include>java.util.Date</xsp:include>
	<xsp:include>java.text.DateFormat</xsp:include>
    </xsp:structure>


    <!-- Element 'notiz', dass nach der XSP-verarbeitung
         erzeugt wird
      -->
    <notiz>
      <xsl:apply-templates/>
    </notiz>
 </xsp:page>


</xsl:template>
<!-- ====================================================== -->



</xsl:stylesheet>

Wir beginnen die Erklärung mit dem Wurzel-Element notiz, dessen Verarbeitung mit xsl:template match="notiz" eingeleitet wird. Die drei anschließenden Zeilen erzeugen in der Ausgabe Processing Instructions, die Cocoon anweisen, das Resultat dieser Transformation nacheinander mit dem XSP-Prozessor (Schritt 2) und anschließend mit dem XSLT-Prozessor zu behandeln (Schritt 3). Letzterer soll dabei notiz2html.xslt verwenden. In Schritt 1 wird die XSP-Seite generiert, die dann von Cocoon ausgeführt wird. Dies passiert implizit und ist nicht zu erkennen. Natürlich wollten wir Ihnen einen Blick hinter die Kulissen gestatten und haben dazu diesen ersten Schritt manuell ausgeführt. Dazu ist lediglich ein Aufruf der XSLT-Maschine Xalan notwendig. Die Kommandozeile und das Ergebnis von Schritt 1 sehen Sie im nächsten Listing.

sm@brown{442}: java org.apache.xalan.xslt.Process -in notiz2.xml -xsl notiz-xsp.xslt -out schritt1.xml
========= Parsing file:/home/sm/cocoon/dokumente/demo/notiz-xsp.xslt ==========
Parse of file:/home/sm/cocoon/dokumente/demo/notiz-xsp.xslt took 1252 milliseconds
========= Parsing notiz2.xml ==========
Parse of notiz2.xml took 110 milliseconds
encoding not supported: UTF8, using Java 8859_1
=============================
Transforming...
transform took 136 milliseconds
XSLProcessor: done


sm@brown{443}: more schritt1.xml 
<?cocoon-process type="xsp"?>
<?cocoon-process type="xslt"?>
<?xml-stylesheet href="notiz2html.xslt" type="text/xsl"?>
<xsp:page language="java" 
          xmlns:xsp="http://www.apache.org/1999/XSP/Core">
<xsp:structure>
 <xsp:include>java.util.Date</xsp:include>
 <xsp:include>java.text.DateFormat</xsp:include>
</xsp:structure>
<notiz>
 <titel>Termine</titel>
 <autor>Weihnachtsmann</autor>
 <datum>24.12.2000</datum><restzeit><xsp:logic>
        Date jetzt = new Date();
        DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT,Locale.GERMANY); 
 
        String terminS = "24.12.2000";
        Date termin = new Date();
        termin = df.parse(terminS);
        long tage = (termin.getTime() - jetzt.getTime()) / 1000 / 60 / 60 / 24;
    </xsp:logic><xsp:expr>tage</xsp:expr> Tagen</restzeit>
 <absatz>Nicht vergessen:
    <wichtig>Geschenke austeilen</wichtig>
 </absatz>
 <absatz>    ... </absatz>
</notiz></xsp:page>

sm@brown{444}: which more
more:    aliased to /usr/bin/cat

Bemerkenswert ist hierbei die Zeile String terminS = "24.12.2000". Im ursprünglichen Stylesheet stand dort String terminS = "<xsl:value-of select="text()"/>". Der Ausdruck xsl:value-of wurde also von der XSLT-Maschine ausgewertet. Beachten Sie insbesondere die ungewöhnlich erscheinende Verschachtelung von Anführungszeichen.

Bei diesem Zwischenergebnis handelt es sich also nun um eine xsp:page-Seite, die wieder eine notiz-Instanz generiert. Cocoon extrahiert aus der obigen XSP-Datei eine compilierbare Java-Datei. Diese Java-Datei wird dann übersetzt und das Compilat als .class-File auf der Festplatte abgelegt. Das Java-Listing sieht wie folgt aus:

    package _home._sm._cocoon._dokumente._demo;

    import java.io.*;
    import java.util.*;
    import org.w3c.dom.*;
    import org.xml.sax.*;
    import javax.servlet.*;
    import javax.servlet.http.*;

    import org.apache.cocoon.parser.*;
    import org.apache.cocoon.producer.*;
    import org.apache.cocoon.framework.*;

    import org.apache.cocoon.processor.xsp.*;
    import org.apache.cocoon.processor.xsp.library.*;

    /* User Imports */
    
      import java.util.Date;
    
      import java.text.DateFormat;
    

    public class _notiz2 extends XSPPage {
      /* User Class Declarations */
      

      public void populateDocument(
        HttpServletRequest request,
        HttpServletResponse response,
        Document document
      )
        throws Exception
      {
	// Node stack logic variables
        Node xspParentNode = null;
        Node xspCurrentNode = document;
        Stack xspNodeStack = new Stack();

	// Make session object readily available
        HttpSession session = request.getSession(true);

        
          document.appendChild(
            document.createProcessingInstruction(
              "cocoon-process",
              "type=\"xslt\""
            )
          );
        
          document.appendChild(
            document.createProcessingInstruction(
              "xml-stylesheet",
              " href=\"notiz2html.xslt\" type=\"text/xsl\""
            )
          );
        
    xspParentNode = xspCurrentNode;
    xspNodeStack.push(xspParentNode);
    xspCurrentNode =
      document.createElement("notiz");
    xspParentNode.appendChild(xspCurrentNode);
    
    
    xspCurrentNode.appendChild(
      document.createTextNode("\n ")
    );
  
    xspParentNode = xspCurrentNode;
    xspNodeStack.push(xspParentNode);
    xspCurrentNode =
      document.createElement("titel");
    xspParentNode.appendChild(xspCurrentNode);
    
    
    xspCurrentNode.appendChild(
      document.createTextNode("Termine")
    );
  
    
    ((Element) xspCurrentNode).normalize();
    xspCurrentNode = (Node) xspNodeStack.pop();
  
    xspCurrentNode.appendChild(
      document.createTextNode("\n ")
    );
  
    xspParentNode = xspCurrentNode;
    xspNodeStack.push(xspParentNode);
    xspCurrentNode =
      document.createElement("autor");
    xspParentNode.appendChild(xspCurrentNode);
    
    
    xspCurrentNode.appendChild(
      document.createTextNode("Weihnachtsmann")
    );
  
    
    ((Element) xspCurrentNode).normalize();
    xspCurrentNode = (Node) xspNodeStack.pop();
  
    xspCurrentNode.appendChild(
      document.createTextNode("\n ")
    );
  
    xspParentNode = xspCurrentNode;
    xspNodeStack.push(xspParentNode);
    xspCurrentNode =
      document.createElement("datum");
    xspParentNode.appendChild(xspCurrentNode);
    
    
    xspCurrentNode.appendChild(
      document.createTextNode("24.12.2000")
    );
  
    
    ((Element) xspCurrentNode).normalize();
    xspCurrentNode = (Node) xspNodeStack.pop();
  
    xspParentNode = xspCurrentNode;
    xspNodeStack.push(xspParentNode);
    xspCurrentNode =
      document.createElement("restzeit");
    xspParentNode.appendChild(xspCurrentNode);
    
    
	Date jetzt = new Date();
	DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT,Locale.GERMANY); 
 
	String terminS = "24.12.2000";
	Date termin = new Date();
	termin = df.parse(terminS);
	long tage = (termin.getTime() - jetzt.getTime()) / 1000 / 60 / 60 / 24;
    
        xspCurrentNode.appendChild(
          xspExpr(tage, document)
        );
      
    xspCurrentNode.appendChild(
      document.createTextNode(" Tagen")
    );
  
    
    ((Element) xspCurrentNode).normalize();
    xspCurrentNode = (Node) xspNodeStack.pop();
  
    xspCurrentNode.appendChild(
      document.createTextNode("\n ")
    );
  
    xspParentNode = xspCurrentNode;
    xspNodeStack.push(xspParentNode);
    xspCurrentNode =
      document.createElement("absatz");
    xspParentNode.appendChild(xspCurrentNode);
    
    
    xspCurrentNode.appendChild(
      document.createTextNode("Nicht vergessen:\n    ")
    );
  
    xspParentNode = xspCurrentNode;
    xspNodeStack.push(xspParentNode);
    xspCurrentNode =
      document.createElement("wichtig");
    xspParentNode.appendChild(xspCurrentNode);
    
    
    xspCurrentNode.appendChild(
      document.createTextNode("Geschenke austeilen")
    );
  
    
    ((Element) xspCurrentNode).normalize();
    xspCurrentNode = (Node) xspNodeStack.pop();
  
    xspCurrentNode.appendChild(
      document.createTextNode("\n ")
    );
  
    
    ((Element) xspCurrentNode).normalize();
    xspCurrentNode = (Node) xspNodeStack.pop();
  
    xspCurrentNode.appendChild(
      document.createTextNode("\n ")
    );
  
    xspParentNode = xspCurrentNode;
    xspNodeStack.push(xspParentNode);
    xspCurrentNode =
      document.createElement("absatz");
    xspParentNode.appendChild(xspCurrentNode);
    
    
    xspCurrentNode.appendChild(
      document.createTextNode("    ... ")
    );
  
    
    ((Element) xspCurrentNode).normalize();
    xspCurrentNode = (Node) xspNodeStack.pop();
  
    xspCurrentNode.appendChild(
      document.createTextNode("\n")
    );
  
    
    ((Element) xspCurrentNode).normalize();
    xspCurrentNode = (Node) xspNodeStack.pop();
  
      }
    }
  

Hieran ist abzulesen, dass nach und nach die neue Notiz-Instanz durch document.createElement() und document.createTextNode() zusammengebaut wird. An der entscheidenden Stelle werden die Java-Anweisungen aus der XSP-Seite ausgeführt und das Ergebnis in das neue Dokument eingefügt. Nach diesem Schritt 2 liegt wieder eine Notiz vor, die ein neues Element namens restzeit enthält; darin steht die berechnete Anzahl der Tage. Das jetzt arbeitende Stylesheet notiz2html.xslt transformiert in Schritt 3 die Daten abschließend in die nachfolgende HTML-Form. Die Browser-Darstellungen im Navigator und Explorer sind in Abbildung 70 und Abbildung 71 zu sehen.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN"
                      "http://www.w3.org/TR/REC-html40/strict.dtd">
<html><head><title>Notiz</title><style type="text/css">
  <!--
	body {
		text-align: center;
		background: #cccccc;
	}
	table {
		padding: 1ex;
	}
	div.framed {
		margin-left:  20%;
		margin-right: 20%;
		margin-top:   4ex;
		background:   white;
		border:	      solid medium black;
	}
	span.titel {
		font-size: 200%;
	}
	.autor {
		color: #0000cc;
		font-weight: bold;
	}
	.datum {
		color: #00cc00;
		text-weight: bold;
	}
	.wichtig {
		color: white;
		background: red;
	}
	address {
		margin-top: 2ex;
	}

  -->
  </style></head><body><div class="framed"><table>
 <tr><th colspan="2"><span class="titel">Termine</span></th></tr>
 <tr><td align="right">von</td><td><span class="autor">Weihnachtsmann</span></td></tr>
 <tr><td align="right">für den</td><td><span class="datum">24.12.2000</span></td></tr><tr><td
       align="right">in</td><td><span class="restzeit">306 Tagen</span></td></tr>
 <tr><td></td><td><p class="absatz">Nicht vergessen:
    <span class="wichtig">Geschenke austeilen</span>
 </p></td></tr>
 <tr><td></td><td><p class="absatz">    ... </p></td></tr>
   </table></div><address>
   Copyright © 2000 <a href="http://www.mintert.com/">Stefan Mintert</a>.<br><a href="http://www.mintert.com/xml/">XML in der Praxis</a><br></address></body></html>

<!-- This page was served in 636 milliseconds by Cocoon 1.6.1 -->
Hier die dynamisch erzeugte
    XSP-Variante im Navigator 4

Abbildung 70: Hier die dynamisch erzeugte XSP-Variante im Navigator 4

Die XSP-Variante im Explorer 5:
    Unterschiede zum Navigator in der CSS-Interpretation

Abbildung 71: Die XSP-Variante im Explorer 5: Unterschiede zum Navigator in der CSS-Interpretation

Valid HTML 4.01!Valid CSS!