Attributwerte zur Laufzeit: Attributwert-Templates

In XSLT wird der Begriff »Template« analog zu einem Funktionsblock in einer Programmiersprache gesehen. Sie haben eine Abfolge von Anweisungen vor sich, die in bestimmten Fällen (wenn dieses Template aufgerufen oder ange­sprochen wird) abgearbeitet werden. Das landläufige Verständnis von »Temp­late« im Sinne von »Vorlage«, »Matrize« führt hier auf Abwege.

Im Template-Block enthaltene XSLT-Instruktionen werden bekanntlich interpre­tiert, Literal Result Elements unverändert ins Ergebnisdokument kopiert. In Bezug auf Letztere wäre eine gewisse Flexibilität jedoch manchmal von Vorteil.

Die Attributwerte und woher sie kommen

Auch Attribute können in Zusammenhang mit Literal Result Elements zwar sehr wohl verwendet werden, von vornherein aber ebenfalls im Sinne des Wortes »literal«, d. h., der gewünschte Attributwert muss im Vorfeld bekannt sein, um ihn in das Stylesheet »wörtlich« einzufügen:

<xsl:template match="abschnitt[@typ='wichtig']">
  <p class="wichtig"><xsl:value-of select="."/></p>
</xsl:template>

In dieser Template-Regel werden nur <abschnitt>-Elemente verarbeitet, deren typ-Attribut den Wert "wichtig" hat, und ein entsprechendes class-Attribut für die Zuweisung eines CSS-Styles gesetzt. Problem: Für jede Klasse würde ein eigenes Template benötigt.

XPath-Ausdrücke als Attributwerte

Aufgabe des XSLT-Parsers ist es, XPath-Ausdrücke auszuwerten und gemäß der Auswertung zu handeln. Das kann darin bestehen, den Ergebnisstring des Ausdrucks einzufügen oder eine Sequenz zusammenzustellen, die durch den Ausdruck beschrieben wurde. Leider wertet der Parser XPath-Ausdrücke von sich aus nur dort aus, wo er sie erwartet, nämlich in den entsprechenden Attri­buten der XSLT-Elemente.

Für die Attribute von Literal Result Elements (und für manche XSLT-Instruktio­nen) ist es jedoch oft erforderlich, dass der Wert eines eingefügten Attributs zur Laufzeit des Templates aus dem Verarbeitungskontext bestimmt werden kann. Manchmal ist es weder möglich, den Wert vorherzubestimmen, noch statische Varianten aller denkbaren Konfigurationen einzubeziehen.

Das zur Lösung dieses Problems dienende Konzept bezeichnet man als Attri­butwert-Template (attribute value template, AVT).

Das Attributwert-Template

Soll der XSLT-Prozessor veranlasst werden, einen XPath-Ausdruck innerhalb eines Attributwerts eines Literal Result Elements als solchen zu erkennen und auszuwerten, so muss ihm dies durch entsprechende Steuerzeichen angezeigt werden. Diesem Zweck dienen die geschweiften Klammern { und }.

<elementname attributname="{expression}">

Da ein Attributwert stets ein Stringwert sein muss, wird ein XPath-Ausdruck innerhalb eines AVT auch immer als String interpretiert beziehungsweise durch Typkonvertierung in einen String umgewandelt, falls der Aus­druck von sich aus keinen String ergibt.

Die Lösung für das oben beschriebene Problem ist jetzt einfach:

<xsl:template match="abschnitt">
  <p class="{@typ}"><xsl:value-of select="."/></p>
</xsl:template>

Die Nodesequenz muss somit nicht im Vorfeld gefiltert und auf eine Reihe sta­tischer Templates verteilt werden, sondern es wird mittels eines Attributwert-Templates der Stringwert des typ-Attributs des aktuellen Knotens extrahiert, und als Wert des class-Attributs in das Ergebnis geschrieben.

Eingebettete XPath-Ausdrücke

Es ist auch möglich, den XPath-Ausdruck in vorgegebene String-Abschnitte ein­zubetten oder mehrere XPath-Ausdrücke zur Generierung eines Attributwerts zu verwenden. Wichtig ist nur die Kennzeichnung der auszuwertenden Teilaus­drücke durch geschweifte Klammern:

<elementname attributname="{exp1}literal{exp2}">

Analog könnte die position()-Funktion benutzt werden, um in der HTML-Ausgabe etwas Ähnliches wie einen Identifier zu erzeugen:

<xsl:template match="abschnitt">
  <p id="teil{fn:position()}"><xsl:value-of select ="."/></p>
</xsl:template>

Das Ergebnis wäre beispielsweise Folgendes:

<p id="teil3">Der Inhalt des dritten Abschnitts</p>

Attributwerte weitergeben

Oft soll der Wert eines Attributs des Quelldokuments an ein korrespondieren­des (nicht unbedingt gleichnamiges) Attribut des Ergebnisdokuments weiter­­gegeben werden. Soll in einem HTML-Ergebnisdokument ein Bild eingefügt werden, dessen im XML-Dokument vorliegende Abmessungen weitergereicht werden sollen, so kann dies so aussehen:

<bild quelle="katze.gif" breite="200" hoehe="120"/>

soll ergeben:

<img src="katze.gif" width="200" height="120"/>

Dann können wir folgendes Template verwenden:

<xsl:template match="bild">
  <img src="{@quelle}" width="{@breite}" height="{@hoehe}"/>
</xsl:template>

Elementinhalte des Current Node in Attributwerte umwandeln

Zusätzlich kann es erforderlich sein, den Inhalt eines Elements des Quelldoku­ments in einen Attributwert des Ergebnisdokuments umzuwandeln. Angenom­men das <bild> sei kein leeres Element, sondern enthielte eine Beschreibung, die in ein alt-Attribut umgewandelt werden soll. So soll beispielsweise:

<bild quelle="katze.gif" breite="200" hoehe="120">Ein Bild meiner Katze</bild>

Folgendes ergeben:

<img src="katze.gif" width="200" height="120" alt="Ein Bild meiner Katze"/>

Hierfür muss das Template nur folgendermaßen erweitert werden:

<xsl:template match="bild">
  <img src="{@quelle}" width="{@breite}" height="{@hoehe}"alt="{.}"/>
</xsl:template>

wobei mit "{.}" der Stringwert des Elements extrahiert wird (dies ist sicherer, falls hier Child-Elemente vorliegen sollten).

Inhalte von Child-Elementen in Attributwerte kopieren

Wenn die in Attributwerte zu kopierenden Informationen nicht in Attributen des aktuellen Knotens, sondern als Inhalte von dessen Child-Elementen vorlie­gen, so können ebenfalls Attributwert-Templates eingesetzt werden. Die Angabe:

<bild>
  <quelle>katze.gif</quelle>
  <breite>200</breite>
  <hoehe>120</hoehe>
</bild>

überführt man in die oben bereits gezeigte Struktur mittels:

<xsl:template match="bild">
  <img src="{quelle}" width="{breite}" height="{hoehe}"/>
</xsl:template>

Der Witz dabei ist, dass ein Attributwert-Template stets den Stringwert des XPath-Ausdrucks – hier ist es ein NameTest für Child-Elemente, der nur aus den Elementnamen besteht – ausgibt. Es ist nicht erforderlich, sich Gedanken über die potenzielle innere Struktur unserer »Datenquellen« zu machen.

Maskierung der geschweiften Klammer

Man trifft auf ein ähnliches Problem, wie bei der Verwendung von <, > oder &, wenn die geschweifte Klammer – aus welchen Gründen auch immer – als »lite­rales« Zeichen innerhalb eines Attributs verwenden werden soll.

Da die Klammer in diesem Kontext ein Steuerzeichen darstellt, muss sie mas­kiert werden. Dies geschieht durch Voranstellen einer zweiten (gleichgerichte­ten) geschweiften Klammer: Für { wird daher die Folge {{ verwendet.

<tag att="Dies ist {{kein}} Template">

entspricht dem gewünschten Inhalt:

<tag att="Dies ist {kein} Template">

Hinweis:
Das Problem besteht gleichermaßen für jene Attribute, die keine Attribut-Templates zulassen, da der Parser die geschweiften Klammern als den Versuch dazu interpretiert, und eben genau mit dieser abschlägigen Meldung reagiert. Auch in diesem Fall muss daher maskiert werden. Ein Ersetzen der Klammer durch ein Character Entity &#123; oder &#125; führt ebenfalls nicht zum Erfolg, da der vorangeschaltete XML-Parser das Entity zum hier unerwünschten Steuerzeichen expandiert, bevor der XSLT-Prozes­sor seine Arbeit aufnimmt.

Wo können Attributwert-Templates verwendet werden?

Leider können AVTs nicht überall im Stylesheet beliebig verwendet werden. Grundsätzlich sind sie allerdings für alle Attribute von Literal Result Elements einsetzbar, sofern die betreffenden Attribute sich nicht im xml- oder xsl-Namensraum befinden (wie beispielsweise xml:lang, xsl:xpath-default-namespace und weitere).

Ebenfalls eingeschränkt ist die Verwendung im Rahmen der XSLT-Instruk­­tionen selbst. Hier sind Attributwert-Templates nur für bestimmte, genau fest­gelegte Attribute gestattet.

Hier eine Übersicht über die Einsatzmöglichkeiten von Attribut-Templates:

XSLT-InstruktionAVT erlaubt für Attribute
xsl:analyze-stringregex, flags
xsl:attributename, namespace, separator
xsl:elementname, namespace
xsl:for-each-groupcollation
xsl:messageterminate
xsl:namespacename
xsl:numberformat, lang, letter-value, ordinal, grouping-separator, grouping-size
xsl:processing-instructionname
xsl:result-documentformat, href, validation, method, byte-order-mark, cdata-section-elements, doctype-public, doctype-system, encoding, escape-uri-attributes, include-content-type, indent, media-type, normalization-form, omit-xml-declaration, standalone, undeclare-prefixes, output-version
xsl:sortlang, data-type, order, case-order, collation, stable
xsl:value-ofseparator

Tabelle: In XSLT 2.0-Instruktionen erlaubte Attributwert-Templates.

Grundsätzlich können Attributwert-Templates außerdem für alle Attribute von Literal Result Elements eingesetzt werden. In XSLT-Instruktionen ist die Verwendung auf die oben genannten Attribute beschränkt.

Achtung – Änderungen gegenüber XSLT 1.0
In Einzelfällen ist in XSLT 2.0 die Verwendung von AVTs nun für Attribute erlaubt, für die dies unter XSLT 1.0 noch verboten war, wie etwa beim terminate-Attribut von xsl:message. Auch das für einige Instruktionen neu hinzugekommene collation-Attribut ist, mit Ausnahme von dem bei xsl:key, stets als AVT interpretierbar.

Weshalb die Einschränkung bei der Verwendbarkeit?

Warum geht es nicht überall? Hintergedanke ist, dass in kritischen Fällen die Abarbeitung des Stylesheets nicht dadurch gefährdet werden darf, dass ein Attributwert einer Instruktion (noch) nicht bekannt ist. Daher sind Attribut­wert-Templates bei allen XSLT-Toplevel-Elementen nicht gestattet! So ist das collation-Attribut von xsl:key im Gegensatz zu seinem sonstigen Auftreten bei anderen Instruktionen kein AVT.

Ein Abweichen von dieser Regel würde bedeuten, die Auffindung statischer Fehler möglicherweise in die Laufzeit des Stylesheets zu verlagern, was Pro­bleme nach sich zöge. Die Abarbeitung eines Stylesheets erfolgt streng nach der Reihe. Das heißt, der Prozessor kann nicht »zurückgehen«, wenn ein benötigter Wert sich »später« ergibt – er bricht vorher mit einem Fehler ab. Diese Einschrän­kung gilt in vergleichbarer Form bei der Verwendung von Parametern und Vari­ablen in XSLT.

   

<< zurück vor >>
Tipp der data2type-Redaktion:
Zum Thema XSLT bieten wir auch folgende Schulungen zur Vertiefung und professionellen Fortbildung an:

Copyright © Galileo Press, Bonn 2008
Für Ihren privaten Gebrauch dürfen Sie die Online-Version ausdrucken.
Ansonsten unterliegt dieses Kapitel aus dem Buch "XSLT 2.0 & XPath 2.0 ― Das umfassende Handbuch" denselben Bestimmungen wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


Galileo Press, Rheinwerkallee 4, 53227 Bonn