XPath / XPath-Funktionen / Stringfunktionen / XPath: tokenize
![]() |
![]() |
➪ Die XPath-Funktion tokenize konvertiert einen String in eine Sequenz.
Auf dieser Seite:Siehe auch
Die tokenize-Funktion ist im Grunde das Gegenstück zu string-join. Während string-join in der Lage ist, eine Sequenz mit mehreren Items in einen Einzelstring zu konvertieren, wobei auch Trennzeichen eingefügt werden können (im Beispiel: ";"), kann tokenize einen derartigen String unter Zuhilfenahme des Trennzeichens wieder in eine Sequenz konvertieren.
Um das zu verdeutlichen, generieren Sie zunächst eine Sequenz aus den Werten 'Meier', 'Schulze', 'Müller', 'Schmidt' sowie den Zahlen 1 bis 10.
<xsl:variable name="v1" as="xs:string+">
<xsl:for-each
select="('Meier',
'Schulze',
'Müller',
'Schmidt',
1 to 10)">
<xsl:value-of select="."/>
</xsl:for-each>
</xsl:variable>
Im nächsten Schritt konvertieren Sie die Sequenz in einen String mit dem Trennzeichen ";".
<xsl:variable name="v2" as="xs:string">
<xsl:value-of select="string-join($v1, ';')"/>
</xsl:variable>
Denselben Effekt erreichen Sie übrigens auch mit dem separator-Attribut von xsl:value-of:
<xsl:value-of
select="'Meier',
'Schulze',
'Müller',
'Schmidt',
1 to 10"
separator=";"/>
Zur Kontrolle können Sie sich den generierten String anzeigen lassen:
<xsl:value-of select="$v2"/>
Hier ist also der String:
Meier;Schulze;Müller;Schmidt;1;2;3;4;5;6;7;8;9;10
Nun kommt tokenize ins Spiel, das den String in eine Itemlist aufsplittet:
<xsl:for-each
select="tokenize(xs:string($v2), ';')">
<item>
<xsl:value-of select="."/>
</item>
</xsl:for-each>
Resultat:
<item>Meier</item>
<item>Schulze</item>
<item>Müller</item>
<item>Schmidt</item>
<item>1</item>
<item>2</item>
<item>3</item>
<item>4</item>
<item>5</item>
<item>6</item>
<item>7</item>
<item>8</item>
<item>9</item>
<item>10</item>
Wie wollen Sie jedoch verfahren, wenn die Zeichentrenner kein Semikolon darstellen, sondern aus Zeichen bestehen, die in regulären Ausdrücken eine besondere Bedeutung haben, etwa "." oder "\"?
Meier.Schulze.Müller.Schmidt.1.2.3.4.5.6.7.8.9.10
Meier\Schulze\Müller\Schmidt\1\2\3\4\5\6\7\8\9\10
Da auch die tokenize-Funktion mit regulären Ausdrücken arbeitet, benötigen Sie den Einsatz eines speziellen Flags q, das dafür sorgt, dass Spezialzeichen in den regulären Ausdrücken als normale Zeichen betrachtet werden. Allgemeines zum Thema Flags finden Sie unter matches.
<xsl:for-each
select="tokenize('Meier\Schulze\Müller\Schmidt',
'\',
'q')">
<item>
<xsl:value-of select="."/>
</item>
</xsl:for-each>
Dieselbe Lösung sieht in XQuery so aus:
xquery version '3.0';
<erg>{
for $m in tokenize('Meier\Schulze\Müller\Schmidt',
'\',
'q')
return
<item>{$m}</item>
}</erg>
Interessant ist auch die Variante, die einzelnen Items der generierten Sequenz auf bestimmte Eigenschaften hin zu überprüfen, etwa, ob sie sich als xs:integer casten lassen. Damit fallen die Werte 'Meier', 'Schulze', 'Müller', 'Schmidt' aus der Sequenz heraus, übrig bleiben die Integerwerte.
<xsl:for-each
select="tokenize(xs:string($v2), ';')
[. castable as xs:integer]">
<item>
<xsl:value-of select="."/>
</item>
</xsl:for-each>
Resultat:
<item>1</item>
<item>2</item>
<item>3</item>
<item>4</item>
<item>5</item>
<item>6</item>
<item>7</item>
<item>8</item>
<item>9</item>
<item>10</item>
Etwas mißverständlich ist die Namensgebung etwa für xs:token: Hierbei handelt es sich um einen String ohne Whitespaces wie line feeds (#xA), carriage returns (#xD) oder tabs (#x9), die jedoch innerhalb von xs:token ggf. erlaubt sein können.
<xs:restriction base="xs:normalizedString">
<xs:whiteSpace value="collapse"/>
</xs:restriction>
Ein xs:string kann jedoch auch jene Sonderzeichen beinhalten.
<xsl:variable
name="vstring"
as="xs:string"> ab;cde
fg h;	i	jk </xsl:variable>
<erg3>
<xsl:for-each
select="tokenize($vstring, ';')">
<item>
<xsl:value-of select="."/>
</item>
</xsl:for-each>
</erg3>
Nun könnten Sie erwarten, dass die tokenize-Funktion sich weigert, einen solchen String abzuarbeiten. Fehlanzeige:
<erg3>
<item> ab</item>
<item>cde
fg h</item>
<item> i jk </item>
</erg3>
Erst die kombinierte Anwendung von normalize-space löscht die unerwünschten Sonderzeichen, sodass die tokenize-Funktion zu einem anderen Resultat kommt.
<erg4>
<xsl:for-each
select="tokenize(normalize-space($vstring), ';')">
<item>
<xsl:value-of select="."/>
</item>
</xsl:for-each>
</erg4>
Noch besser (Danke für den Tipp!): Deklarieren Sie die Variable gleich mit dem passenden Datentyp xs:token.
<xsl:variable
name="vtoken"
as="xs:token"> ab;cde
fg h;	i	jk </xsl:variable>
<erg4>
<xsl:for-each select="tokenize($vtoken, ';')">
<item>
<xsl:value-of select="."/>
</item>
</xsl:for-each>
</erg4>
In XQuery gefällt mir dieser Ansatz genau so gut:
xquery version '3.0';
<erg4>{
let $v as xs:token := " ab;cde
fg h;	i	jk "
for $m in tokenize($v, ';') return
<item>{$m}</item>
}</erg4>
Das Ergebnis:
<erg4>
<item>ab</item>
<item>cde fg h</item>
<item> i jk</item>
</erg4>
wg / 15. März 2019
Fragen? Anmerkungen? Tipps?
Bitte nehmen Sie Kontakt zu mir auf.
V.i.S.d.P.: Wilfried Grupe * Klus 6 * 37643 Negenborn
☎ 0151. 750 360 61 * eMail: info10@wilfried-grupe.de