next up previous contents
Nächste Seite: 8.3.2 Sprachunterstützung Aufwärts: 8.3 Generierung der Ausgabe Vorherige Seite: 8.3 Generierung der Ausgabe   Inhalt

8.3.1 Folgerungen der Struktur

Anhand der Struktur, die das Dokument besitzt, lassen sich Gewichtungen festlegen, die als Grundlage einer Ausprägung dienen. So wurden Schlüsselwörter als präzise Stichwörter zur knappen Beschreibung einer Textpassage definiert und werden dementsprechend innerhalb des Textes durch Fettdruck hervorgehoben. An anderer Stelle werden sie gegebenenfalls als Ersatz für den gesamten Text fungieren. newterm und marker sind Abschwächungen dazu, die in einigen Ausprägungen teilweise gar nicht auftreten. Innerhalb des Textes werden sie nun als kursiv und unterstrichen dargestellt.

Code-Beispiel 5:
Die Schlüsselwörter werden in der Standardausprägung zu XHTML fett dargestellt. Der Namensraum für die Elemente wurde mit xmlns:lec="http://www-lehre.inf.uos.de/ tschnied/lecture" bekannt gemacht. Um auf bestimmte Elemente zugreifen zu können, müssen sie deshalb alle mit dem lec-Präfix aufgerufen werden. Da in einem Schlüsselwort-Element auch andere Elemente enthalten sein können, werden alle seine Kinderelemente mittels des apply-templates-Elementes aufgerufen und abgearbeitet. Da die eingefügten Werte keine Leerzeichen enthalten, wird durch das text-Element abschließend noch ein Leerzeichen angehängt.
<xsl:template match="lec:keyword">
  <b><xsl:apply-templates/></b>
  <!-- Einfuegen eines Leerzeichens -->
  <xsl:text>&#160;</xsl:text>
</xsl:template>
Derartige Vorlagen, die für jedes mögliche Element existieren, erlauben die Verarbeitung des Dokumentes in der Reihenfolge, in der die Informationen eingegeben wurden. Das ist aber nicht immer gewünscht. So ist an einigen Stellen in dem Dokument die Reihenfolge bestimmter Einträge beliebig, aber die Darstellung soll immer gleich ausfallen. Ein Kapitel zum Beispiel besteht aus einem Titel, gegebenenfalls Ersetzungstitel, Content und optionaler Zusammenfassung. Da diese alle nur maximal einmal auftreten dürfen, ist die Reihenfolge nicht wesentlich aber für die Darstellung sehr entscheidend. Der Titel soll immer als Überschrift und nicht als Unterschrift verwendet werden. Um derartige Reihenfolgen für die Ausprägung zu berücksichtigen, ist die Verarbeitung der Elemente in einer vorgegebenen Reihenfolge vorzunehmen. Deshalb wird in einer Kapitelvorlage erst der Titel und dann in Abhängigkeit der Position der Content und die Zusammenfassung ausgewertet. Die Bearbeitung der Fußnoten ist neben den im Text erscheinenden Zahlen auch erst am Ende der Ausgabe vorzunehmen. Dazu wird im Fall einer Ausgabe in mehrere Dateien die Bearbeitung der Fußnoten auch erst am Schluss eines Kapitels vorgenommen.

Code-Beispiel 6:
Für jedes Kapitel soll eine HTML-Seite erzeugt werden. Die HTML-Seite besteht immer aus dem Titel des Kapitels, gefolgt von dem Content oder einer optionalen Zusammenfassung. Sind diese ganzen Informationen verarbeitet, so müssen noch die Inhalte zu den Fußnoten angehängt werden. Das geschieht über den Aufruf einer Vorlage für Fußnoten mit einem dafür vorgesehenen Modus annotation. Da die Fußnoten beliebig tief in anderen Elementen geschachtelt sein können, werden sie unabhängig von ihrer Verzweigungsstruktur alle aufgerufen, bis auf die, die sich in weiteren Unterkapiteln befinden. Dazu werden in der vorgeschalteten for-each-Anweisung alle chapter-Elemente aussortiert. Diese Fußnoten werden erst bei der Bearbeitung der eigenen Kapitel eingefügt.
<!-- Bearbeitung des Titels -->
<h1 align="left">
  <xsl:apply-templates select="lec:title"/>
</h1>
<!-- Aufruf der Vorlagen fuer den Content und das Abstract -->
<xsl:apply-templates select="lec:content | lec:abstract"/>
<!-- Fussnoten wenn vorhanden -->
<xsl:if 
 test="content/*[not(local-name()='chapter')]//lec:footnote">
 <p>
  <xsl:for-each 
   select="lec:content/*[not(local-name()='chapter')]">
   <xsl:apply-templates 
    select=".//lec:footnote" mode="annotation"/>
  </xsl:for-each>
 </p>
 <hr/>
</xsl:if>
Eine größere Aufgabe kommt der Nummerierung der Kapitel und den damit verbundenen Links innerhalb eines Dokumentes zu. Die Nummerierung verläuft dabei ganz einfach mittels des number-Elements.
<xsl:number level="multiple" count="lec:chapter" format="1"/>
Damit wird über beliebig viele Ebenen gezählt und zwar nur alle chapter-Elemente. Die Formatierung kann zusätzlich noch angegeben werden und wird hier standardmäßig mit einem Punkt getrennt. Mögliches Beispiel wäre etwa 8.3.1. Auf diese Art lassen sich auch Verweise zu den Kapiteln innerhalb des Dokumentes realisieren. Allerdings ist es meistens nicht sinnvoll nur eine Datei zu generieren, da die Aufteilung in mehrere Dateien erhöhte Übersichtlichkeit bietet. Auch hierfür können die Nummerierungen der Kapitel herangezogen werden, da sie in der benutzten Art eine eindeutige Identifizierung bilden. Auf das Aufteilen auf mehrere Dateien wird in Kapitel 8.3.3 weiter eingegangen. Bei der Aufteilung in mehrere Dateien muss auch eine Navigation eingebaut werden. Die Navigation soll sich für diese Ausprägung entlang der eingegebenen Dokumentstruktur bewegen. Daher ist für jede Seite der Vorgänger und ein Nachfolger zu bestimmen und zu referenzieren. Der Vorgänger ist dabei immer das in der Reihenfolge vorher aufgetretene Kapitel. Ist dieses auf der gleichen Gliederungsebene, so kann einfach auf die um eins reduzierte aktuelle Kapitelnummer verwiesen werden. Sollte das Vorgängerkapitel allerdings Unterkapitel besitzen, so stellt das letzte Unterkapitel des Vorgängerkapitels den Vorgänger dar. Dazu muss das vorhergehende Kapitel rekursiv immer sein letztes Unterkapitel aufrufen, bis es bei dem der tiefsten Ebene angelangt ist. Dieses unterste Kapitel bildet dann den Vorgänger. Ist gar kein Kapitel als Vorgänger des aktuellen Kapitels vorhanden, so ist das übergeordnete Kapitel als Vorgänger einzusetzen. Diese Bestimmung des Vorgängers entspricht einer rückwärts gelesenen preorder-Traversierung der Kapitel im Baum. Die Realisierung wird in XSLT mittels Rekursion durchgeführt. Das folgene Beispiel beschreibt diese Umsetzung für die Bestimmung des Vorgängers.

Code-Beispiel 7:
Die Bestimmung wird überall anhand der Nummerierung der Kapitel durchgeführt. Dazu muss immer mittels des for-each-Elementes in den jeweiligen Kontext gewechselt werden, auch wenn im Fall der Eltern nur ein Knoten in Frage kommt. Für die Suche nach dem letzten Unterkapitel eines vorherigen Kapitels wird eine extra Vorlage get_last_child_pos aufgerufen, die rekursiv sich selber aufruft und immer weiter in die Tiefe absteigt.
<!-- Vorlage zur Bestimmung des Vorgaengers -->
<xsl:template name="get_back_pos">
 <xsl:choose>
  <!-- auf der selben Ebene ist ein vorheriges Kapitel -->
  <xsl:when test="preceding-sibling::chapter">
   <!-- merke die aktuelle Kapitelnummer -->
   <xsl:variable name="actual_pos">
    <xsl:number level="single" count="chapter"/>
   </xsl:variable>
   <!-- wechsle den Kontext zu den Eltern -->
   <xsl:for-each select="parent::content">
    <!-- wechsle den Kontext zu dem vorherigen Kapitel -->
    <xsl:for-each select="chapter[number($actual_pos) -1]">
     <!-- bestimme das letzte Unterkapitel des Vorgaengers -->
     <xsl:call-template name="get_last_child_pos"/>
    </xsl:for-each>
   </xsl:for-each>				
  </xsl:when>
  <!-- sonst waehle den Elternknoten -->
  <xsl:otherwise>
   <xsl:for-each select="parent::content">
    <xsl:for-each select="parent::chapter">
     <xsl:number level="multiple" count="chapter" format="1"/>
    </xsl:for-each>
   </xsl:for-each>
  </xsl:otherwise>
 </xsl:choose>
</xsl:template>

<!-- Kapitelnummer des tiefsten und letzten Kapitels -->
<xsl:template name="get_last_child_pos">
 <!-- wenn Unterkapitel da sind -->
 <xsl:if test="content/chapter">
 
  <!-- im letzten Kapitel weiter suchen -->
  <xsl:for-each select="content/chapter[last()]">
   <xsl:call-template name="get_last_child_pos"/>
  </xsl:for-each>
 </xsl:if>
 <!-- sonst ist das aktuelle Kapitel das gesuchte -->
 <xsl:if test="not(content/chapter)">
  <xsl:number level="multiple" count="chapter" format="1"/>			
 </xsl:if>			
</xsl:template>
Es wurden keine Anforderungen zu der Speicherungsart der Daten vorgenommen, dennoch sollte die Möglichkeit gegeben werden die Daten verteilt zu speichern und nicht in einer Datei verwalten zu müssen. Zum Einfügen verteilter Dateien werden diese über Attributangaben der Elemente, für die sie eingefügt werden sollen, spezifiziert. Die Auswertung wird in XSLT mittels der document-Funktion vorgenommen. Dazu wird die URI der einzubindenen Datei aus dem Attribut an die document-Funktion übergeben und auf diese Elemente kann dann genauso zugegriffen werden, wie auf die Elemente des eigenen Dokumentes. Dadurch lässt sich beispielsweise das Literaturverzeichnis aus einer externen Datei beziehen oder innerhalb des Dokumentes verwalten. Der externe Bezug erhält dabei den Vorrang. Auf welche Art ein solches Verzeichnis verwaltet werden soll, hängt auch von der sonstigen Datenverwaltung ab, die hier nicht näher betrachtet werden soll.

Code-Beispiel 8:
Durch Angabe einer filelocation als Attribut des bibliography-Elementes, werden die Daten aus der externen Datei bezogen. Dem Test, ob diese Angabe existiert, folgt die Zuweisung des Zugriffs auf dieses Dokument in einer Variablen items. Dadurch muss der Zugriff auf die Datei nur einmal gemacht werden und an späterer Stelle kann über die Variable in der Baumstruktur der Datei navigiert werden.
<!-- Attribut filelocation existiert -->
<xsl:if test="@filelocation">
 <!-- Zugriff auf die Datei in Variable speichern -->
 <xsl:variable name="items" 
               select="document(@filelocation)"/>
 <ul>
  <!-- fuer jeden Eintrag im Literaturverzeichnis -->
  <xsl:for-each select="$items/bibliography/item">
   <!-- ... Bearbeitung einfuegen ... -->
  </xsl:for-each>
 </ul>
</xsl:if>
Derartige Bearbeitungsschritte können beispielsweise auch für das Zusammenziehen mehrerer getrennt gespeicherter Kapitel zu einem Dokument benutzt werden. Dafür wurden einige Elemente, wie das chapter- oder example-Element, global definiert und mit dem filelocation-Attribut versehen. So lassen sich auch Definitionen oder Beispiele in einer gesonderten Datei speichern. Diese Vorgehensweise ist aber nur für XML-basierte Daten möglich. In dieser XSL-Transformation wird auch vorausgesetzt, dass es sich nur um nach dem Schema gültige XML-Dokumente handelt. Andere Dokumente müssten aufgrund ihrer Datenstruktur verarbeitet werden. Für Dateien, die keine XML-Dateien sind, ist das nicht so einfach zu lösen. Eine typisches Beispiel für die Notwendigkeit andere Dateien einzulesen, ist die Integration von Beispielcode. So kann an diversen Stellen zwar Code, der alle seine Leerzeichen, Tabs und Zeilenumbrüche beibehält, in ein XML-Dokument integriert werden, aber dieser muss direkt in dem XML-Dokument eingefügt werden. Mittels der document-Funktion ist das aus einer externen nicht-XML-Datei nicht möglich. Derartige Anwendungen können nur über eigene Erweiterungsfunktionen gelöst werden. In dem aktuellen Arbeitspapier zu XSLT 2.0 [W3CXSLTb] ist bereits eine unparsed-text-Funktion aufgenommen, die abhängig von der übergebenen URI eine Datei einliest und den Inhalt als String und ohne weitere Verarbeitung direkt in den Ergebnisbaum einfügt. Damit lassen sich in der Zukunft beispielsweise externe Codeauszüge einfügen.
next up previous contents
Nächste Seite: 8.3.2 Sprachunterstützung Aufwärts: 8.3 Generierung der Ausgabe Vorherige Seite: 8.3 Generierung der Ausgabe   Inhalt
Tanja Schniederberend 2003-06-11