XSLT-1.0-Lösungen
Kommentare

Text richtig formatieren
Ein häufiger Anwendungsfall von XSLT ist die Generierung von formatierten HTML-Dateien aus einem oder mehreren XML-Dokumenten heraus. Oft wird dabei Text in CDATA-Abschnitten

Text richtig formatieren

Ein häufiger Anwendungsfall von XSLT ist die Generierung von formatierten HTML-Dateien aus einem oder mehreren XML-Dokumenten heraus. Oft wird dabei Text in CDATA-Abschnitten definiert, um die eigentliche Textformatierung (wie Zeilenumbrüche) aufrecht zu erhalten. Kopiert man jedoch den Ausgangstext einfach in das HTML-Dokument, so fallen die ganzen Zeilenumbrüche weg und man erhält eine einzige lange Zeile. Um dies zu umgehen, kann man sich ein einfaches Template basteln, das einen String in einen anderen String mit einem XML-Element ersetzt. Dieses kann man natürlich nicht nur für das Ersetzen eines Zeilenumbruches mit dem
-Tag verwenden, sondern dank Parametrisierung für jede Art von Stringersetzung. Ein rekursives Template, das einen String mit einem Tag ersetzt, zeigt Listing 3.

Listing 3
-----------------------------------------------------------------

Auch dieses Template arbeitet rekursiv. Zunächst wird getestet, ob das gesuchte Wort in unserem Ausgangstext enthalten ist. Ist dies nicht der Fall, wird die Rekursion abgebrochen. Ist das Wort enthalten, wird eine Ersetzung durch das Kopieren des gesamten Textes in Einzelteilen vorgenommen. Da damit immer nur ein Vorkommen des Wortes ersetzt werden kann, ruft sich das Template mit dem neuen Ausgangstext wieder auf und das Spiel beginnt von vorne, so lange, bis das gesuchte Wort nicht mehr gefunden werden kann. Um von einem Text alle Zeilenumbrüche mit dem -Tag zu ersetzen, wird folgender Aufruf benutzt:

 

Der Parameter string enthält dabei den original Text, der ersetzt werden soll. Der Parameter from setzt fest, welche(s) Zeichen ersetzt werden soll, und der to-Parameter enthält das oder die Tags, die anstelle des gesuchten Strings eingesetzt werden sollen.

Zahlen und Formate

Als XSLT-Entwickler steht man oft vor der Aufgabe, Zahlen, Daten oder Strings in einer bestimmten Art und Weise zu formatieren. Als erstes Beispiel dient das Umwandeln von Telefonnummern. Oft erhält man Formate, die auch andere Zeichen als Zahlen enthalten, wie etwa (089) 4645-12. Damit man daraus eine vollständige, zahlenbasierte Telefonnummer generieren kann, genügt folgende Zeile:

(089)4645-12

Hier werden mittels der translate-Funktion alle Zeichen, die keine Zahlen sind, entfernt. Die Funktion erwartet folgende Parameter:

  • Ausgangstext
  • Zeichen, die übersetzt werden sollen
  • Zeichen, mit denen die des zweiten Parameters übersetzt werden sollen

Die translate-Funktion arbeitet nach folgendem Schema. Ist ein Zeichen im zweiten Parameter angegeben, aber wird im dritten Parameter keine Entsprechung dafür gefunden, dann wird dieses Zeichen im Ergebnis einfach weggelassen. In unserem Beispiel würde die Vorgehensweise also wie folgt aussehen:

  • Eingangstext ist (089)4645-12
  • Die erste translate-Funktion filtert alle Zahlen. Da im dritten Parameter keine Entsprechungen für die Zahlen 0–9 angegeben sind, werden diese im Ergebnis einfach weggelassen. Wir erhalten eine Liste mit allen restlichen Zeichen, hier: ()-
  • Nun liegen alle ungültigen Zeichen vor und wir machen uns nochmals die translate-Funktion zunutze. Diesmal übergeben wir allerdings nicht die Zahlen, sondern die soeben herausgefilterten Zeichen. Wir erhalten genau den gegenteiligen Effekt – nur die Ziffern bleiben erhalten: 089464512.

Ein weiteres praktisches Anwendungsbeispiel ist das Formatieren von Zahlen mit führenden Nullen. Als Beispiel dient die Zahl 123, aus der man einen String mit der Länge von sechs Zeichen erzeugen will, wobei führende Nullen verwendet werden. Dafür könnte man die format-number()-Funktion nutzen, aber zum Lernen von XSLT soll hier eine eigene, rekursive Routine dafür gebastelt werden (Listing 4).

Listing 4
--------------------------------------------------------------------
0=$digits">

Es ist erkennbar, dass rekursive Templates äußerst häufig benötigt werden. Diese ähneln im Ablauf dem Schleifen-Beispiel. Die Routine setzt so lange eine Null (bzw. das Zeichen, das im Parameter leading angegeben wird) vor den Ausgangstext, bis die gewünschte Zeichenlänge erreicht wurde. Ist dies der Fall, wird die neu formatierte Zahl einfach ausgegeben und die Routine damit beendet. Der Aufruf für unser Beispiel würde dann so erfolgen:

123
Listen gekonnt aufteilen

Oft kommt es vor, dass man ein XML-Dokument mit mehreren Einträgen hat, die man dann aufteilen möchte. Um dies zu erreichen, muss man zwei geschachtelte for-each-Schleifen verwenden. Ein XML-Dokument mit mehreren hundert Einträgen und der folgenden Struktur ist Beispiel:

John SmithMichael Walker
  ...

Nun soll eine Tabelle mit je 20 Einträgen erstellt werden, in der dann in jeder Zeile der jeweilige Kundenname erscheint. Der entsprechende XSLT-Quellcode dazu sieht wie folgt aus:

<for-each select=".|following-sibling::item[position() 

In diesem Template wird zuerst eine Variable mit der maximalen Anzahl von Einträgen in einer Tabelle definiert. Dann werden mittels einer ersten for-each-Schleife alle Knoten ermittelt, die sich durch die Anzahl der Einträge mit Rest 1 teilen lassen. Dadurch erhalten wir eine Art Gruppierung, da nur die Knoten auf Position 1, 21, 41 usw. selektiert werden. Anschließend wird eine neue Tabelle erstellt und mittels einer zweiten for-each-Schleife durch alle Knoten durchgegangen, die dem aktuellen Knoten folgen, bis die maximale Anzahl der Knoten (20 in unserem Beispiel) erreicht wurde, dann beginnt das Spiel wieder von vorne.

Fazit

XSLT 1.0 bietet umfangreiche Möglichkeiten, XML-Dokumente in andere Formate zu transformieren. Allerdings gibt es vor allem in den Bereichen dynamische Variablen, dynamische Referenzen und der String-/Zeichen- und Datumsverarbeitung erhebliche Mängel. Diese sollen zwar in XSLT 2.0 bereinigt sein. Bis die gängigen XSLT-Prozessoren auch XSLT 2.0 komplett unterstützen, muss man sich wohl oder übel noch mit einigen Tricks bei XSLT 1.0 behelfen, um zu plausiblen Ergebnissen zu kommen. Vor allem muss man sehr oft auf rekursive Funktionen zurückgreifen, um zum Ziel zu gelangen, aber einige Features, wie zum Beispiel dynamische Variablen, funktionieren überhaupt nicht.

Alexander Adam ist einer der Projektleiter des Renesis-Projekts und Geschäftsführer bei Emia Systems. Er arbeitete auch an XStudio, einem SVG Authoring Tool, mit und schrieb das Buch „SVG – Das Praxis-Buch“, erschienen im Franzis-Verlag.
Unsere Redaktion empfiehlt:

Relevante Beiträge

Meinungen zu diesem Beitrag

X
- Gib Deinen Standort ein -
- or -