Anzeige
Smartes Cloud Hosting für anspruchsvolle Projekte.
↬ Loslegen und Spaces testen ↬ Jetzt testen!
Gastautor 10. September 2003

XML-Workshop Teil 5: Style Sheets, Elemente und Attribute

Kein Beitragsbild

von Jan Winkler

Anzeige

Teil 5 unseres Workshops ist der Verwendung mehrerer Style Sheets sowie der Verwendung von Elementen, Attributen und Variablen gewidmet.

Mehrere Style Sheets verwenden
Es gibt zwei Wege, in einem XSLT-Dokument die Angaben eines anderen zu verwenden. Im ersten Fall benutzt man dazu xsl:include. Als Wert des href-Attributes erhält dies die URL der zu verwendenden Datei. Diese wird eingelesen. Die enthaltenen Angaben werden an der Stelle, an der der Aufruf stattfand, in das aktuelle Dokument eingebunden. Im zweiten Fall benutzt man das xsl:import-Element. Auch hier wird das href-Attribut mit der jeweiligen URL definiert. Der Unterschied zu xsl:include besteht darin, dass die Regeln des importierten Style Sheets Vorrang vor denen des eigentlichen Dokuments haben.

Ein Beispiel:

 <?xml version="1.0"?>

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

<xsl:import href="trans1.xsl"/>
 <xsl:import href="trans2.xsl"/>
      <xsl:include href="inc1.xsl"/>
 <!-- ... -->

<xsl:import href="inc2.xsl"/>
 <!-- ... -->
 </xsl:stylesheet>

Bitte beachten Sie, dass beide Elemente nur als Top-Level Element verwendbar sind. Außerdem sollten die xsl:import-Elemente vor allen anderen Elementen definiert werden – xsl:include kann danach überall auf Root-Ebene vertreten sein.

Elemente erzeugen
XSLT bietet zum Erzeugen der Resultate vorgefertigte Lösungen (/Elemente). Diese werden angewandt, um eine saubere Syntax des Resultat-Dokuments zu erhalten und um Knoten zu erzeugen, die innerhalb der Quelle schonverwendet wurden. Elemente werden mit xsl:element erzeugt. Dies besitzt die Attribute

  1. name (Name des Elements)
  2. namespace (Namensraum des Elements) sowie
  3. use-attribute-sets (Name der zu verwendenden Attributliste).

Der Name muss definiert werden – der Namespace und die Attributliste stehen frei. Innerhalb des xsl:element-Elements können beliebige Informationen (Text, Markup, Kommentare …) folgen.

Beispiel:

      <xsl:element name="MeinElement"
>
 Das ist mein Element.
 </xsl:element>

erzeugt:

      <MeinElement> Das ist mein Element. </MeinElement>

Attribute erzeugen
So, wie Elemente erzeugt werden können, ist es auch möglich, diesen Attribute zuzuweisen. Dazu verwendet man das xsl:attribute-Element. Es erhält als Wert des name-Attributes den zu verwendenden Namen sowie bei Bedarf ein Namespace-Attribut . Innerhalb des Elements wird der Wert des erzeugten Attributes notiert.

Beispiel:

      <xsl:element name="MeinElement"
>
 <xsl:attribute name="MeinAttribut">MeinWert</xsl:attribute>

<p>
 <xsl:attribute name="align">right</xsl:attribute>

Das ist mein Element.
 </p>
 </xsl:element>

… erzeugt:

      <MeinElement MeinAttribut="MeinWert">

<p align="right">
 Das ist mein Element.
 </p>

</MeinElement>

Bitte beachten Sie, das das Element nur innerhalb eines

  1. xsl:element-
  2. xsl:attribute-set-
  3. definierten Elements

verwendet werden kann. Außerdem sollten Sie darauf achten, dass die Attribut-Definition ohne Zwischentext direkt nach der Element-Definition stehen sollte.

Attributlisten
Mit Attributlisten kann man häufig verwendete Attribute schneller verwenden, indem man sie einem Element über use-attribute-sets zuweist und nicht jedes Mal neu definieren muss. Attributlisten werden durch das Element xsl:attribute-set definiert und beinhalten ausschließlich Attribute (xsl:attribute). Außerdem müssen sie durch das name-Attribut mit einem Namen versehen werden, der dann von Elementen verwendet werden kann.

Ein Quellbeispiel:

      <?xml
version="1.0"?>
 <?xml-stylesheet href="trans.xsl"
type="text/xsl"?>
      <!DOCTYPE A [
 <!ELEMENT
A ( B )*>
 <!ELEMENT B EMPTY>
 ]>
      <A>

<B />
 </A>

Das Style Sheet:

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

<xsl:attribute-set name="Liste1">
 <xsl:attribute name="align">right</xsl:attribute>

<xsl:attribute name="style">color:red;</xsl:attribute>

</xsl:attribute-set>
 <xsl:attribute-set name="Liste2" use-attribute-sets="Liste1">

<xsl:attribute name="src">meinbild.gif</xsl:attribute>

</xsl:attribute-set>
 <xsl:template match="A">
 <html><body>

<xsl:element name="h3" use-attribute-sets="Liste1">

Attributlisten
 </xsl:element>
 <hr />
 <xsl:apply-templates/>

</body></html>
 </xsl:template>
 <xsl:template match="B">

<xsl:element name="img" use-attribute-sets="Liste2" />

</xsl:template>
 </xsl:stylesheet>

… erzeugt:

      <html>

<body>
 <h3 align="right" style="color:red;">

Attributlisten
 </h3>
 <hr>
 <img align="right"
style="color:red;" src="meinbild.gif">
 </body>

</html>

Resultat der Transformierung
Des Weiteren unterstützt das Element die Verwendung weiterer Attribut-Listen, die als eine durch Leerzeichen getrennte Liste als Wert von use-attribute-sets definiert werden können (siehe Beispiel oben). Bitte beachten Sie, dass es sich hier um ein Top-Level Element handelt.

Verzweigung einer HTML-Datei

Resultat der Transformierung

Sonstiges erzeugen
Neben Elementen und dazugehörigen Attributen können auch Texte, Processing-Instructions oder Kommentare erzeugt werden. Da diese sich in etwa gleich der Erzeugung von Elementen verhalten, soll das folgende Beispiel genügen, um die Verwendung der einzelnen Elemente zu verdeutlichen:

      <xsl:text>
Inhalt </xsl:text>
 <xsl:processing-instruction name="xml-stylesheet">

href="test1.xsl" type="text/xsl"
 </xsl:processing-instruction>

<xsl:comment>
 Dies ist ein Kommentar.
 </xsl:comment>

… erzeugt:

      <?xml-stylesheet href="test1.xsl" type="text/xsl">

<!--
 Dies ist ein Kommentar.
 -->

Computer generierten Text erzeugen
Neben der Möglichkeit, mittels xsl:text statisch Text erzeugen zu können, bietet XSLT die Voraussetzungen, um Text durch den Parser erstellen zu lassen. Dazu wird das xsl:value-of-Element im Zusammenhang mit dessen select-Attribut verwendet. Tritt dieses auf, wird der Wert des durch select beschriebenen Knotens an dieser Stelle eingefügt.

Beispiel:

      <xsl:template
match="Person">
 <xsl:value-of select="@Anrede" />
heisst:
 <xsl:value-of select="@Vorname" />
 <xsl:text>
</xsl:text>
 <xsl:value-of select="@Nachname" />.

</xsl:template>

… erzeugt:

      Er heisst: Max Mustermann.

Bitte beachten Sie, dass innerhalb von Elementen – ob XSL oder Markup – statt dieser Schreibweise auch einfach geschweifte Klammern ({ und }) verwendet werden können. Sie stehen als Synonym für das Element xsl:value-of. Innerhalb der Klammern notieren Sie dann den Wert, den Sie üblicherweise als select-Wert notiert hätten.

Kopieren
Um Elemente des Quellbaums in das Resultat zu übernehmen, kopiert man diese mit Hilfe des Elements xsl:copy. Es kann innerhalb von Templates verwendet werden und veranlasst, dass der aktuelle Knoten bzw. das aktuelle Element in das Resultat kopiert wird. Ein eventueller Namespace wird dabei übernommen – jedoch keine Attribute oder Unterelemente. Außerdem steht wiederum das bereits bekannte Attribut use-attribute-sets zur Verfügung. Beispiel:

      <xsl:template
match="B">
 a
 <xsl:copy> b </xsl:copy>
 c

</xsl:template>

… erzeugt:

      a
 <B> b
</B>
 c

Bitte beachten Sie, dass dieses Element nur auf Element-Knoten angewandt werden darf. Außerdem besteht eine zweite Möglichkeit des Kopierens: xsl:copy-of. Dieses Element kopiert – im Gegensatz zu xsl:copy – den gesamten mit select definierten Knoten inklusive Unterknoten aus dem Quell-Dokument in das Resultat-Dokument.

Nummerierungen erzeugen
Nummerierungen können etwa bei Überschriften, Kapitel-Bezeichnungen oder einfach Listen zur Anwendung kommen. Man definiert sie mit dem Element xsl:number. Es hat folgende Attribute:

  1. level – Beschreibt, ob die Aufzählung nur auf einer (single/Standard), mehreren (multiple) oder allen (any) Zweigen des Quell-Baumes fortgeführt werden soll.
  2. count – Beschreibt einen Pattern (siehe oben), bei dessen Auftreten der Zählwert erhöht werden soll. Standard ist der Pattern des Templates.
  3. from – Beschreibt Patterns, bei deren Auftreten der Zähler beginnen soll (~zurücksetzen). Als Standard gilt jedes Elternelement.
  4. value – Funktion oder XPath-Ausdruck, der die Berechnung des Zählerstandes erlaubt. Standard ist position().
  5. format – String, der das Format der Ausgabe beschreibt (1, a, A, i, I). Alle anderen Zeichen werden als Zusatz angesehen.
  6. lang – Beschreibt eine Sprache, aus deren Alphabet die Zeichen verwendet werden sollen.
  7. letter-value – Beschreibt, ob die alphabetische (alphabetic) oder traditionelle (traditional/Standard) Zählweise verwendet werden soll.
  8. grouping-separator – Trennzeichen für Gruppierungen (wie z.B. bei 1.000.000).
  9. grouping-size – Beschreibt die Größe der Gruppierungen.

Ein Beispiel:

      <xsl:template match="H4">

<xsl:number level="any" from="H1" count="H2"/>

<xsl:text>.</xsl:text>
 <xsl:number level="any" from="H2"
count="H3"/>
 <xsl:text>.</xsl:text>
 <xsl:number
level="any" from="H3" count="H4"/>
 <xsl:text>
</xsl:text>
 <xsl:apply-templates/>
 </xsl:template>

Wiederholungen
Unter Umständen ist es notwendig, bestimmte Abläufe oder Knoten innerhalb eines Templates in einer gewissen Reihenfolge durchlaufen zu lassen. Dazu verwendet man das Element

      xsl:for-each

Quellbeispiel:

      <?xml version="1.0"
?>
 <?xml-stylesheet href="test1.xsl" type="text/xsl"
?>
      <!DOCTYPE A [
 <!ELEMENT A ( B )*>
 <!ELEMENT
B ( C | B )*>
 <!ELEMENT C EMPTY>
 ]>
      <A>

<B><C /><C /><C /></B>
 <B><C /><C
/><C /><C /></B>
 </A>

Style Sheet:

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

<xsl:template match="/">
 <table>
 <xsl:for-each
select="A/B">
 <tr>
 <th><xsl:apply-templates
select="."/></th>
 <xsl:for-each select="C">

<td><xsl:apply-templates select="."/></td>
 </xsl:for-each>

</tr>
 </xsl:for-each>
 </table>
 </xsl:template>

<xsl:template match="B">TH</xsl:template>
 <xsl:template
match="C">TD</xsl:template>
 </xsl:stylesheet>

… ergibt:

Verzweigung einer HTML-Datei

Das Resultat der Transformierung

Bedingte Abschnitte
Innerhalb von XSLT gibt es die Möglichkeit, Transformationen nur dann auszuführen, wenn eine bestimte Bedingung erfüllt ist. Dazu wird das Element

      xsl:if
      test
      true

Beispiel:

      <xsl:template match="A">
 <xsl:if
test="position() mod 2 = 0">
 <p>1</p>
 </xsl:if>

<xsl:if test="position() mod 2 = 1">
 <p>2</p>

</xsl:if>
 </xsl:template>

… ergibt:

      12121212...

Eine Auswahl treffen
Wenn die Auswahl durch xsl:if nicht mehr ausreicht bzw. zu umständlich wird, kann dieses Element durch (drei) andere Elemente ersetzt werden: xsl:choose, xsl:when und xsl:otherwise. Ähnlich wie in anderen Programmiersprachen wird so eine Mehrfachauswahl definiert. Die gesamte Auswahl wird von xsl:choose umschlossen. Darin enthalten sind xsl:when und xsl:otherwise. Das Element xsl:when beschreibt mit Hilfe des test-Attributes eine Bedingung. Ist diese erfüllt, wird der Inhalt des Elementes in den Resultat-Baum übernommen – die anderen Bedingungen werden nicht weiter betrachtet, der Parser schreitet mit dem nächsten Knoten nach dem schließenden xsl:choose-Tag fort. Ist die Bedingung nicht erfüllt, schreitet der Parser zum nächsten xsl:when weiter und prüft diese. Wurde auch die letzte Bedingung nicht erfüllt, wird letztlich der Inhalt des xsl:otherwise-Elements übernommen. Beispiel:

      <xsl:template match="C">
 <xsl:choose>
 <xsl:when
test="position() mod 3 = 0"><p>0</p></xsl:when>

<xsl:when test="position() mod 3 = 1"><p>1</p></xsl:when>

<xsl:otherwise><p>2</p></xsl:otherwise>
 </xsl:choose>

</xsl:template>

… ergibt: 120120120120…

Sortieren
Die Reihenfolge von Daten ist besonders bei langen unübersichtlichen Listen sehr wichtig. Das Sortieren der Daten kann mit XSLT bestimmt und beeinflusst werden. Wird das Element

      xsl:sort
      select, data-type,
lang, order
      case-order
  1. select

    – enthält einen Pattern (Standard ist …), der beschreibt, welche Knoten sortiert werden sollen.

  2. lang

    – enthält eine Sprachdefinition (de, en, …) die zur Sortierung verwendet werden soll.

  3. data-type

    – beschreibt, ob die zu sortierenden Knoten wie Strings (text/Standard), Zahlen (number) oder andere Datentypen (Angabe des Datentypes nach XML-Names) sortiert werden sollen.

  4. order

    – beschreibt, ob die Daten aufsteigend (ascending/Standard) oder absteigend (descending) sortiert werden soll.

  5. case-order 

    – beschreibt, ob bei data-type=“text“ die kleinen (upper-first) oder die großen Buchstaben (lower-first) als erstes einsortiert werden sollen. (Also ob a,b,c,A,B,C oder A,B,C,a,b,c)

Als Beispiel wollen wir unser Adressbuch aus dem ersten Kapitel nach Namen sortiert ausgeben lassen. Wir fügen dem Buch allerdings noch einige Personen hinzu:

      <?xml version="1.0" ?>
 <?xml-stylesheet
href="trans.xsl" type="text/xsl"?>
 <Adressbuch>

<Kunde Name="Max Mustermann">
 <Adresse>
 <Strasse>Musterstrasse
14</Strasse>
 <PLZ>12345</PLZ><Ort>Mustehausen</Ort>

</Adresse>
 </Kunde>
 <Kunde Name="August Ausgedacht">

<Adresse>
 <Strasse>Gibts-Nicht-Weg 37</Strasse>
 <PLZ>67890</PLZ><Ort>Augsburg</Ort>

</Adresse>
 </Kunde>
 
      <Kunde Name="Gunter
Gibtsnicht">
 <Adresse>
 <Strasse>Hauptstrasse 001</Strasse>

<PLZ>65381</PLZ><Ort>Berlin</Ort>
 </Adresse>

</Kunde>
 <Kunde Name="Jutta Jefferson">
 <Adresse>

<Strasse>Bahnhofsweg 123</Strasse>
 <PLZ>86413</PLZ><Ort>Hamburg</Ort>

</Adresse>
 </Kunde>
      </Adressbuch>

Als Style Sheet benutzen wir:

      <?xml version="1.0"?>

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

<xsl:template match="/">
 <h1>Kunden</h1>
 <table>

<tr><th>Kunde</th><td>Strasse</td><td>PLZ
Ort</td></tr>
 <xsl:for-each select="Adressbuch/Kunde">

<xsl:sort select="@Name"/>
 <tr>
 <th><xsl:value-of
select="@Name"/></th>
 <td><xsl:value-of select="Adresse/Strasse"
/></td>
 <td>
 <xsl:value-of select="Adresse/PLZ"
/>
 <xsl:text> </xsl:text>
 <xsl:value-of select="Adresse/Ort
"/>
 </td>
 </tr>
 </xsl:for-each>
 </table>

</xsl:template>
 </xsl:stylesheet>
      

      
Verzweigung einer HTML-Datei
Resultat der Transformierung

Bitte beachten Sie, das dieses Element nur innerhalb von

      xsl:apply-templates
      xsl:for-each

Variablen und Parameter
Wenn innerhalb des gesamten Dokumentes ein bestimmter Text immer wieder auftritt oder es Schwierigkeiten mit dem Erstellen von Attributen gibt (weil acb=“def=“““ einen Fehler ergibt), können Variablen zum Einsatz kommen. Diese definiert man mit Hilfe des xsl:variable- oder xsl:param-Elements. Beide funktionieren in etwa gleich: Als Wert des name-Attributes wird der Variablenname definiert und innerhalb des Elements der Wert. Dieser kann aus fast allen beliebigen Dingen bestehen (Text, Markup, …).

Einziger Unterschied der beiden ist, dass der Wert von xsl:param als Standardwert gilt; wenn das Template oder Style Sheet, in dem das xsl:param-Element auftritt, aufgerufen wird, können die Parameter (xsl:param) als Standardwerte verwendet werden (siehe unten). Um die Werte nun wiederum abzurufen, wird xsl:value-of (bzw. { und }) benutzt und diesem ein Dollar-Zeichen ($) sowie der Variablenname übergeben. Beispiel:

      <xsl:variable
name="wert">@Name="Max Mustermann"</xsl:variable>

<xsl:value-of select="Adressbuch/Kunde[$wert]"/>

… gibt den Inhalt des Kunden mit dem Namen „Max Mustermann“ aus.

Bitte beachten Sie die Lebensdauer von Variablen: Eine Variable besteht nur innerhalb eines Templates oder Style Sheets. Wird innerhalb eines untergeordneten Templates ein neuer Wert für die Variable definiert, so überschreibt dies nicht die eigentliche Variable. Ist der Bereich des neuen Wertes zu Ende, tritt der vorherige wieder in Kraft. Bitte beachten Sie ausserdem, dass Variablen (xsl:variable) entweder als Top-Level Element oder innerhalb eines Templates definiert werden können – Parameter (xsl:param) dagegen können nur als Top-Level Elemente gelten.

Um Parameter innerhalb eines Templates verwenden zu können, müssen diese an das jeweilige Template übergeben werden. Dies geschieht mittels des Elements xsl:with-param, welches als Attribut den Namen des Parameters erhält. Wird es aufgerufen, so übergibt es den Wert des Parameters an die gleichnamige Variable.

Behandlung von Whitespaces
Neben der normalen Behandlung von Whitespaces durch XML kann diese für den XSL-Parser nochmals konkret festgeschrieben werden. Dies kann durch zwei Elemente geschehen: xsl:strip-space und xsl:preserve-space. Beide Elemente erhalten dazu das Attribut elements, welches als Wert eine durch Leerzeichen getrennte Liste von Elementnamen enthält. Bei allen Elementen, die so mit dem Element xsl:strip-space ausgezeichnet werden, werden die Whitespaces zusammengefasst (wie in XML beschrieben). Bei allen Elementen, die durch xsl:preserve-space definiert werden, bleiben die Whitespaces erhalten. Grundsätzlich brauchen Elemente nicht extra mit xsl:strip-space definiert werden – sollen jedoch bei Elementen, die sich innerhalb eines mit xsl:preserve-space beschriebenen Elements befinden, die Whitespaces gekürzt werden, sollte dies hier definiert werden.

Beispiel:

      <?xml version="1.0"?>

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

<!-- import/include -->
 <xsl:strip-space elements="Adressbuch
Strasse">
 <xsl:preserve-space elements="Person">

<!-- sonstiges -->
 </xsl:stylesheet>

Bitte beachten Sie, dass beide Top-Level Elemente sind und möglichst vor Templates definiert werden sollten. Außerdem kann anstelle einer Liste der Joker (*) definiert werden. Er besagt, dass alle Elemente einbezogen werden.

Darüber hinaus besteht eine dritte Möglichkeit, um Text so übernehmen zu lassen, wie er notiert wurde. Alle Notierungen innerhalb eines xsl:text-Elements werden auch in das resultierende Dokument übernommen (inklusive aller Whitespaces).

Beispiel:

      <xsl:text>
 Dieser Text
 wird genau so

auch im Resultat
 erscheinen!
 </xsl:text>

XSL-Software
Neben dem Mozilla Browser gibt es einige – meist serverseitige – Tools, mit denen Sie XML-Dateien transformieren können. Dazu gehören unter anderem Cocoon, Xalan oder Sun’s JAXP:

Cocoon (XSLT Server Plugin)
Xalan (Java XSLT Parser)
JAXP (JavaTM API for XML Processing)

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.