Formatierung von Text und Zahlen

(Auszug aus "Java und XSLT" von Eric M. Burke)

XSLT und XPath definieren einen kleinen Satz von Funktionen zur Manipulation von Text und Zahlen. Diese erlauben Ihnen, Strings zu konkatenieren, Substrings zu extrahieren, die Länge eines Strings zu ermitteln und ähnliche Aufgaben zu bewerkstelligen. Während diese Funktionen nicht die von einer Programmiersprache wie Java gebotenen Fähigkeiten erreichen, ermöglichen sie doch einige der gebräuchlichsten Textmanipulationsfunktionen.

Formatieren von Zahlen

Die format-number( )-Funktion wird von XSLT bereitgestellt, um Zahlen wie 123 in formatierte Zahlen wie EUR 123,00 umzuwandeln. Die Funktion sieht wie folgt aus:

string format-number(zahlenwert, string, string?)

Der erste Parameter ist die zu formatierende Zahl, der zweite Parameter ist ein Format-String und der dritte, optionale Parameter, ist der Name eines <xsl:decimal-format>-Elements. Wir werden in diesem Buch nur die ersten beiden Parameter ansprechen. Interessanterweise wird das Verhalten der format-number( )-Funktion von der JDK 1.1.x-Version der Klasse java.text.DecimalFormat definiert. Für vollständige Informationen zur Syntax des zweiten Arguments schauen Sie in die Dokumentation des JDK 1.1.x.

Die Ausgabe von Währungen ist eine gängige Verwendung der format-number( )-Funktion. Das Muster EUR #,##0.00 kann eine Zahl beispielsweise in Euro-Währungsschreibweise formatieren. Die folgende Tabelle zeigt verschiedene mögliche Ein- und Ausgabewerte für dieses Muster.

Tabelle: Formatierung von Währungen mit EUR #,##0.00

Zahl Ergebnis
0 EUR 0,00
0,9 EUR 0,90
0,919 EUR 0,92
10 EUR 10,00
1000 EUR 1.000,00
12345,12345 EUR 12.345,12

Der XSLT-Code zur Verwendung dieser Funktion könnte so oder so ähnlich aussehen:

<xsl:value-of select="format-number(betrag,'EUR #,##0.00')"/>

Es wird angenommen, daß betrag ein Element in den XML-Daten (Anmerkung: die XSLT-Spezifikation definiert nicht, was geschehen soll, wenn die XML-Daten keine gültige Zahl enthalten) ist, wie beispielsweise <betrag>1000</betrag>. Die Zeichen # und 0 sind Platzhalter für Ziffern und verhalten sich exakt so, wie es java.text.DecimalFormat festlegt. Im Prinzip ist 0 ein Platzhalter für jede beliebige Ziffer, während # ein Platzhalter ist, der wegfällt, wenn der Eingabewert 0 ist.

Neben Währungen sind Prozentangaben ein gebräuchliches Format. Um eine Prozentangabe auszugeben, muß das Formatmuster mit einem %-Zeichen enden. Der folgende XSLT-Code zeigt ein paar Beispiele:

<!-- gibt 0% aus -->
<xsl:value-of select="format-number(0,'0%')"/>

<!-- gibt 10% aus -->
<xsl:value-of select="format-number(0.1,'0%')"/>

<!-- gibt 100% aus -->
<xsl:value-of select="format-number(1,'0%')"/>

Wie zuvor ist der erste Parameter der format-number( )-Funktion die zu formatierende Zahl und der zweite Parameter ist das Muster. Die 0 im Muster gibt an, daß wenigstens eine Ziffer immer angezeigt werden soll. Das %-Zeichen hat den Nebeneffekt, daß der Wert mit 100 multipliziert wird, damit er als Prozentsatz dargestellt wird. Als Konsequenz wird 0.15 als 15% und 1 als 100% dargestellt.

Um mehr Muster zu testen, können die XML-Daten im folgenden Beispiel verwendet werden. Das funktioniert in Verbindung mit zahlenFormatierung.xslt, um jede Kombination von Zahlen und Format in den XML-Daten anzuzeigen.

Beispiel: zahlenFormatierung.xml

<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" href="zahlenFormatierung.xslt"?>
<zahlenFormatierung>
   <formatBeispiele>
      <!-- fügen Sie mehr <format>-Elemente hinzu, um andere Kombinationen zu testen-->
      <format>EUR #,##0.00</format>
      <format>#.#</format>
      <format>0.#</format>
      <format>0.0</format>
      <format>0%</format>
      <format>0.0#</format>
   </formatBeispiele>
   <zahlenBeispiele>
      <!-- fügen Sie mehr <format>-Elemente hinzu, um andere Kombinationen zu testen-->
      <zahl>-10</zahl>
      <zahl>-1</zahl>
      <zahl>0</zahl>
      <zahl>0,000123</zahl>
      <zahl>0,1</zahl>
      <zahl>0,9</zahl>
      <zahl>0,91</zahl>
      <zahl>0,919</zahl>
      <zahl>1</zahl>
      <zahl>10</zahl>
      <zahl>100</zahl>
      <zahl>1000</zahl>
      <zahl>10000</zahl>
      <zahl>12345,12345</zahl>
      <zahl>55555,55555</zahl>
   </zahlenBeispiele>
</zahlenFormatierung>

Das Stylesheet, zahlenFormatierung.xslt, wird im folgenden Beispiel gezeigt. Kommentare im Code erläutern, was bei jedem Schritt geschieht. Um neue Muster zu testen, bearbeiten Sie einfach die XML-Daten, und führen Sie die Transformation erneut durch. Da die XML-Datei das Stylesheet mit <?xml-stylesheet?> referenziert, können Sie das XML einfach in einen XSLT-fähigen Webbrowser laden und den Aktualisieren-Knopf drücken, um die Änderungen nachzuvollziehen.

Beispiel: zahlenFormatierung.xslt

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="html"/>
   <xsl:template match="/">
      <html>
         <body>
            <!-- eine Schleife für jedes der Beispielformate -->
            <xsl:for-each select="zahlenFormatierung/formatBeispiele/format">
               <h2>
                  <!-- das Format als Kopfzeile anzeigen -->
                  <xsl:value-of select="."/>
               </h2>
               <table border="1" cellpadding="2" cellspacing="0">
                  <tr>
                     <th>Zahl</th>
                     <th>Ergebnis</th>
                  </tr>
                  <!-- das Format als Parameter an das Template zur Anzeige jeder Zahl übergeben -->
                  <xsl:apply-templates select="/zahlenFormatierung/zahlenBeispiele/zahl">
                     <xsl:with-param name="fmt" select="."/>
                  </xsl:apply-templates>
               </table>
            </xsl:for-each>
         </body>
      </html>
   </xsl:template>
   <!-- Ausgeben der Zahl, gefolgt vom Ergebnis der format-number()-Funktion -->
   <xsl:template match="zahl">
      <xsl:param name="fmt"/>
      <tr>
         <td align="right">
            <xsl:value-of select="."/>
         </td>
         <td align="right">
            <!-- Der erste Parameter ist ein Punkt, der den Textinhalt des <zahl>-Elements repräsentiert -->
            <xsl:value-of select="format-number(.,$fmt)"/>
         </td>
      </tr>
   </xsl:template>
</xsl:stylesheet>

Dieses Stylesheet geht zunächst in einer Schleife eine Liste der <format>-Elemente durch:

<xsl:for-each select="zahlenFormatierung/formatBeispiele/format">

Innerhalb der Schleife werden alle <zahl>-Elemente selektiert. Das bedeutet, jedes Format wird auf jede Zahl angewandt:

<xsl:apply-templates select="/zahlenFormatierung/zahlenBeispiele/zahl">

Formatierung von Text

In der XPath-Spezifikation sind verschiedene Funktionen zur Textformatierung definiert, die es dem Code in einem XSLT-Stylesheet gestatten, Operationen wie die Konkatenation von zwei oder mehreren Strings, Extraktion eines Substrings und Berechnung der Länge eines Strings durchzuführen. Anders als Strings in Java werden alle Strings in XSLT und XPath beginnend mit Position 1 anstatt Position 0 indiziert.

Lassen Sie uns annehmen, daß ein Stylesheet die folgenden Variablen definiert:

<xsl:variable name="vorname" select="'Eric'"/>
<xsl:variable name="nachname" select="'Burke'"/>
<xsl:variable name="mittelname" select="'Matthew'"/>
<xsl:variable name="vollerName" select="concat($vorname, ' ', $mittelname, ' ', $nachname)"/>

In den ersten drei Variablen werden Hochkommas verwendet, um anzuzeigen, daß es sich bei den Werten um Strings handelt. Ohne die Hochkommas würde der XSLT-Prozessor die Werte als XPath-Ausdrücke behandeln und versuchen, die gleichnamigen Knoten aus den XML-Eingabedaten zu selektieren. Die vierte Variable, vollerName, zeigt, wie die concat( )-Funktion genutzt werden kann, um zwei oder mehrere Strings zu konkatenieren. Diese Funktion erwartet eine kommaseparierte Liste von Strings als Argument und liefert die konkatenierten Ergebnisse zurück. In diesem Fall ist Eric Matthew Burke der Wert von vollerName.

Die folgende Tabelle liefert zusätzliche Beispiele für Stringfunktionen. Die Variablen in dieser Tabelle sind dieselben wie im vorangegangenen Beispiel. In der ersten Spalte ist der Rückgabetyp der Funktion zuerst aufgelistet, gefolgt vom Funktionsnamen und der Parameterliste. Die zweite und dritte Spalte zeigen ein Beispiel zur Verwendung und die Ausgabe des Beispiels.

Tabelle: Beispiele für Stringfunktionen

Funktionssyntax Beispiel Ausgabe
string concat(string,string,string*) concat($vorname, ' ', $nachname) Eric Burke
boolean starts-with(string,string) starts-with($vorname, 'Er') true
boolean contains(string,string) contains($vollerName, 'Smith') false
string substring-before(string,string) substring-before($vollerName, ' ') Eric
string substring-after(string,string) substring-after($vollerName, ' ') Matthew Burke
string substring(string,number,number?) substring($mittelname,1,1) M
number string-length(string?) string-length($vollerName) 18
string normalize-space(string?) normalize-space(' test ') test
string translate(string,string,string) translate('test','aeiou','AEIOU') tEst

Alle Stringvergleiche, wie starts-with() und contains( ), unterscheiden zwischen Groß- und Kleinschreibung. Es gibt in XSLT keine Möglichkeit, das abzustellen. Eine Möglichkeit es zu umgehen besteht darin, beide Strings in Groß- oder Kleinbuchstaben umzuwandeln und den Vergleich dann durchzuführen. Auch diese Umwandlung wird in der aktuellen XSLT-Implementierung nicht direkt unterstützt, aber mit der translate( )-Funktion kann diese Aufgabe gelöst werden. Der folgende XSLT-Code wandelt einen String von Klein- in Großbuchstaben um:

translate($text,'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ')

In den Funktionen substring-before( ) und substring-after( ) enthält das zweite Argument einen Begrenzungsstring. Wird dieser sogenannte Delimiter, der nicht unbedingt ein einzelnes Zeichen sein muß, nicht gefunden, wird ein leerer String zurückgeliefert. Diese Funktionen können genutzt werden, um formatierte Daten, wie Datumsangaben, zu parsen:

<datum>25.06.2001</datum>

Der XSLT-Code zur Extraktion von Tag, Monat und Jahr sieht wie folgt aus:

<xsl:variable name="datumsStr" select="//datum"/>
<xsl:variable name="monatJahr" select="substring-after($datumsStr, '.')"/>
Tag: <xsl:value-of select="substring-before($datumsStr, '.')"/> <br/>
Monat: <xsl:value-of select="substring-before($monatJahr, '.')"/> <br/>
Jahr: <xsl:value-of select="substring-after($monatJahr, '.')"/>

In der ersten Codezeile wird die datumsStr-Variable mit dem vollen Datum initialisiert. Die nächste Zeile erzeugt die monatJahr-Variable, die alles ab dem ersten . enthält – an dieser Stelle datumsStr=25.06.2001 und monatJahr=06.2001. In Java ist dies ein wenig einfacher, weil Sie einfach eine Instanz der Klasse StringTokenizer erzeugen und durch die einzelnen Token iterieren oder die lastIndexOf( )-Methode von java.lang.String verwenden, um den zweiten . zu lokalisieren. Mit XSLT sind die Optionen etwas eingeschränkter. Die verbleibenden Zeilen teilen die Variablen in substrings, jeweils wieder begrenzt durch den Punkt (.). Die Ausgabe ist wie folgt:

Tag: 25
Monat: 06
Jahr: 2001

Eine andere Form der substring( )-Funktion nimmt zwei oder mehr Zahlen als Argumente, die den Anfangsindex und optional die Länge des substring angeben. Wird die zweite Zahl ausgelassen, geht der substring bis zum Ende des Eingabestrings weiter. Der Anfangsindex beginnt immer mit Position 1, daher liefert substring("abcde",2,3) bcd zurück und substring("abcde",2) liefert bcde zurück.

   

<< zurück vor >>

 

 

 

Tipp der data2type-Redaktion:
Zum Thema Java & XSLT bieten wir auch folgende Schulungen zur Vertiefung und professionellen Fortbildung an:

Copyright © 2002 O'Reilly Verlag GmbH & Co. KG
Für Ihren privaten Gebrauch dürfen Sie die Online-Version ausdrucken.
Ansonsten unterliegt dieses Kapitel aus dem Buch "Java und XSLT" 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.

O’Reilly Verlag GmbH & Co. KG, Balthasarstraße 81, 50670 Köln, kommentar(at)oreilly.de