Wirrungen

XSLT, die Transformationssprache für XML-Dokumente, eignet sich auch dazu, komplexe Dat(ei)en in andere Formate zu wandeln. Als Basis können unterschiedliche Dokumente - inklusive verschiedener Strukturen - dienen.

In Pocket speichern vorlesen Druckansicht 18 Kommentare lesen
Lesezeit: 12 Min.
Von
  • Henning Behme
Inhaltsverzeichnis

Ging es im ersten Teil dieses Tutorials darum, Grundlegendes zu XPath und XSLT vorzustellen, soll dieser zweite Teil zweierlei bringen: weitere XPath- und XSLT-Funktionen und -Elemente sowie ein tiefer strukturiertes XML-Dokument, das in HTML zu wandeln ist. Außerdem soll ein Stylesheet auf mehrere XML-Quellen zugreifen.

Bei dem Wörterbuch, das im ersten Teil als Beispiel für die Wandlung von XML in HTML diente, handelt es sich im Grunde eher um Daten als Texte, denn die (vielen) Einträge für Begriffe würden wahrscheinlich in einem DBMS residieren und von dort abgerufen werden. Das lässt sich hinsichtlich umfangreicher Texte nicht unbedingt sagen (obwohl man auch sie in einem DBMS speichern kann).

Grundlage dieses Teils sollen Artikel sein, wie sie in einer Zeitschrift die Grundlage für Online-Texte sein könnten. Die Präsentation orientiert sich - wen wunderts? - am Online-Design der iX-Artikel. Es könnte stattdessen auch ein Buch oder Ähnliches sein, aber schon ein Artikel ist hier nicht umfassend darstellbar.

Zunächst zur Struktur der Dokumente. Listing 1, ein Auszug aus der DTD für Artikel, zeigt, dass jeder Artikel eine Reihe Elemente enthalten muss sowie einige (zum Teil mehrfach) enthalten kann. title, subtitle, author, abstract müssen immer genau einmal vorhanden sein, eine section mindestens einmal (wegen des Pluszeichens), und ein listing kann wahlweise entfallen (auf Grund des Sterns). bibliographie und ixtract können einmal vorkommen, müssen es aber nicht.

Mehr Infos

Listing 1: Artikel-DTD

<!-- artikel: a small DTD to define the structure of articles
maintainer: Henning Behme; hb@ix.heise.de
-->

<!-- block and inline elements -->

<!ENTITY % inline "acronym|annotation|br|company|date|em|picture|
inline-ref|organization|person|progname|q|ref|span|
strong|sub|sup|term|time|year" >

<!ENTITY % lists "ul|dl|ol" >

<!ENTITY % block "answer|block-ref|citation|
listing|marginalia|p|question|%lists;" >

<!-- external definition for daily stuff -->
<!ENTITY % general SYSTEM "/usr/local/xml/dtd/general.dtd">
%general;

<!-- external definition for bibliographic references -->
<!ENTITY % biblio SYSTEM "/usr/local/xml/dtd/bibl-short.dtd">
%biblio;

<!-- ...............DTD _proper_............... -->

<!ELEMENT article ( title, subtitle, author, abstract, section+,
bibliographie?, listing*, ixtract?, dictionary? ) >

<!ELEMENT section ( title?, ( %block; )+ ) >

<!ELEMENT title ( #PCDATA | %inline; )* >
<!ELEMENT subtitle ( #PCDATA | %inline; )* >
<!ELEMENT abstract ( #PCDATA | %inline; )* >

<!ELEMENT listing ( title?, bu?, li-text ) >
<!ELEMENT bu ( #PCDATA | %inline; )* >
<!ELEMENT li-text ( #PCDATA | %inline; )* >
<!ELEMENT annotation ( #PCDATA | %inline; )* >
<!ELEMENT picture ( #PCDATA | %inline; )* >
<!ELEMENT block-ref EMPTY >
<!ELEMENT inline-ref EMPTY >

<!ELEMENT ixtract ( ixitem+ ) >
<!ELEMENT ixitem ( #PCDATA | %inline; )* >

<!-- attributes for the elements which have any, after all -->

<!ATTLIST article
monat CDATA #REQUIRED
jahr CDATA #REQUIRED
seite CDATA #REQUIRED
rubrik (mt|titel|review|wissen|praxis) #REQUIRED
id ID #REQUIRED
aufmacher CDATA #REQUIRED
topic CDATA #REQUIRED >

<!ATTLIST section
id ID #REQUIRED >

<!ATTLIST picture
src CDATA #REQUIRED
alt CDATA #REQUIRED
width CDATA #IMPLIED
height CDATA #IMPLIED >

<!ATTLIST block-ref
idref IDREF #REQUIRED
about CDATA #REQUIRED
kind CDATA #IMPLIED >

<!ATTLIST inline-ref
idref IDREF #REQUIRED
about CDATA #REQUIRED
kind CDATA #IMPLIED >

Eine section kann alle im Entity block definierten Elemente enthalten; die meisten folgenden entweder #PCDATA oder eins der Inline-Elemente (ebenfalls durch ein Entity definiert).

Ist erst einmal ein Artikel auf diese Weise geschrieben, müssen Stylesheets her, mit deren Hilfe ein XSLT-Prozessor - hier wird das Michael Kays Saxon sein - das Dokument in HTML wandeln kann. Listing 2 enthält das Stylesheet, das per Script aufgerufen wird:

saxon artikel.xml xsl/article.xsl

Eine Ausgabedatei zu benennen ist nicht erforderlich, wie sich gleich zeigen wird. Das Listing enthält unterhalb der Kommentarzeile, in der ‘Root’ steht, ein einziges Template, das dem Prozessor mitteilt: es sind ausgehend von der Wurzel mehrere Kindelemente zu verarbeiten. Dabei handelt es sich um section, listing, bibliographie und ixtract - und natürlich deren Kindelemente (rekursiv).

Mehr Infos

Listing 2: article.xsl

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

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/TR/REC-html40">

<xsl:include href="navigation/leftcell.xsl"/>
<xsl:include href="div.xsl"/>
<xsl:include href="listings.xsl"/>
<xsl:include href="bibliographie.xsl"/>
<xsl:include href="section.xsl"/>
<xsl:include href="ixtract.xsl"/>

<xsl:variable name="dir">html</xsl:variable>
<xsl:variable name="filesep"
select="system-property('file.separator')"/>

<!-- ....................Root............... -->
<xsl:template match="/">
<xsl:apply-templates select="//section"/>
<xsl:apply-templates select="//listing"/>
<xsl:apply-templates select="//bibliographie"/>
<xsl:apply-templates select="//ixtract"/>
</xsl:template>

</xsl:stylesheet>

Wie mit den genannten Elementen umzugehen ist, beschreiben die oberhalb des Root-Template referenzierten Dateien section.xsl et cetera. In die wiederum ist das die Elemente Betreffende ausgelagert, bis auf die Bearbeitung derjenigen, die weit ‘unten’ in der Hierarchie angesiedelt sind. Listing 2 enthält noch nichts über die Ausgabe, das beinhalten die Stylesheets für Abschnitte, Listings und so weiter.

Einzig das Verzeichnis, in dem alle HTML-Dokumente landen sollen, und die Variable für den Pfadtrenner, den alle untergeordneten Stylesheets benötigen, sind in diesem Mantel deklariert. Und außer diesen referenziert das Mantel-Stylesheet zwei XSL-Dateien, die ebenso vielen Zwecken dienen:

  • navigation/leftcell.xsl: sorgt für die Corporate Identity, in diesem Fall für all die Details, die Abbildung 1 am linken Rand enthält - eben das übliche iX-Layout.
  • div.xsl: dieses Stylesheet enthält ausschließlich so genannte named templates, Templates, die teilweise unabhängig vom Kontext angesprochen werden können; etwa den Aufruf des in der vorgenannten Datei gespeicherten do-left-cell oder den für alle zu generierenden Dateien gleichen HTML-Header (do-html-head), der in Listing 3 aufgerufen wird und in Listing 4 abgedruckt zu sehen ist.
Mehr Infos

Listing 3: section.xsl

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

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/TR/REC-html40"
xmlns:saxon="http://icl.com/saxon"
saxon:trace="no"
extension-element-prefixes="saxon">

<!-- ...................sections............... -->
<xsl:template match="section">
<xsl:variable name="thissection">
<xsl:value-of select="@id"/>
</xsl:variable>

<saxon:output method="html"
file="{$dir}{$filesep}{$thissection}.html"
doctype-public="-//W3C//DTD HTML 4.0 Transitional"
doctype-system="http://www.w3.org/TR/REC-html40"
encoding="iso-8859-1"
indent="yes">

<html>
<xsl:call-template name="do-html-head"/>
<!-- .............body mit Farben fuer die, die
ohne Stylesheets arbeiten....... -->
<body bgcolor="#ffffff" text="#000000"
link="#006699" vlink="#666666" alink="#3399cc">

<table border="0" cellspacing="0" cellpadding="3">

<xsl:call-template name="do-left-cell"/>

<!-- .............Ausgabe et cetera............. -->
<tr>
<td valign="top">
<p class="blau-weiss-s" align="right">
<strong>
<xsl:text>iX </xsl:text>
<xsl:value-of select="/article/@monat"/>
<xsl:text>/</xsl:text>
<xsl:value-of select="/article/@jahr"/>
<xsl:text>, S. </xsl:text>
<xsl:value-of select="/article/@seite"/>
<xsl:text>: </xsl:text>
<xsl:value-of select="/article/@topic"/>
</strong>
</p>
<!-- .............Ende der Ausgabe............. -->
<table border="0" width="100%"
cellpadding="3" cellspacing="0">
<tr>
<td>
<xsl:call-template name="do-article-top"/>
</td>
</tr>
</table>

<div class="text">
<!-- ..........Beruecksichtigung der ersten section -->
<xsl:choose>
<xsl:when test="position()=1">
<xsl:apply-templates select="/article/abstract"/>
<p>
<big class="first-letter">
<xsl:value-of select="substring(p[position()=1],1,1)"/>
</big>
<xsl:value-of select="substring(p[position()=1],2)"/>
</p>
<xsl:apply-templates select="p[position()>1]
| block-ref | ol | dl | ul | listing"/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="title"/>
<xsl:apply-templates select="p"/>
</xsl:otherwise>
</xsl:choose>
<!-- ..........bis hier section-Sonderbehandlung -->
</div>

</td></tr>
<xsl:call-template name="do-foot"/>
</table>
</body>
</html>
</saxon:output>
<xsl:message> - <xsl:value-of select="$thissection"/>: done</xsl:message>
</xsl:template>

</xsl:stylesheet>
Mehr Infos

Listing 4: do-html-head aus div.xsl

siehe Listing 14: div.xsl gesamt

<!-- ..............html head.................. -->
<xsl:template name="do-html-head">
<head>
<!-- ................Meta-Elemente.......... -->
<meta name="description"
content="iX - MAGAZIN FUER PROFESSIONELLE INFORMATIONSTECHNIK"/>
<meta name="copyright"
content="Copyright by Verlag Heinz Heise, Hannover, Germany"/>
<meta>
<xsl:attribute name="author">
<xsl:apply-templates select="ancestor::article/author"/>
</xsl:attribute>
</meta>
<meta>
<xsl:attribute name="keywords">
<xsl:value-of select="ancestor::article/@topic"/>
<xsl:text>, Computer, Magazin, DV-Profi, unternehmensweit,
Internet, Intranet, WorldWideWeb, Betriebssysteme,
Client-Server-Computing, Industrie, Wissenschaft,
Informationstechnik </xsl:text>
</xsl:attribute>
</meta>
<title><xsl:apply-templates select="/article/title"/></title>
<!-- .................Stylesheets........... -->
<link rel="stylesheet" href="/ix/style/farben.css" TYPE="text/css"/>
<link rel="stylesheet" href="/ix/style/alle.css" TYPE="text/css"/>
<link rel="stylesheet" href="article.css" type="text/css"/>
</head>
</xsl:template>

Ein frühes Stadium dieses Artikels: links ist, wie auf allen dazugehörigen Seiten, das iX-Menü zu erkennen (Abb. 1).

Listing 3 beschreibt, dass jeder Abschnitt in einer gesonderten Datei zu speichern ist. Als Trennorientierung dazu dienen die bei iX üblichen Zwischenüberschriften (wie die über diesem Absatz). Sie leiten jeweils eine section ein, aber das ist eine durchaus künstliche Aufteilung. Das aus dem saxon-Namensraum (statt xsl) stammende saxon:output gibt hier - wie im ersten Teil die entrys - jede section in eine Datei aus, deren Namen sich aus der Variablen dir (Wert: ‘html’), dem Pfadtrenner und dem Wert des Attributs id zusammensetzt.

Fast noch wichtiger ist, dass nicht alle sections gleich behandelt werden. Wie Abbildung 1 zeigt, soll der erste Buchstabe des ersten Absatzes der ersten Sektion einen eigenen Stil erhalten. Deshalb muss Listing 3 etwas komplizierter aufgebaut sein als ansonsten erforderlich.

Wenn der XSLT-Prozessor auf die erste section ‘trifft’, soll er zunächst den abstract ausgeben. Anschließend greift er mit

<xsl:value-of select="substring(p[position()=1],1,1)"/>

den ersten Buchstaben von Absatz eins (und nur den) heraus, um sich anschließend dem Rest des Absatzes zu widmen:

<xsl:value-of select="substring(p[position()=1],2)"/>

Die Markierung <big class="first-letter"></big> bekommt ihren eigentlichen Wert erst durch ein im HTML-Head geladenes Stylesheet, das die in Abbildung 1 zu erkennende Umsetzung bewirkt: der erste Buchstabe als das übliche Initial. substring ist eine der Funktionen, die XPath definiert (siehe den ersten Teil des Tutorials [1]) und wird hier mit unterschiedlicher Parameterzahl aufgerufen.

Im ersten Fall beinhaltet der Ausdruck im Attribut select den Teilstring des Paragraphen, der an erster Stelle steht (position()=1), angefangen beim ersten Buchstaben - und dort auch aufhört. Der zweite substring-Aufruf liefert aus demselben Absatz alles vom zweiten Buchstaben bis zum Ende; weil der dritte Parameter nicht vorhanden ist. Handelt es sich nicht um den allerersten Absatz des Artikels (xsl:otherwise), nimmt sich der Prozessor Titel und Absätze der section vor.

So komfortabel diese Art von Zugriff ist, hat sie doch einen Nachteil: Durch den Zugriff auf den ersten Absatz mit xsl:value-of statt des üblichen xsl:apply-templates gehen Markierungen verloren, wie Abbildung 1 zeigt: im zweiten Abatz sind die als Akronym gekennzeichneten Begriffe tatsächlich auch als solche bearbeitet worden. Hintergrund: ein ‘Unterbringen’ dieser Funktion innerhalb des Absatz-Templates ist natürlich auf dieselbe Weise möglich. Der erste Buchstabe lässt sich wie oben herausfischen. Soll aber der Rest des Absatzes mit xsl:apply-templates verarbeitet werden, muss es sich beim dazugehörenden select-Wert um einen Node-Set handeln, den wiederum substring nicht zurückliefert. Stattdessen ist das Ergebnis der String aus den Textknotenwerten im und unterhalb des Absatzes.

Listing 4 zeigt eins der benannten Templates, die aus div.xsl stammen. do-html-head gibt die Header-Informationen für die einzelnen Dateien aus. Bemerkenswert an dem Template ist eine Zeile. Innerhalb des Attributs keywords wird zunächst das Thema des Artikel als Wert geschrieben:

<xsl:value-of select="ancestor::article/@topic"/>

Erst danach füllt der XSLT-Prozessor den Attributwert mit den Standardbegriffen. Diese und ähnliche Bestandteile auszulagern, empfiehlt sich vor allem wegen der Einfachheit, mit der Änderungen für alles möglich sind.

Ebenfalls der Einfachheit halber ist es sinnvoll, Elemente, die so heißen wie in HTML und auch genauso, wie sie in der Quelle vorkommen, in der gewandelten Datei stehen sollen, mit Hilfe von xsl:copy zu übertragen. Listing 5 zeigt das für mehrere Elemente, was bedeutet, dass die durch die Pipe - das logische Oder - getrennten Elemente alle dieselbe Behandlung erfahren: Sie und ihr Inhalt werden kopiert.

Mehr Infos

Listing 5: xsl:copy

<!-- ...................ol|dl|ul + em............... -->
<xsl:template match="ul|dl|ol|li|dd|dt|em">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>

Schon im Template der section war eine Auswahl mit xsl:choose und xsl:when/xsl:otherwise zu sehen. Listing 6 zeigt, wie in Abbildung 1 rechts oben die Liste der vorhandenen Abschnitte und Listings sowie Bibliografie und iX-TRACT zu Stande kommen. Im Falle von Literaturangaben (hier abgefragt) und iX-TRACT (hier vorausgesetzt) schreibt bereits do-article-top die Verweise. Für die anderen existiert das darunter stehende Template (auch in div.xsl), das je nach Kontext unterschiedliche Ausgaben vorbereitet.

Mehr Infos

Listing 6: xsl:choose

<!-- Aufruf in do-article-top, in div.xsl -->

<xsl:apply-templates select="//section/title" mode="topics"/>
<xsl:apply-templates select="//listing/title" mode="topics"/>
<xsl:apply-templates select="//sidebar/title" mode="topics"/>
<xsl:if test="/article/bibliographie">
<li><a>
<xsl:attribute name="href">literatur.html</xsl:attribute>
<xsl:text>Literatur</xsl:text>
</a></li>
</xsl:if>

<!-- Template für die Ausgabe der Liste, ebenfalls in div.xsl -->
<xsl:template match="section/title |
listing/title |
sidebar/title" mode="topics">
<li>
<a>
<xsl:attribute name="href">
<xsl:choose>
<xsl:when test="parent::section">
<xsl:text>sec</xsl:text>
</xsl:when>
<xsl:when test="parent::listing">
<xsl:text>list</xsl:text>
</xsl:when>
<xsl:when test="parent::sidebar">
<xsl:text>box</xsl:text>
</xsl:when>
</xsl:choose>
<xsl:value-of select="position()"/>
<xsl:text>.html</xsl:text>
</xsl:attribute>
<xsl:choose>
<xsl:when test="parent::section[position()=1]">
<xsl:text>1. Abschnitt</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates/>
</xsl:otherwise>
</xsl:choose>
</a>
</li>
</xsl:template>

XSLT kennt zwar Variablen und Parameter, aber die lassen sich innerhalb der laufenden Transformation nicht verändern. Wie fast zu erwarten, kann man dies Problem umgehen. Dazu sei der Rahmen des Online-Artikels als Beispielanwendung verlassen, denn hier würde das Folgende keinen Sinn ergeben. Das in Listing 7 aufgerufene Template do-country bekommt im Moment seines Aufrufs erst den Wert für das Attribut thiscountry zugewiesen, sodass es jeweils den Wert hat, den das Land im Kontext des XML-Dokuments besitzt.

Mehr Infos

Listing 7: xsl:with-param

<xsl:include href="country.xsl"/>

<xsl:param name="thiscountry"/>

<!-- irgendwo "spaeter" im Stylesheet -->
<xsl:template match="country">
<xsl:param name="thiscountry">
<xsl:value-of select="."/>
</xsl:param>
<xsl:call-template name="do-country">
<xsl:with-param name="thiscountry"/>
</xsl:call-template>
</xsl:template>

<!-- eingelesenes Stylesheet "country.xsl" -->

<xsl:template name="do-country">
<xsl:choose>
<xsl:when test=".='at'">
<xsl:text>Österreich</xsl:text>
</xsl:when>

<xsl:when test=".='be'">
<xsl:text>Belgien</xsl:text>
</xsl:when>
<xsl:when test=".='bu'">
<xsl:text>Bulgarien</xsl:text>
</xsl:when>
<xsl:when test=".='de'">
<xsl:text>Deutschland</xsl:text>
</xsl:when>
<!-- weitere Staaten -->
<xsl:when test=".='uk'">
<xsl:text>Großbritannien</xsl:text>
</xsl:when>
<xsl:when test=".='us'">
<xsl:text>USA</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="."/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>

Ein beliebiges Stylesheet bindet die Datei country.xsl ein und verwendet das dort enthaltene do-country an Stellen, an denen im Quellcode eine Länderbezeichnung steht (‘at’ et cetera). Für den Wert des Elements (in diesem Fall ‘.’; ein Attribut darf es auch sein) ersetzt das benannte Template den ausgeschriebenen Namen. Denkbar wäre an dieser Stelle, eine Ausgabe in unterschiedlichen Sprachen vorzusehen. Das erforderte ein xsl:choose innerhalb des vorhandenen xsl:choose, etwa

<xsl:choose>
<xsl:when test=".='at'">
<xsl:choose>
<xsl:when test="@language='en'">
<xsl:text>Austria>/xsl:text>
</xsl:when>
. <xsl:otherwise>
<xsl:text>Österreich>/xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
... weitere Fälle ...
</xsl:choose>

Auch die nächste Möglichkeit, in XSL-Transformationen die Ausgabe zu kontrollieren, geht über das Artikelbeispiel hinaus. Gedacht sei ein Buch, das aus Kapiteln sowie darin Abschnitten und darin wiederum Unterabschnitten besteht ([2] entnommen). Für die Ausgabe aller Überschriften - unabhängig von der Ebene und vorausgesetzt, dass all diese Elemente eine Überschrift besitzen - etwa in einem Inhaltsverzeichnis ist xsl:number die richtige Anweisung. Wie Listing 8 zeigt und Abbildung 2 ‘beweist’, formatiert xsl:number die Kapitel, Abschnitte und Unterabschnitte in drei Stufen (deshalb level="multiple"). Als Format wäre beispielsweise für einen Anhang auch ‘A.1.1’ möglich, und römische Ziffern lassen sich ebenfalls verwenden. Stünde als Wert von format ‘I.i.i’ im Template, sähe das Ergebnis aus wie Abbildung 3.

Mehr Infos

Listing 8: xsl:number

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

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/TR/REC-html40">

<xsl:output method="html"/>
<!-- ....................Root............... -->
<xsl:template match="/">
<html>
<body>
<ul>
<xsl:apply-templates select="//ueberschrift"/>
</ul>
</body>
</html>
</xsl:template>

<xsl:template match="ueberschrift">
<li>
<xsl:number level="multiple"
count="kapitel|abschnitt|unterabschnitt"
format="1.1.1 "/>
<xsl:apply-templates/>
</li>
</xsl:template>

</xsl:stylesheet>

Gelegentlich kann es sinnvoll sein, aus einem XML-Dokument heraus auf Daten oder Textbruchstücke zuzugreifen, die sich in einem anderen XML-Dokument befinden. Um auf das Beispiel der iX-Artikel zurückzukommen: Innerhalb eines Quelltextes könnte ein Verweis auf einen Eintrag des Wörterbuchs, wie es der erste Teil vorstellte, enthalten sein: entweder inline oder als Block.

In diesem Fall muss für inline-ref und block-ref jeweils ein Template vorhanden sein, das den Zugriff auf das externe Dokument realisiert (siehe Listing 9). Beide Elemente sind leer und verweisen mittels ihres Attributs idref auf den Eintrag im Wörterbuch. Der Attributwert wird Inhalt der Variablen thisterm, und mit deren Hilfe kann man an xsl:apply-templates die genaue Abfrage übergeben. Handelt es sich um einen Inline-Verweis, sollen Akronym und Begriff ausgegeben werden, wie es das Template, das auf entry passt, zeigt. Im Falle eines block-ref soll die Definition des infrage stehenden Begriffs als blockquote in der Ausgabe erscheinen.

Mehr Infos

Listing 9: document()

<!-- ...................inline-/block-ref............... -->
<xsl:template match="inline-ref">
<xsl:variable name="thisterm">
<xsl:value-of select="@idref"/>
</xsl:variable>
<xsl:apply-templates
select="document('../dictionary.xml')//entry[@id=$thisterm]"/>
</xsl:template>

<xsl:template match="entry">
<xsl:value-of select="acro"/>
<xsl:text> (</xsl:text>
<xsl:value-of select="term"/>
<xsl:text>)</xsl:text>
</xsl:template>

<xsl:template match="block-ref">
<xsl:variable name="thisterm">
<xsl:value-of select="@idref"/>
</xsl:variable>
<blockquote>
<xsl:apply-templates
select="document('../dictionary.xml')//entry[@id=$thisterm]/expl[@lang='de']"/>
</blockquote>
</xsl:template>

Im Vergleich zu Abbildung 1 ist hier durch document() absichtlich Unsinn in der Ausgabe gelandet: ‘VRML’ und dessen Erklärung (Abb. 4).

Um den Unterschied hervorzuheben, ist in Abbildung 4 Nonsens generiert worden, denn statt XML hat sich VRML in den zweiten Absatz eingeschlichen (noch dazu, ohne als Akronym kleiner zu erscheinen). Im Anschluss an den zweiten Absatz schließlich erscheint die Erklärung dafür, was VRML ist, als blockquote in fetter Schrift.

In den hier wiedergegeben Listings fehlen all die Kleinigkeiten, die relativ unkompliziert zu erstellen sind: vom Bild bis zum Akronym. Und es kann keine Rede davon sein, dass mit diesem zweiten Teil die Möglichkeiten von XSLT ausgeschöpft wären.

Dennoch soll es im dritten nicht um noch mehr Funktionen/Elemente/Anweisungen gehen, sondern um den Versuch, ohne den Umweg über statische HTML-Dateien XML-Daten an die Browser auszuliefern und ‘on-the-fly’ HTML zu generieren. Online werden die Stylesheets in ganzer Länge zur Verfügung stehen.

[1] Henning Behme; XML-Programmierung; Mutabor; XSLT-Tutorial I: Grundlagen und erste Beispielanwendung

[2] Henning Behme, Stefan Mintert; XML in der Praxis, 2. Auflage; München (Addison-Wesley) 2000

Mehr Infos

iX-TRACT

  • Anhand von Online-iX-Artikeln zeigt dieser zweite Teil des XSLT-Tutorials Möglichkeiten, komplexe Dokumente in HTML zu wandeln.
  • Zu den Bestandteilen von XPath und XSLT, die hier zum Tragen kommen, gehören benannte Templates sowie xsl:choose, xsl:number und das Navigieren über Achsen.
  • XSLT erlaubt mit document() den Zugriff auf andere Dokumente als die dem XSLT-Prozessor übergebene Quelle.
Mehr Infos

Listing 10: leftcell.xsl

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

<!-- Menu fuer iX-Webseiten, die mit XSLT erstellt
werden: hier nur die Tabellenzelle links mit dem Logo
-->

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/TR/REC-html40"
xmlns:saxon="http://icl.com/saxon"
saxon:trace="no"
extension-element-prefixes="saxon">

<xsl:template name="do-left-cell">
<tr>
<td class="blau-dblau" valign="top" rowspan="2">
<div class="grau-dblau">
<a href="/" class="grau-dblau">heise online</a><br/>
<a href="/ct/" class="grau-dblau">c't</a> -
<a href="/ix/" class="grau-dblau">iX</a> -
<a href="/tp/" class="grau-dblau">Telepolis</a>
</div>

<!-- ...............IVW-Pixel zum Zaehlen......... -->
<ivwpixel/><br/>

<div class="logo">
<table border="0" cellspacing="0"
cellpadding="0" width="137" height="85">
<tr>
<td><a href="/ix/"><img
src="/ix/images/2000/ix_logo_w.gif" width="137"
height="85" alt="iX" border="0"
style="display: none" /></a></td>
</tr>
</table>
</div>

<h5>
<!-- statt im Folgenden mit Saxons entity-ref zu
arbeiten, koennte man die nbsp-Etities auch
innerhalb von xsl:text referenzieren:
<xsl:text>&nbsp;</xsl:text>
-->
<saxon:entity-ref name="nbsp"/>
<saxon:entity-ref name="nbsp"/><a href="/ix/default_en.shtml"
class="grau-dblau">iX in English</a><br/>

<saxon:entity-ref name="nbsp"/>
<saxon:entity-ref name="nbsp"/><a href="/ix/inhalt.shtml"
class="grau-dblau">Inhalt (aktuell)</a><br/>

<saxon:entity-ref name="nbsp"/>
<saxon:entity-ref name="nbsp"/><a href="/ix/iXInhalt/search.shtml"
class="grau-dblau">Inhalt (Archiv)</a><br/>

<saxon:entity-ref name="nbsp"/>
<saxon:entity-ref name="nbsp"/><a href="/ix/vorschau.shtml"
class="grau-dblau">Vorschau</a><br/>

<saxon:entity-ref name="nbsp"/>
<saxon:entity-ref name="nbsp"/><a href="/ix/impressum.shtml"
class="grau-dblau">Impressum</a><br/>

<saxon:entity-ref name="nbsp"/>
<saxon:entity-ref name="nbsp"/><a href="/newsticker/"
class="grau-dblau">Newsticker</a>
</h5>

<!-- ...............Einblenden von Werbung......... -->
<contentbanner></contentbanner>

<h5><b>iX-EXTRA</b><br/>
<saxon:entity-ref name="nbsp"/>
<saxon:entity-ref name="nbsp"/><a href="/ix/online/"
class="grau-dblau">Online-Artikel</a><br/>

<saxon:entity-ref name="nbsp"/>
<saxon:entity-ref name="nbsp"/>
<saxon:entity-ref name="nbsp"/>
<a href="/ix/online/intinfo.html"
class="grau-dblau-s">
<saxon:entity-ref name="gt"/>
<saxon:entity-ref name="nbsp"/>Internet-Infos</a><br/>

<saxon:entity-ref name="nbsp"/>
<saxon:entity-ref name="nbsp"/>
<saxon:entity-ref name="nbsp"/>
<a href="/ix/online/perl.html"
class="grau-dblau-s">
<saxon:entity-ref name="gt"/>
<saxon:entity-ref name="nbsp"/>Perl</a><br/>

<saxon:entity-ref name="nbsp"/>
<saxon:entity-ref name="nbsp"/>
<saxon:entity-ref name="nbsp"/>
<a href="/ix/online/www.html"
class="grau-dblau-s">
<saxon:entity-ref name="gt"/>
<saxon:entity-ref name="nbsp"/>WWW</a><br/>

<saxon:entity-ref name="nbsp"/>
<saxon:entity-ref name="nbsp"/><a href="/ix/urls/"
class="grau-dblau">URLs</a><br/>
<saxon:entity-ref name="nbsp"/>
<saxon:entity-ref name="nbsp"/>
<a href="/ix/forum/go.shtml?list=1&amp;g=952686372_61"
class="grau-dblau">WAP-Forum</a><br/>
<saxon:entity-ref name="nbsp"/>
<saxon:entity-ref name="nbsp"/>
<a href="/ix/forum/go.shtml?list=1&amp;g=953046695_80"
class="grau-dblau">Windows-2000-Forum</a><br/>
<saxon:entity-ref name="nbsp"/>
</h5>

<h5><b>iX-SPEZIAL</b><br/>
<saxon:entity-ref name="nbsp"/>
<saxon:entity-ref name="nbsp"/><a href="/ix/provider/"
class="grau-dblau">Provider</a><br/>

<saxon:entity-ref name="nbsp"/>
<saxon:entity-ref name="nbsp"/><a href="/ix/events/"
class="grau-dblau">Veranstaltungen</a><br/>

<saxon:entity-ref name="nbsp"/>
<saxon:entity-ref name="nbsp"/><a href="/ix/x11/"
class="grau-dblau">GUIs&amp;Graphics</a><br/>

<saxon:entity-ref name="nbsp"/>
<saxon:entity-ref name="nbsp"/><a href="/ix/linux/"
class="grau-dblau">Linux</a><br/>

<saxon:entity-ref name="nbsp"/>
<saxon:entity-ref name="nbsp"/><a href="/ix/raven/Web/"
class="grau-dblau">WorldWideWeb</a><br/>

<saxon:entity-ref name="nbsp"/>
<saxon:entity-ref name="nbsp"/>
<saxon:entity-ref name="nbsp"/><a href="/ix/raven/Web/Java/"
class="grau-dblau-s">
<saxon:entity-ref name="gt"/>
<saxon:entity-ref name="nbsp"/>Java</a><br/>

<saxon:entity-ref name="nbsp"/>
<saxon:entity-ref name="nbsp"/>
<saxon:entity-ref name="nbsp"/><a href="/ix/raven/Web/xml/timeline/"
class="grau-dblau-s">
<saxon:entity-ref name="gt"/>

<saxon:entity-ref name="nbsp"/>Timeline</a><br/>


<saxon:entity-ref name="nbsp"/>
<saxon:entity-ref name="nbsp"/>
<saxon:entity-ref name="nbsp"/><a href="/ix/raven/Web/xml/"
class="grau-dblau-s">
<saxon:entity-ref name="gt"/>
<saxon:entity-ref name="nbsp"/>XML</a>
</h5>

<h5><b>iX-SERVICE</b><br/>
<saxon:entity-ref name="nbsp"/>
<saxon:entity-ref name="nbsp"/>
<a href="ftp://ftp.heise.de/pub/ix/"
class="grau-dblau">FTP-Server</a><br/>
<saxon:entity-ref name="nbsp"/>
<saxon:entity-ref name="nbsp"/>
<saxon:entity-ref name="nbsp"/>
<a href="ftp://ftp.heise.de/pub/ix/ix_listings/"
class="grau-dblau-s"><saxon:entity-ref name="gt"/>
<saxon:entity-ref name="nbsp"/>Listings</a><br/>
<saxon:entity-ref name="nbsp"/>
<saxon:entity-ref name="nbsp"/>
<saxon:entity-ref name="nbsp"/>
<a href="ftp://ftp.heise.de/pub/ix/inhalt/"
class="grau-dblau-s"><saxon:entity-ref name="gt"/>
<saxon:entity-ref name="nbsp"/>Register</a><br/>
<saxon:entity-ref name="nbsp"/>
<saxon:entity-ref name="nbsp"/>
<a href="/abo/ix/" class="grau-dblau">Abo</a><br/>
<saxon:entity-ref name="nbsp"/>
<saxon:entity-ref name="nbsp"/>
<a href="http://www.dpunkt.de/produkte/edition-ix.html"
class="grau-dblau">Edition</a><br/>
<saxon:entity-ref name="nbsp"/>
<saxon:entity-ref name="nbsp"/><a href="/presseinfo/"
class="grau-dblau">Presse-Infos</a><br/>
</h5>

</td>

<!-- ...............Einblenden von Werbung......... -->
<td valign="top">
<heiseadvert></heiseadvert>
</td>
</tr>

</xsl:template>

</xsl:stylesheet>
Mehr Infos

Listing 11: listings.xsl

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

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/TR/REC-html40"
xmlns:saxon="http://icl.com/saxon"
saxon:trace="no"
extension-element-prefixes="saxon">

<!-- ...................listing............... -->
<xsl:template match="listing">
<xsl:variable name="thislisting">
<xsl:value-of select="position()"/>
</xsl:variable>

<saxon:output method="html"
file="{$dir}{$filesep}list{$thislisting}.html"
doctype-public="-//W3C//DTD HTML 4.0 Transitional"
doctype-system="http://www.w3.org/TR/REC-html40"
encoding="iso-8859-1"
indent="yes">

<html>
<xsl:call-template name="do-html-head"/>
<body bgcolor="#ffffff" text="#000000"
link="#006699" vlink="#666666" alink="#3399cc">

<table border="1" width="100%" cellspacing="0" cellpadding="3">

<xsl:call-template name="do-left-cell"/>


<!-- .............Ausgabe et cetera............. -->
<tr>
<td valign="top">
<p class="blau-weiss-s" align="right">
<strong>
<xsl:text>iX </xsl:text>
<xsl:value-of select="/article/@monat"/>
<xsl:text>/</xsl:text>
<xsl:value-of select="/article/@jahr"/>
<xsl:text>, S. </xsl:text>
<xsl:value-of select="/article/@seite"/>
<xsl:text>: </xsl:text>
<xsl:value-of select="/article/@topic"/>
</strong>
</p>
<!-- .............Ende der Ausgabe............. -->
<table border="0" width="100%" cellpadding="3" cellspacing="0">
<tr>
<td>
<xsl:call-template name="do-article-top"/>
</td>
</tr>
</table>
<!-- ...................the real listing............... -->
<div class="text">
<HEISETEXT>
<table border="0" width="100%" cellspacing="0" cellpadding="3">
<tr class="graublau">
<td class="grau2">
<xsl:apply-templates select="title"/>
</td>
<td class="grau2" align="right">
<xsl:text>[listing #</xsl:text>
<xsl:value-of select="position()"/>
<xsl:text>]</xsl:text>
</td>
</tr>
<tr>
<td colspan="2" bgcolor="#ccccff">
<pre>
<xsl:apply-templates select="li-text"/>
</pre>
</td>
</tr>
<tr class="graublau">
<td class="grau2" colspan="2">
<strong>
<xsl:apply-templates select="bu"/>
</strong>
</td>
</tr>
</table>
<!-- ............end of the real listing............... -->
</HEISETEXT>
</div>
</td>
</tr>

<xsl:call-template name="do-foot"/>
</table>
</body>
</html>
</saxon:output>
<xsl:message> - listing <xsl:value-of select="$thislisting"/>: done</xsl:message>
</xsl:template>

</xsl:stylesheet>
Mehr Infos

Listing 12: bibliographie.xsl

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

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/TR/REC-html40"
xmlns:saxon="http://icl.com/saxon"
saxon:trace="no"
extension-element-prefixes="saxon">

<!-- ...................bibliographie............... -->
<xsl:template match="bibliographie">

<saxon:output method="html"
file="{$dir}{$filesep}literatur.html"
doctype-public="-//W3C//DTD HTML 4.0 Transitional"
doctype-system="http://www.w3.org/TR/REC-html40"
encoding="iso-8859-1"
indent="yes">

<html>
<xsl:call-template name="do-html-head"/>
<body bgcolor="#ffffff" text="#000000"
link="#006699" vlink="#666666" alink="#3399cc">
<table border="1" width="100%" cellspacing="0" cellpadding="3">

<xsl:call-template name="do-left-cell"/>

<!-- .............Ausgabe et cetera............. -->
<tr>
<td valign="top">
<p class="blau-weiss-s" align="right">
<strong>
<xsl:text>iX </xsl:text>
<xsl:value-of select="/article/@monat"/>
<xsl:text>/</xsl:text>
<xsl:value-of select="/article/@jahr"/>
<xsl:text>, S. </xsl:text>
<xsl:value-of select="/article/@seite"/>
<xsl:text>: </xsl:text>
<xsl:value-of select="/article/@topic"/>
</strong>
</p>
<!-- .............Ende der Ausgabe............. -->
<table border="0" width="100%" cellpadding="3" cellspacing="0">
<tr>
<td>
<xsl:call-template name="do-article-top"/>
</td>
</tr>
</table>
<div class="text">
<HEISETEXT>
<!-- ...................the real listing............... -->
<table border="0" cellspacing="0" cellpadding="3">
<tr class="graublau">
<td class="weissblau">
<xsl:text>Literatur</xsl:text>
</td>
</tr>
<tr>
<td>
<xsl:apply-templates/>
</td>
</tr>
</table>
<!-- ............end of the real listing............... -->
</HEISETEXT>
</div>
</td>
</tr>

<xsl:call-template name="do-foot"/>
</table>
</body>
</html>
</saxon:output>
<xsl:message> - bibliographie: done</xsl:message>
</xsl:template>

<xsl:template match="artikel">
<p class="einzug-links">
<xsl:text>[</xsl:text>
<xsl:value-of select="position()"/>
<xsl:text>] </xsl:text>
<xsl:apply-templates select="author"/>
<xsl:text>; </xsl:text>
<xsl:apply-templates select="titel"/>
<xsl:text>; </xsl:text>
<xsl:choose>
<xsl:when test="@url">
<a>
<xsl:attribute name="href">
<xsl:value-of select="@url"/>
</xsl:attribute>
<xsl:apply-templates select="untertitel"/>
</a>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="untertitel"/>
</xsl:otherwise>
</xsl:choose>
<xsl:text>; </xsl:text>
<xsl:apply-templates select="zeitschrift"/>
<xsl:text> </xsl:text>
<xsl:apply-templates select="monat"/>
<xsl:text>/</xsl:text>
<xsl:apply-templates select="jahr"/>
<xsl:text>, S. </xsl:text>
<xsl:apply-templates select="seite"/>
</p>
</xsl:template>

<xsl:template match="artikel/author">
<xsl:value-of select="fname"/>
<xsl:text> </xsl:text>
<xsl:value-of select="lname"/>
<xsl:text>; </xsl:text>
</xsl:template>

<xsl:template match="artikel/titel|untertitel|zeitschrift|monat|jahr">
<xsl:value-of select="."/>
</xsl:template>

<xsl:template match="seite">
<xsl:apply-templates/>
</xsl:template>

</xsl:stylesheet>
Mehr Infos

Listing 13: ixtract.xsl

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

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/TR/REC-html40"
xmlns:saxon="http://icl.com/saxon"
saxon:trace="no"
extension-element-prefixes="saxon">

<!-- ...................ixtract............... -->
<xsl:template match="ixtract">

<saxon:output method="html"
file="{$dir}{$filesep}ixtract.html"
doctype-public="-//W3C//DTD HTML 4.0 Transitional"
doctype-system="http://www.w3.org/TR/REC-html40"
encoding="iso-8859-1"
indent="yes">

<html>
<xsl:call-template name="do-html-head"/>
<body bgcolor="#ffffff" text="#000000"
link="#006699" vlink="#666666" alink="#3399cc">
<table border="1" width="100%" cellspacing="0" cellpadding="3">

<xsl:call-template name="do-left-cell"/>

<!-- .............Ausgabe et cetera............. -->
<tr>
<td valign="top">
<p class="blau-weiss-s" align="right">
<strong>
<xsl:text>iX </xsl:text>
<xsl:value-of select="/article/@monat"/>
<xsl:text>/</xsl:text>
<xsl:value-of select="/article/@jahr"/>
<xsl:text>, S. </xsl:text>
<xsl:value-of select="/article/@seite"/>
<xsl:text>: </xsl:text>
<xsl:value-of select="/article/@topic"/>
</strong>
</p>
<!-- .............Ende der Ausgabe............. -->
<table border="0" width="100%" cellpadding="3" cellspacing="0">
<tr>
<td>
<xsl:call-template name="do-article-top"/>
</td>
</tr>
</table>
<div class="text">
<HEISETEXT>
<!-- ...................the real listing............... -->
<table border="0" cellspacing="0" cellpadding="3">
<tr class="graublau">
<td class="thema">
<b><xsl:text>iX-TRACT</xsl:text></b>
</td>
</tr>
<tr>
<td class="kasten">
<ul><xsl:apply-templates/></ul>
</td>
</tr>
</table>
<!-- ............end of the real listing............... -->
</HEISETEXT>
</div>
</td>
</tr>

<xsl:call-template name="do-foot"/>
</table>
</body>
</html>
</saxon:output>
<xsl:message> - iX-TRACT: done</xsl:message>
</xsl:template>

<xsl:template match="ixitem">
<li>
<xsl:apply-templates/>
</li>
</xsl:template>

</xsl:stylesheet>
Mehr Infos

Listing 14: div.xsl gesamt

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

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/TR/REC-html40"
xmlns:saxon="http://icl.com/saxon"
saxon:trace="no"
extension-element-prefixes="saxon">

<xsl:param name="thisday"/>
<xsl:param name="thismonth"/>
<xsl:param name="thisyear"/>

<!-- ..............article top.................. -->
<xsl:template name="do-article-top">
<!-- .............Dachzeile (subtitle)............. -->
<table border="0" width="100%"
cellpadding="3" cellspacing="0">
<tr>
<td class="thema">
<strong>
<xsl:apply-templates select="/article/subtitle"/>
</strong>
</td>
<td class="thema" align="right" valign="top">
<xsl:choose>
<xsl:when test="name(.)='section'">
<xsl:text>[Abschnitt </xsl:text>
<xsl:value-of select="position()"/>
<xsl:text>]</xsl:text>
</xsl:when>
<xsl:when test="name(.)='listing'">
<xsl:text>[Listings]</xsl:text>
</xsl:when>
<xsl:when test="name(.)='sidebar'">
<xsl:text>[Kasten]</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text> </xsl:text>
</xsl:otherwise>
</xsl:choose>
</td>
</tr>

<tr><td colspan="2">
<table border="0" width="100%"
cellpadding="3" cellspacing="0">
<tr>
<td>
<h2>
<xsl:apply-templates select="/article/title"/>
</h2>
<h3>
<xsl:apply-templates select="/article/author"/>
</h3>
</td>
<td>
<img src="{/article/@aufmacher}" alt="Aufmacherfoto"/>
</td>
<td valign="top" width="33%">
<h4>
<xsl:text>Other sections &amp; c.</xsl:text>
</h4>
<ul>
<xsl:apply-templates select="//section/title" mode="topics"/>
<xsl:apply-templates select="//listing/title" mode="topics"/>
<xsl:apply-templates select="//sidebar/title" mode="topics"/>
<xsl:if test="/article/bibliographie">
<li><a>
<xsl:attribute name="href">literatur.html</xsl:attribute>
<xsl:text>Literatur</xsl:text>
</a></li>
</xsl:if>
<li><a>
<xsl:attribute name="href">ixtract.html</xsl:attribute>
<xsl:text>iXtract</xsl:text>
</a></li>
</ul>
</td>
</tr>
</table>

</td>
</tr>
</table>
</xsl:template>

<!-- ..............iX line.................. -->
<xsl:template name="do-ix-line">
<tr><td class="graublau" rowspan="2" valign="top">
<img src="/images/io.ltgray.sm.gif" border="0"
hspace="20" alt="I/O"/>
<p class="graublau"><em>iX</em> Special</p>
</td>
<td><h5 class="iX">iX - MAGAZIN FÜR PROFESSIONELLE INFORMATIONSTECHNIK</h5></td>
</tr>
</xsl:template>

<!-- ..............html head.................. -->
<xsl:template name="do-html-head">
<head>
<!-- ................Meta-Elemente.......... -->
<meta name="description"
content="iX - MAGAZIN FUER PROFESSIONELLE INFORMATIONSTECHNIK"/>
<meta name="copyright"
content="Copyright by Verlag Heinz Heise, Hannover, Germany"/>
<meta>
<xsl:attribute name="author">
<xsl:apply-templates select="ancestor::article/author"/>
</xsl:attribute>
</meta>
<meta>
<xsl:attribute name="keywords">
<xsl:value-of select="ancestor::article/@topic"/>
<xsl:text>, Computer, Magazin, DV-Profi, unternehmensweit,
Internet, Intranet, WorldWideWeb, Betriebssysteme,
Client-Server-Computing, Industrie, Wissenschaft,
Informationstechnik </xsl:text>
</xsl:attribute>
</meta>
<title><xsl:apply-templates select="/article/title"/></title>
<!-- .................Stylesheets........... -->
<link rel="stylesheet" href="/ix/style/farben.css" TYPE="text/css"/>
<link rel="stylesheet" href="/ix/style/alle.css" TYPE="text/css"/>
<link rel="stylesheet" href="article.css" type="text/css"/>
</head>
</xsl:template>

<!-- ..............foot.................. -->
<xsl:template name="do-foot">
<tr>
<td valign="bottom" class="grau-dblau">
<saxon:entity-ref name="copy"/> Verlag Heinz Heise 2000
</td>

<td>
<!-- ..........forward/backward.................... -->

<p class="navig">
<xsl:if test="not(position()=1)">
<a>
<xsl:attribute name="class">navigate</xsl:attribute>
<xsl:attribute name="href">
<xsl:value-of select="preceding-sibling::section[1]/@id"/>
<xsl:text>.html</xsl:text>
</xsl:attribute>
<xsl:text>backward</xsl:text>
</a>
</xsl:if>

<xsl:if test="not(position()=1) and not(position()=last())">
<xsl:text> | </xsl:text>
</xsl:if>

<xsl:if test="not(position()=last())">
<a>
<xsl:attribute name="class">navigate</xsl:attribute>
<xsl:attribute name="href">
<xsl:value-of select="following-sibling::section/@id"/>
<xsl:text>.html</xsl:text>
</xsl:attribute>
<xsl:text>forward</xsl:text>
</a>
</xsl:if>
</p>
<!-- ..........end of forward/backward.................... -->
<p class="foot">
<xsl:text>Last modification: </xsl:text>
<xsl:value-of select="$thismonth"/>
<xsl:text>/</xsl:text>
<xsl:value-of select="$thisday"/>
<xsl:text>/</xsl:text>
<xsl:value-of select="$thisyear"/>
<xsl:text> by </xsl:text>
<a>
<xsl:attribute name="href">
<xsl:text>mailto:hb@ix.heise.de</xsl:text>
</xsl:attribute>
Henning Behme
</a>
</p>

</td>
</tr>
</xsl:template>

<!-- ...................section et al./title............... -->
<xsl:template match="section/title | listing/title | sidebar/title" mode="topics">
<li>
<a>
<xsl:attribute name="href">
<xsl:choose>
<xsl:when test="parent::section">
<xsl:text>sec</xsl:text>
</xsl:when>
<xsl:when test="parent::listing">
<xsl:text>list</xsl:text>
</xsl:when>
<xsl:when test="parent::sidebar">
<xsl:text>box</xsl:text>
</xsl:when>
</xsl:choose>
<xsl:value-of select="position()"/>
<xsl:text>.html</xsl:text>
</xsl:attribute>
<xsl:apply-templates/>
</a>
</li>
</xsl:template>
</xsl:stylesheet>
Mehr Infos

Listing 15: artikel.xml

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

<!DOCTYPE article SYSTEM "/usr/local/xml/dtd/article.dtd">

<!-- Fragmentarisches Beispiel eines Artikels, noch dazu in
fruehem Stadium; nur zum Ausprobieren -->

<article topic="XML-Programmierung"
aufmacher="xslt-tut2.jpg" id="xslt-tut2"
rubrik="praxis" seite="1001" jahr="2001" monat="2">
<title>Wirrungen</title>
<subtitle>XSLT-Tutorial II: verschachtelte Strukturen
und mehrere Ausgangsdokumente</subtitle>
<author>
<fname>Henning</fname>
<lname>Behme</lname>
</author>

<abstract><acronym>XSLT</acronym>, die Transformationssprache für
<acronym>XML</acronym>-Dokumente, eignet sich durchaus dazu, komplexe
Dat(ei)en in andere Formate zu wandeln. Als Basis
können unterschiedliche Dokumente -- inklusive
verschiedener Strukturen -- dienen.</abstract>

<section id="sec1">

<title>Anfang</title>

<p>Ging es im ersten Teil dieses Tutorials darum,
Grundlegendes zu XPath und <acronym>XSLT</acronym>
vorzustellen, so soll dieser zweite Teil zweierlei
bringen: weitere XPath- und
<acronym>XSLT</acronym>-Funktionen sowie ein tiefer
strukturiertes <acronym>XML</acronym>-Dokument, das
in <acronym>HTML</acronym> zu wandeln ist. Außerdem
soll ein Stylesheet auf mehrere
<acronym>XML</acronym>-Quellen zugreifen.</p>

<p>Bei dem Wörterbuch, das im ersten Teil als
Beispiel für die Wandlung von <inline-ref
about="dict" idref="xml"/> in
<acronym>HTML</acronym> diente, Handelt es sich im
Grunde eher um Daten als Texte, denn die (vielen)
Einträge für Begriffe würden wahrscheinlich in
einem <acronym>DBMS</acronym> residieren und von
dort abgerufen werden. Das lässt sich hinsichtl
umfangreicher Texte nicht unbedingt sagen (obwohl
man auch sie in einem <acronym>DBMS</acronym>
speichern kann).</p>

<block-ref about="dict" idref="xml"/>

<p>Grundlage dieses Teils sollen Artikel sein, wie
sie in einer Zeitschrift die Grundlage füre
Online-Texte sein könnten. Die Präsentation
orientiert sich -- wen wunderts? -- an der Art und
Weise, wie <em>iX</em>-Artikel online aussehen.</p>

<p>Zunächst zur Struktur der Dokumente. Listing**1,
ein Auszug aus der DTD für Artikel, zeigt, dass
jeder Artikel eine Reihe Elemente enthalten muss
sowie einige (zum Teil mehrfach) enthalten
kann. <em>title</em>, <em>subtitle</em>,
<em>author</em>, <em>abstract</em> müssen immer
vorhanden sein, eine <em>section</em> mindestens
einmal (wegen des Pluszeichens) und ein listing
kann wahlweise entfallen (auf Grund des
Sterns). <em>bibliographie</em> und
<em>ixtract</em> können einmal vorkommen, müssen es
aber nicht.</p>

<p>Eine <em>section</em> kann alle im Entity
<em>block</em> definierten Elemente enthalten; die
meisten folgenden entweder <em>#PCDATA</em> oder
eins der Inline-Elemente (ebenfall durch ein Entity
definiert).</p>

</section>

<section id="sec2">

<title>2. Abschnitt</title>

<p>Nur ein Dummy-Absatz</p>

</section>

<bibliographie>

<artikel url="/ix/artikel/2001/01/167/"
id="behm.ix0101">
<author>
<fname>Henning</fname>
<lname>Behme</lname>
</author>
<titel>Mutabor</titel>
<untertitel>XSLT-Tutorial I: Grundlagen und erste
Beispielanwendung</untertitel>
<zeitschrift>iX</zeitschrift>
<monat>1</monat>
<jahr>2001</jahr>
<seite>167</seite>
</artikel>

<book id="bemi00">
<titel>XML in der Praxis</titel>
<author>
<fname>Henning</fname>
<lname>Behme</lname>
</author>
<author>
<fname>Stefan</fname>
<lname>Mintert</lname>
</author>
<ort>München</ort>
<jahr>2000</jahr>
<verlag>Addison-Wesley</verlag>
</book>

</bibliographie>

<listing>
<title>DTD</title>
<bu>Auszug aus der Dokumenttyp-Definition für Artikel</bu>
<li-text>
<!ELEMENT article ( title, subtitle, author,
abstract, section+,
bibliographie?, listing*,
ixtract?, dictionary? ) >

<!ELEMENT section ( title?, ( %block; )+ ) >

<!ELEMENT title ( #PCDATA | %inline; )* >
<!ELEMENT subtitle ( #PCDATA | %inline; )* >
<!ELEMENT abstract ( #PCDATA | %inline; )* >

<!ELEMENT listing ( title?, bu?, li-text ) >
<!ELEMENT bu ( #PCDATA | %inline; )* >
<!ELEMENT li-text ( #PCDATA | %inline; )* >
<!ELEMENT annotation ( #PCDATA | %inline; )* >
<!ELEMENT picture ( #PCDATA | %inline; )* >
<!ELEMENT block-ref EMPTY >
<!ELEMENT inline-ref EMPTY >

<!ELEMENT ixtract ( ixitem+ ) >
<!ELEMENT ixitem ( #PCDATA | %inline; )* >
</li-text>
</listing>

<listing>
<title>xsl:choose</title>
<bu>Abhängig vom Elternelement Ausgaben machen</bu>
<li-text>
<xsl:template match="section/title |
listing/title |
sidebar/title" mode="topics">
<li>
<a>
<xsl:attribute name="href">
<xsl:choose>
<xsl:when test="parent::section">
<xsl:text>sec</xsl:text>
</xsl:when>
<xsl:when test="parent::listing">
<xsl:text>list</xsl:text>
</xsl:when>
<xsl:when test="parent::sidebar">
<xsl:text>box</xsl:text>
</xsl:when>
</xsl:choose>
<xsl:value-of select="position()"/>
<xsl:text>.html</xsl:text>
</xsl:attribute>
<xsl:choose>
<xsl:when test="parent::section[position()=1]">
<xsl:text>1. Abschnitt</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates/>
</xsl:otherwise>
</xsl:choose>
</a>
</li>
</xsl:template>
</li-text>
</listing>

<listing>
<title>country.xsl</title>
<bu>Wechselne Parameterwerte an xsl:choose übergeben</bu>
<li-text>
<xsl:include href="country.xsl"/>

<xsl:param name="thiscountry"/>

<!-- irgendwo "spaeter" im Stylesheet -->
<xsl:template match="country">
<xsl:param name="thiscountry">
<xsl:value-of select="."/>
</xsl:param>
<xsl:call-template name="do-country">
<xsl:with-param name="thiscountry"/>
</xsl:call-template>
</xsl:template>

<!-- eingelesenes Stylesheet "country.xsl" -->

<xsl:template name="do-country">
<xsl:choose>
<xsl:when test=".='at'">
<xsl:text>Österreich</xsl:text>
</xsl:when>

<xsl:when test=".='be'">
<xsl:text>Belgien</xsl:text>
</xsl:when>
<xsl:when test=".='bu'">
<xsl:text>Bulgarien</xsl:text>
</xsl:when>
<xsl:when test=".='de'">
<xsl:text>Deutschland</xsl:text>
</xsl:when>
<!-- weitere Staaten -->
<xsl:when test=".='uk'">
<xsl:text>Großbritannien</xsl:text>
</xsl:when>
<xsl:when test=".='us'">
<xsl:text>USA</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="."/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</li-text>
</listing>

<ixtract>
<ixitem><acronym>XSLT</acronym> eignet sich gut
dazu, aus tief verschachtelten Dokumenten eine
Reihe von <acronym>HTML</acronym>-Dateien zu
erzeugen.</ixitem>

<ixitem>Variable und Parameter erlauben es, von
außen und innerhalb des Quelldokuments die
Verarbeitung zu beeinflussen.</ixitem>

<ixitem>Aus der Verarbeitung eines Quelldokuments
heraus kann ein <acronym>XSLT</acronym>-Prozessor auf weitere
<acronym>XML</acronym>-Dokumente
zugreifen.</ixitem>

</ixtract>

</article>

(hb)