XSLT - Erzeugen des Ergebnisdokuments


... [Seminar XML und Java] ... [Thema: XSLT] ... [Zusätzliche Funktionen] ...


Übersicht: XSLT - Erzeugen des Ergebnisdokuments


Text aus dem Quelldokument

<!-- Category: instruction -->
<xsl:value-of
  select = string-expression
  disable-output-escaping = "yes" | "no" />

Mit xsl:value-of kann man Text aus dem Quelldokument in das Ergebnisdokument schreiben. Im select-Attribut wird ein XPath-Ausdruck angegeben, dessen Ergebnis zu einem String konvertiert wird.

Hat das Attribut disable-output-escaping den Wert yes, so werden keine Zeichendaten ausmaskiert. Zeichen wir <, > oder & bleiben erhalten und werden nicht mit &lt;, &gt; oder &amp; ausmaskiert. Die Voreinstellung ist no.

Bei xsl:value-of ändert sich der Current Node des XSLT Kontextes nicht.


Textelemente

<!-- Category: instruction -->
<xsl:text
  disable-output-escaping = "yes" | "no">
  <!-- Content: #PCDATA -->
</xsl:text>

Mit xsl:text werden Textelemente erzeugt. Im Unterschied zu reinen Textelementen des Stylesheets wird Leerraum unterhalb von xsl:text nicht dem Whitespace-Stripping unterworfen.


Elemente

<!-- Category: instruction -->
<xsl:element
  name = { qname }
  namespace = { uri-reference }
  use-attribute-sets = qnames>
  <!-- Content: template -->
</xsl:element>

Es wird ein Element erzeugt, das den Qualified Name name erhält. Der erzeugte Knoten erhält einen Namespace Node mit dem URI des Attributes namespace, wenn dieses angegeben ist. Der Expanded Name des erzeugten Elements wird aus diesem Namespace-URI und dem Qualified Name gebildet.

Innerhalb des erzeugten Elements wird der unter xsl:element sich befindende Teilbaum instanziiert.

Mit use-attribute-sets kann ein benannter Satz von Attributen angegeben werden, der direkt mit dem Element instanziiert wird. Das hat die gleiche Wirkung, als wenn für jedes Attribut innerhalb des benannten Attributsatzes xsl:attribute aufgerufen wird.


Attribute

<!-- Category: instruction -->
<xsl:attribute
  name = { qname }
  namespace = { uri-reference }>
  <!-- Content: template -->
</xsl:attribute>

Mit xsl:attribute könne Attribute erzeugt werden. Dabei wird der Inhalt von xsl:attribute instanziiert und bildet dann den Wert des erzeugten Attributs, das Ergebnis des Templates muss ein gültiger Attributwert sein.

xsl:attribute kann nur direkt nach dem Erzeugen des Elements, also entweder einem Literal Result Element oder dem xsl:element-Ausdruck, eingesetzt werden.


Kommentare

<!-- Category: instruction -->
<xsl:comment>
  <!-- Content: template -->
</xsl:comment>

Der Inhalt des xsl:comment-Elements wird instanziiert und ergibt den Inhalt des Kommentars, es dürfen nur Zeichendaten entstehen, die in Kommentaren erlaubt sind.


Processing Instructions

<!-- Category: instruction -->
<xsl:processing-instruction
  name = { ncname }>
  <!-- Content: template -->
</xsl:processing-instruction>

Das Attribut name ergibt das Taget der Processing Instruction und wird als Attribue Value Template interpretiert. Der Inhalt von xsl:processing-instruction wird instanziiert und ergibt den Wert der Processing Instruction. Dabei dürfen nur Textelement entstehen, die Zeichenfolge ?> ist nicht erlaubt.


Schleifen

<!-- Category: instruction -->
<xsl:for-each
  select = node-set-expression>
  <!-- Content: (xsl:sort*, template) -->
</xsl:for-each>

Der Ausdruck im Attribut select bestimmt die Elemente des Quelledokuments, über die man die Schleife bilden will. Anschließend wird der Teilbaum unterhalb des xsl:for-each-Elements für jedes Element in diesem Node Set instanziiert. Man muss bei Schleifen darauf achten, dass sich der Current Node des XSLT-Kontextes dauernd innerhalb der Schleife ändert.

Über xsl:sort hat man die Möglichkeit, die Elemente der Current Node List vor ihrer Verarbeitung zu sortieren. Macht man dies nicht, werden sie in der Reihenfolge abgearbeitet, in der sie selektiert wurden.

Beispiel:

<xsl:for-each select="images/image">
  <tr><td><img src="{org}"/></td></tr>
</xsl:for-each>

Diese Schleife zählt alle image-Elemente unterhalb des images-Element ausgehend vom Current Node auf.


Bedingungen

<!-- Category: instruction -->
<xsl:if
  test =boolean-expression>
  <!-- Content:template -->
</xsl:if>

<!-- Category: instruction -->
<xsl:choose>
  <!-- Content: (xsl:when+, xsl:otherwise?) -->
</xsl:choose>

<xsl:when
  test = boolean-expression>
  <!-- Content: template -->
</xsl:when>

<xsl:otherwise>
  <!--Content: template -->
</xsl:otherwise>

Es gibt zwei Arten von Bedingungen:

  1. xsl:if für den bedingten Einschluss eines Templates ohne alternative Verzweigung
  2. xsl:choose für eine Fallunterscheidung zwischen mehreren Alternativen

Bei xsl:if wird im Attribut test ein XPath-Ausdruck angegeben, dessen Ergebnis in einen booleschen Wert konvertiert wird. Ist der Wert true, wird das Tempate unterhalb von xsl:if instanziiert, sonst nicht.

Ähnlich funktioniert xsl:choose. Die xsl:when-Konstrukte werden nacheinander ausgewertet. Bei der ersten Bedingung, die true ergibt - und nur bei dieser - wird das eingeschlossene Template instanziiert. Sollte keine passende Bedingung vorhanden sein, wird - sofern vorhanden - das Template des xsl:otherwise-Konstrukts instanziiert.

Beispiel:

<xsl:choose>
  <xsl:when test="stadt='HH'">Hamburg</xsl:when>
  <xsl:when test="stadt='HB'">Bremen</xsl:when>
  <xsl:when test="stadt='M'">München</xsl:when>
  [........]
  <xsl:otherwise><xsl:value-of select="stadt"/></xsl:otherwise>
</xsl:choose>

Dieses Beispiel gibt den Namen einer Stadt ausgehend vom Autokennzeichen aus. Gehört das Autokennzeichen zu keiner Stadt, wird es selbst ausgegeben.


Sortieren

<xsl:sort
  select = string-expression
  lang = { nmtoken }
  data-type = { "text" | "number" | qname-but-not-ncname }
  order = { "ascending" | "descending" }
  case-order = { "upper-first" | "lower-first" } />

Im select-Attibut wird ein Ausdruck angegeben, dessen Ergebnis bei der Sortierung in einen Stringwert umgewandelt wird. Dieser Stringwert wird dann auch zur Sortierung verwendet.

Hier eine kurze Erläuterung der weiteren Attribute:

Beispiel:

<xsl:apply-templates select="book">
  <xsl:sort select="@isbn"/>
</xsl:apply-templates>

Zur Verarbeitung aller book-Elemente, nach der ISBN-Nummer sortiert.


Nummerierung

XSLT berücksichtigt in der Transformation bereits die Möglichkeit von Nummerierungen.

<!-- Category: instruction -->
<xsl:number
  level = "single" | "multiple" | "any"
  count = pattern
  from = pattern
  value = number-expression
  format = { string }
  lang = { nmtoken }
  letter-value = { "alphabetic" | "traditional" }
  grouping-separator = { char }
  grouping-size = { number } />

Als Ergebnis von xsl:number wird im Ergebnisdokument ein Stringwert erzeugt.

Es gibt zwei Möglichkeiten, die Nummerierung zu bestimmen. Über das Attribut value kann ein Ausdruck angegeben werden, dessen Ergebnis in eine Zahl konvertiert wird.

Beispiel:

<xsl:for-each select="urheber">
  <xsl:number value="position()" format="1. " />
  <xsl:apply-templates select="." />
</xsl:for-each>

Wird value weggelassen, wird die Position des Current Nodes im Quelldokument berechnet. Dabei beeinflussen die Attribute level, count und from diese Berechnung.

level="single" dient zum einfachen Durchzählen einer Liste von Elementen auf einer Ebene, ohne Hierarchiestufen zu berücksichtigen. Der Prozessor geht in diesem Fall bis zum ersten Knoten der ancestor-or-self-Achse, der zum count-Pattern passt. Jetzt werden die preceding-sibling-Knoten des gefundenen Vorfahrens gezählt, die zum count-Pattern passen. Die Anzahl plus eins wird in eine Liste der Länge eins eingetragen. Wenn kein Knoten gefunden wurde, wird eine leere Liste erzeugt. Falls das from-Attribut spezifiziert ist, werden nur die Vorfahren gezählt, die als Nachfolger zum nächsten Vorfahren auftreten, der auf das Pattern in from passt.

Beispiel:

<xsl:template match="ol/item">
  <xsl:number level="single" count="item"/>. <xsl:apply-templates/>
</xsl:template>

Dieses Beispiel nummeriert die Items (item) einer Ordered List (ol) durch.

level="multiply" dient zum Nummerieren hierarchischer Abschnitte wie Kapitel, Abschnitt und Unterabschnitt. In diesem Fall wird erstmal ein Node Set der ancestor-or-self-Achse in umgekehrter Reihenfolge aufgebaut.

Aus diesem Node Set wird werden die Knoten selektiert, die zum count-Pattern passen. Für diese Knoten wird jetzt eine Zahl erzeugt, die die Anzahl der Elemente auf der preceding-sibling-Achse des Knotens enthält, die zum count-Pattern passen. from begrenzt die Suche nach Vorfahren nach oben.

level="any" ist zum einfachen Nummerieren von Elementen ohne Rücksicht auf die Hierarchie gedacht. Auch hier wird eine Liste der Länge eins erstellt, die die Anzahl der Knoten des vereinigten  Node Sets der ancestor-or-self- und der preceding-Achse enthält. Gezählt werden nur die Knoten, die zum count-Pattern passen. Das from-Attribut begrenzt den Zählbereich, diesmal noch oben und nach vorne.

Die Formatierung der Nummer

Wenn die "Zählliste" bestimmt ist, ist der nächste Schritt die Formatierung in einen String. Dies wird hauptsächlich durch das Attribut format bestimmt.

Besteht die Zählliste aus mehreren Zahlen, kommen folgende Reglen zur Anwendung:

Die Attribute grouping-seperator und grouping-size können zur Teilung des Ausgabestrings in Blöcke benutzt werden. Ist z.B. grouping-seperator=" " und grouping-size="2", dann würde die Zählliste "12345" als "1 23 45" ausgegeben werden (Gruppen werden immer von rechts gezählt):

Das Attribut lang spezifiziert die Ziel-Sprache und orientiert sich wieder an xml:lang. letter-value ist für Fälle, in denen es zwei Möglichkeiten des Sequenzbildung gibt. Über alphabetic oder traditionell kann dann die Sequenzbildung gesteuert werden.


Kopieren von Elementen

<!-- Category: instruction -->
<xsl:copy
  use-attribute-sets = qnames>
  <!-- Content: template -->
</xsl:copy>

Mit dem xsl:copy-Konstrukt wird der Current Node einfach als Element im Ergebnisdokument erzeugt. Hierbei werden auch alle Namespace Nodes erzeugt, aber keine Attribute oder Kindelemente. Der Inhalt des Elements wird im Ergebnisdokument instanziiert, erst dieser Inhalt liefert die Attribute (z.B. über xsl:attribute) sowie den (neuen) Inhalt des Elements im Zieldokument.

Das Template in xsl:copy wird allerdings nur für Root Nodes und Element Nodes instanziiert.


Kopieren von Teilbäumen

<!-- Category: instruction -->
<xsl:copy-of
  select = expression />

Mittels xsl:copy-of kann man Teilbäume in das Ergebnisdokument kopieren.

Das Attribut select ist ein Ausdruck, der einen String, eine Zahl, einen boolschen Wert, ein Node Set oder ein Result Tree Fragment zurückliefert.


... [Seminar XML und Java] ... [Thema: XSLT] ... [Aufbau eines Stylesheets] ... [Zusätzliche Funktionen]