XPath 3.0, XPath 2.0, XPath 1.0 / XPath-Funktionen / Stringfunktionen / XPath: string oder xs:string?

XPath: string oder xs:string?

XPath: string oder xs:string?

➪ Die XPath-Funktion string konvertiert einen Textnode in einen String.

Auf dieser Seite:

Einfach und unkompliziert ist die Anwendung der string-Funktion bei einem einzelnen, klar definierten Element. Hier wird ein Textnode in einen String konvertiert.


<xsl:value-of select="string(//Ort[1]/Mensch[1]/vorname)"/>

Das funktioniert auch bei folgendem Aufruf, wo sämtliche Textnodes des komplexen Elements Mensch in einen Einzelstring <s> ... </s> übernommen werden (es entstehen also nicht mehrere <s> ... </s>).


<xsl:for-each 
     select="string(//Ort[1]/Mensch[1])">
  <s><xsl:value-of select="."/></s>
</xsl:for-each>

Alternativ (mit demselben Ergebnis) wäre auch der folgende Aufruf denkbar gewesen: xs:string(//Ort[1]/Mensch[1]). Das Ergebnis ist:


1 Holzflos Hugo 234.56 1 1 3 
Hemd 12.99 38.97 1 9 
Hemd 12.99 116.91 1 8 
Hemd 12.99 103.92 1 9 
Hose 25.99 233.91 1 9 
Hose 25.99 233.91 1 8 
Hose 25.99 207.92 1 8 
Hose 25.99 207.92 1 8 
Schuhe 151.23 1209.84 1 8 
Schuhe 151.23 1209.84 

Wichtig ist, dass sich ein eindeutiger Node adressieren lässt. Unzulässig ist dagegen die Übergabe einer Nodelist mit mehreren Items, was wieder zu der Fehlermeldung "A sequence of more than one item ... " führt. Vergleichen Sie auch hier die Sequenz-Funktionen und .


<xsl:for-each 
     select="string(//Ort[1]/Mensch[1]/child::*)">
  <s><xsl:value-of select="."/></s>
</xsl:for-each>
Fehlerlevel: fatal
Beschreibung: XPTY0004: A sequence of more than one item is 
not allowed as the first argument of string() (<id/>, <name/>, ...)
URL: http://www.w3.org/TR/xpath20/#ERRXPTY0004

bzw.


<xsl:for-each 
     select="string(//Mensch)">
  <s><xsl:value-of select="."/></s>
</xsl:for-each>
Fehlerlevel: fatal
Beschreibung: XPTY0004: A sequence of more than one item is 
not allowed as the first argument of string() (<Mensch/>, <Mensch/>, ...)
URL: http://www.w3.org/TR/xpath20/#ERRXPTY0004

Siehe auch den .

fn:string oder xs:string?

Die string-Funktion wird in XPath 1.0 verwendet; in XPath 2.0 steht zusätzlich der Schema-Datentyp xs:string zur Verfügung (xmlns:xs="http://www.w3.org/2001/XMLSchema). Je nach XPath-Version wird die string-Funktion intern anders verarbeitet.

XPath 1.0 string(object): string. Ist object eine Liste mit mehreren Nodes, muss damit gerechnet werden, dass nur der erste Node verarbeitet wird; die restlichen Nodes werden ignoriert.
XPath 2.0 fn:string() as xs:string; fn:string($arg as item()?) as xs:string

Bei einigen XSLT-3.0-Prozessoren können Sie den Unterschied zwischen xs:string und fn:string gut erkennen, wenn Sie eine analysieren. Betrachten Sie die Variable "v1", die lediglich ein root-Element aufweist; dieses besitzt jedoch kein Childnode wert, dessen Existenz Sie überprüfen wollen.


<xsl:variable name="v1"><root/></xsl:variable>

<xsl:template match="/">
  <ergebnis>
    <empty>
      <xsl:value-of 
           select="empty($v1/root/wert)"/>
    </empty>
    <empty_xs_string>
      <xsl:value-of 
           select="empty(xs:string($v1/root/wert))"/>
    </empty_xs_string>
    <exists_string>
      <xsl:value-of 
           select="exists(string($v1/root/wert))"/>
    </exists_string>
    <one-or-more_string>
      <xsl:value-of 
           select="one-or-more(string($v1/root/wert))"/>
    </one-or-more_string>
    <exactly-one_string>
        <xsl:value-of 
             select="exactly-one(string($v1/root/wert))"/>
    </exactly-one_string>
  </ergebnis>
</xsl:template>

Die Gegenprobe bestätigt das mit dem jeweiligen Ergebnis "false".


<xsl:template match="/">
  <ergebnis>
    <emptystring>
      <xsl:value-of 
           select="empty(string($v1/root/wert))"/>
    </emptystring>
    <exists>
      <xsl:value-of 
           select="exists($v1/root/wert)"/>
    </exists>
    <exists_xs_string>
      <xsl:value-of 
           select="exists(xs:string($v1/root/wert))"/>
    </exists_xs_string>
    <!--<one-or-more>
    <xsl:value-of 
         select="one-or-more($v1/root/wert)"/>
  </one-or-more>-->
    <!--<one-or-more_xs_string>
    <xsl:value-of 
         select="one-or-more(xs:string($v1/root/wert))"/>
  </one-or-more_xs_string>-->
    <!--<exactly-one>
        <xsl:value-of 
             select="exactly-one($v1/root/wert)"/>
    </exactly-one>-->
    <!--<exactly-one_xs_string>
        <xsl:value-of 
             select="exactly-one(xs:string($v1/root/wert))"/>
    </exactly-one_xs_string>-->
  </ergebnis>
</xsl:template>

Typabhängige Auswertung

In XSLT 2.0 hängt die Auswertung von string() vom Typ des übergebenen Parameters ab. Ist der Input ein Atom-Wert (atomic value), so werden Boolean-Werte (xs:boolean mit true() oder false()) als Strings dargestellt (true, false). Ähnliches gilt für Zahlen oder Datumswerte: Sie können die Inhalte mit Stringfunktionen weiter verarbeiten, aber keine Rechenoperationen durchführen.


<xsl:variable 
     name="v1" 
     select="string(//Ort[1]/Mensch[2]/Kauf[2]/preis)"/>
<xsl:variable 
     name="v2" 
     select="string(//Ort[1]/Mensch[2]/Kauf[2]/anzahl)"/>   

Eine Multiplikation der Stringwerte läuft auf einen Fehler:


<xsl:value-of select="$v2 * $v1"/>
Fehlerlevel: fatal
Beschreibung: XPTY0004: Arithmetic operator is not defined for 
arguments of types (xs:string, xs:string)
URL: http://www.w3.org/TR/xpath20/#ERRXPTY0004

Prinzipiell korrekt wäre nun eine Typkonvertierung von string zu number:


<xsl:value-of 
     select="number($v2) * number($v1)"/>

Hier schlägt jedoch die automatische Typkonvertierung für number() zu, die beide Werte als xs:double betrachtet und entsprechend behandelt. Ist $v2=25.99 und $v1=7, so wird als Ergebnis nicht 181.93 berechnet, sondern 181.92999999999998.

Der scheinbar vernachlässigbare Rundungsfehler kann sich bei sehr zahlreichen Rechenoperationen (Summierungen) zu einem absoluten Fehler auswirken. Daher empfiehlt sich eine Typkonvertierung als xs:decimal:


<xsl:value-of 
     select="xs:decimal($v2) * xs:decimal($v1)"/>

Sonderzeichen

Ein xs:string kann auch Sonderzeichen wie Carriage Return (#xD), Linefeed (#xA) oder Tabulator (#x9) beinhalten.


<erg>
<xsl:variable 
     name="vstring" 
     as="xs:string"> ab;cde&#xA;fg  h;&#x9;i&#x9;jk </xsl:variable>
<xsl:value-of select="$vstring"/>
</erg>

Das Ergebnis des vorstehenden Aufrufs beinhaltet auch den Zeilenumbruch und das Tabulatorzeichen.


<erg>   ab;cde
fg  h;	i	jk    </erg>

Siehe auch und .

wg / 13. April 2018



Fragen? Anmerkungen? Tipps?

Bitte nehmen Sie Kontakt zu mir auf.






Vielen Dank für Ihr Interesse an meiner Arbeit.


V.i.S.d.P.: Wilfried Grupe * Klus 6 * 37643 Negenborn

☎ 0151. 750 360 61 * eMail: info10@wilfried-grupe.de

www.wilfried-grupe.de/string.html