XSLT - Template Rules


... [Seminar XML und Java] ... [Thema: XSLT] ... [Anwenden von Templates] ...


Übersicht: XSLT - Template Rules


Hinweis

Man muss die zwei Begriffe Template und Template Rule unterscheiden. Eine Template Rule definiert Regeln für den Transformationsprozess und enthält immer ein Template. Das Template ist ein Stück Stylesheet, das im Ergebnisdokument instanziiert wird. Im folgenden Beispiel ist das gesamte Konstrukt eine Template Rule, der hervorgehoben dargestellte Teil ist das Template.

<xsl:template match="ims-object">;
  <h1><xsl:apply-templates select="eb_nummer /></h1>;
  <h2><xsl:apply-templates select="bezeichnung /></h2>;
  <div class="beschreibung"><xsl:apply-templates select="text /></div>
;
</xsl:template>


xsl:template

Template Rules werden mit dem Element xsl:template definiert:

<!-- Category: top-level-element -->
<xsl:template
  match = pattern
  name = qname
  priority = number
  mode = qname>
  <!-- Content: (xsl:param*, template) -->
</xsl:template>

Eine Template Rule wird zur Formulierung eines Transformationsprozesses für eine Menge von Knotentypen im Quelldokument verwendet. Über die verschiedenen Attribute kann die Instanziierung beeinflusst werden. Außerdem ist es möglich, innerhalb des Templates Parameter zu deklarieren. Der Prozess des Traversierens kann mit xsl:apply-templates oder xsl:for-each explizit gesteuert werden.

Beispiel:

<xsl:template match="SPIELORT" >
  [...]

</xsl:template>

Diese Template Rule passt auf ein Element "SPIELORT" im Quelldokument.


Patterns

Ein Pattern beschreibt eine Regel, nach der eine Template Rule für einen Knoten ausgewählt wird. Ein Knoten passt ("match") dann zu einem Pattern, wenn er zu dem Node Set gehört, das sich durch die Anwendung des Pattern mit dem zu testenden Knoten selbst oder einem seiner Vorfahren als Context Node ergibt.

Das Matchen könnte also z.B. folgendermaßen ablaufen: der zu prüfende Knoten wird als Context Node gesetzt und der Pattern in diesem Kontext ausgewertet. Ist der zu testende Knoten nicht im resultierenden Node Set enthalten, wird als nächster Context Node der Elternknoten des zu testenden Knotens benutzt. Dieser Vorgang wiederholt sich so lange, bis kein Vorfahre mehr übrig ist oder der zu testende Knoten im Node Set erscheint. Im ersten Fall passt der Knoten eben nicht auf den Pattern.

Beispiele:

/ Wurzelelement
* jedes Element
@* jedes Attribut
absatz jedes Element absatz
absatz | einschub jedes Element absatz oder einschub
kuenstler/name jedes Element name als Kind von kuenstler
buch//absatz jedes Element absatz unterhalb von buch
text() Textelemente
absatz[1] jedes Element absatz, das das erste Kind seines übergeordneten Elements ist
*[position()=1 and self::absatz] dito
list-el[position() mod 2 = 1] trifft jedes ungerade Element list-el
kapitel[@class="anhang"]//absatz jedes Element absatz mit einem Vorfahren kapitel, dessen Attributwert für class 'anhang' ist.


Modi und Namen

Modi

Über das mode-Attribut kann ein Element des Quelldokuments auf unterschiedliche Weise transformiert werden. Das ermöglicht die Definition unterschiedlicher Template Rules für ein und dasselbe Pattern. Wird beim Ausführen von Templates kein mode spezifiziert, wird eine Template Rule ohne mode-Attribut gesucht und ausgeführt.

Beispiel:

<xsl:template match="images" mode="einfach" >
  <!-- Transformiere ein images-Element in einfacher Form -->
</xsl:template>

<xsl:template match="images" mode="genaue" >
  <!-- Transformiere ein images-Element in genauer Form -->
</xsl:template>

Namen

name benennt die Template Rule. Mittels xsl:call-template kann eine Template Rule dann explizit zur Ausführung gebracht werden. So können Template Rules definiert werden, die unabhängig vom Knoten des Quelldokuments Sinn machen. Dies könnte eine Art "Baustein" sein, der unabhängig vom aktuellen Kontext beliebig häufig benutzt werden kann.

Beispiel:

<xsl:template name="tabellenkopf">
  <!-- Baustein für einen Tabellenkopf -->
</xsl:template>


Prioritäten

Manchmal kommt es vor, dass es für einen zu testenden Knoten mehr als eine passende Template Rule gibt. Möglich wäre dies zum Beispiel durch den Import von Stylesheets oder auch einfach durch unterschiedliche Template Rules, die durch ihr Pattern für einen und denselben Knoten in Frage kommen.

Die Auflösung solcher Konflikte läuft in drei Schritten ab. Zuerst einmal wird eine Liste aller in Frage kommenden Template Rules gebildet. Von diesen werden dann nur die weiter betrachtet, die die höchste Importpräzedenz haben.

Diese werden anschließend nach Ihrer Priorität bewertet. Die Priorität wird über das entsprechende Attribut der Template Rules gesteuert. Gibt es hier immer noch Alternativen, wird dies als Fehler behandelt.

Fehlt allerdings das entsprechende Attribut, wird eine Standardpriorität aus dem Pattern der Template Rule berechnet. Diese ergibt sich wie folgt:

  1. Ist das Pattern eine Kombination von Pattern mittels des Pipe-Symbols wird die Summe der einzelnen Alternativen betrachtet.
  2. Die Priorität ist 0, wenn das Pattern aus einem Qualified Name oder dem Node Type processing-instruction() nach einem child::- oder attribute::-Axis Specifier besteht, z.B. absatz, @href oder child::processing-instruction(presentation-manager).
  3. Die Priorität ist -0,25, wenn das Pattern aus dem Nametest NCName:* nach einem child::- oder attribute::-Axis Specifier besteht, z.B. child::ims:*.
  4. Andernfalls ist die Priorität -0,5, wenn das Pattern lediglich aus einem Node Test (text(), comment(), node()) nach einem child::- oder attribute::-Axis Specifier besteht, z.B. child::text().
  5. Wenn das alles nicht zu trifft, ist die Priorität 0,5.

Mit diesen Regeln wird die Wichtigkeit der Template Rules nach ihrer Spezialisierung gestaffelt. Der am häufigsten auftretende Fall, der Test auf einen bestimmten Namen, wird mit der Priorität 0 bewertet. Weniger spezifische Patterns erhalten eine kleinere Priorität. Was dann übrig bleibt, ist auf jeden Fall spezieller als der allgemeine Fall.

Beispiel:

<xsl:template match="text">
  <!-- Tu was mit text -->
</xsl:template>

<xsl:template match="image/text">
  <!-- Tu was anderes mit text -->
</xsl:template>

Wird jetzt irgendwo <xsl:apply-templates select="text" /> aufgerufen, sind in dem Fall, dass das Element text unterhalb eines image-Elements steht, beide Templates Kandidaten für die Ausführung. Jetzt greift die Priorisierung: Das erste Template hat die Priorität 0, das zweite bekommt, da es einen spezielleren Fall behandelt, die Priorität 0,5 und wird somit instanziiert.


Literal Result Elements

Literal Result Elements sind all die Elemente, die nicht zum Namensraum von XSLT und nicht zu den Extension Namespaces gehören. Für ein Literal Result Element wird im Ergebnisdokument ein Element erzeugt, das den gleichen Expanded Name wie im Stylesheet erhält. Außerdem bekommt es eine Kopie aller Attribute, die es im Stylesheet besitzt. Auch die Namespace Nodes des Elements werden kopiert, wenn:

  1. der Namespace-URI nicht zu der extension-element-prefixes-Liste gehört
  2. der Namespace-URI nicht zum XSLT-Namespace gehört
  3. der Namespace-URI nicht zu der exclude-result-prefixes-Liste gehört.

Beispiel:

<xsl:template match="ims-object">
  <html>
    <head>
       <title><xsl:apply-templates select="eb_nummer"/></title>
    </head>
    <body>
      <h1>Objekt: <xsl:apply-templates select="bezeichnung"/></h1>
    </body>
  </html>
</xsl:template>

Die hervorgehobenen Elemente sind Literal Result Elements. Das Ergebnis könnte dann so aussehen, wobei der Wert für eb_nummer mit 1999/05/0001, der Wert des Elements bezeichnung mit Kartenspiel angenommen wird:

<html>
  <head>
     <title>1999/05/0001</title>
   </head>
  <body>
    <h1>Objekt: Kartenspiel</h1>
  </body>
</html>


Parameter in Templates

Templates können mit Parametern versehen werden. Diese können mit Vorgabewerten (select="left" im Beispiel) versehen werden, die dann zum Einsatz kommen, wenn ein Parameter nicht spezifiziert wurde. Zum Einsatz kommt hier das xsl:param-Konstrukt, das später noch genauer erklärt wird.

Beispiel:

<xsl:template match="image">
  <xsl:param name="align" select="left"/>
  <img src="org" align="{$align}"/>
</xsl:template>


... [Seminar XML und Java] ... [Thema: XSLT] ... [Template Rules] ... [Anwenden von Templates] ...