XPath 3.0, XPath 2.0, XPath 1.0 / XPath Funktionen / Stringfunktionen / XPath: contains

XPath: contains

XPath: contains

➪ Die XPath-Funktion "contains" prüft, ob in einem String ein bestimmter Teilstring enthalten ist.

Sie kann Teil einer Fallunterscheidung (xsl:if, xsl:choose) sein, aber auch direkt als Prädikat verwendet werden, wodurch sich die relevante Position ändert.


<xsl:for-each select="//Mensch">
  <xsl:if test="contains(vorname, 'ar')">
   <m lfdnr="{position()}">
    <xsl:value-of select="vorname"/>
   </m>
  </xsl:if>
</xsl:for-each>

Resultat:


<m lfdnr="10">Maria</m>
<m lfdnr="11">Mario</m>

Alternativer Aufruf mit abweichender Numerierung:


<xsl:for-each select="//Mensch[contains(vorname, 'ar')]">
  <m lfdnr="{position()}">
   <xsl:value-of select="vorname"/>
  </m>
</xsl:for-each>

Resultat:


<m lfdnr="1">Maria</m>
<m lfdnr="2">Mario</m>

XSL-Versionierung

Bei der Arbeit mit contains und anderen Funktionen ist es wichtig, im XPath-Statement einzelne Nodes zu adressieren. Würden wir dagegen eine ganze Anzahl von Nodes ansprechen, etwa so:


<ergebnis>
  <xsl:value-of 
       select="//*[contains(text(),'los')]"/>
</ergebnis>

so würde das Ergebnis je nach deklarierter XSL-Version unterschiedlich ausfallen.


<xsl:stylesheet 
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     version="1.0">
</xsl:stylesheet>

In der version="1.0" geben unterschiedliche (Xalan ebenso wie Saxon-9) das erste gefundene Element aus, alle folgenden Elemente, die wir mit [contains(text(),'los')] ebenfalls ansprechen, werden ignoriert (Informationsverlust!).


<ergebnis>Holzflos</ergebnis>

In der version="3.0" quittiert der Saxon-9-Prozessor denselben Aufruf dagegen mit einer Fehlermeldung:


Fehlerlevel: fatal
Beschreibung: XPTY0004: A sequence of more than one item 
is not allowed as the first argument of contains() ("", "", ...)

Case-insensitive Suche

Wollen wir case-insensitive nach einem Begriff suchen, zum Beispiel alle Textinhalte im Dokument, die die Zeichenkette "ne" enthalten, aber unabhängig von der Schreibweise (es sollen also auch "Ne", "NE" oder "nE" gefunden werden, so bietet sich die Arbeit mit an:


<xsl:template match="/">
    <ergebnis>
        <xsl:for-each 
             select="/*/descendant::text()
                     [contains(lower-case(.), 'ne')]">
            <gefunden>
                <xsl:value-of select="."/>
            </gefunden>
        </xsl:for-each>
    </ergebnis>
</xsl:template>

Das Ergebnis dieses Aufrufs finden wir hier:


<ergebnis>
   <gefunden>Neustadt</gefunden>
   <gefunden>Simone</gefunden>
   <gefunden>Werner</gefunden>
   <gefunden>Leinenlos</gefunden>
   <gefunden>Liane</gefunden>
</ergebnis>

Eine Alternative, die dasselbe Ergebnis zutage fördert, ist die - Funktion, mit einem Flag für die case-insensitive Prüfung "i".


<xsl:for-each 
     select="/*/descendant::text()
             [matches(., 'ne', 'i')]">
    <gefunden>
        <xsl:value-of select="."/>
    </gefunden>
</xsl:for-each>

Eine dritte Alternative, die ebenfalls dasselbe Ergebnis zutage fördert, ist die Kombination der contains-Funktion mit .


<xsl:for-each 
     select="/*/descendant::text()
             [contains(translate(., 'NE', 'ne'), 'ne')]">
    <gefunden>
        <xsl:value-of select="."/>
    </gefunden>
</xsl:for-each>

Je nach verwendetem Prozessor finden wir eine vierte Alternative in der Arbeit mit einer Collation als drittem Parameter. Zum Thema Collations siehe meine Anmerkungen zum Thema .


<xsl:for-each 
     select="/*/descendant::text()
             [contains(., 'ne', 
             (: Collation-Zeichenkette :))]">
    <gefunden>
        <xsl:value-of select="."/>
    </gefunden>
</xsl:for-each>

fn:contains-token

fn:contains-token prüft, ob die gegebenen Zeichenkette einem Token entspricht, ggf. unter den Regeln der Collation.


fn:contains-token('eins zwei drei ', 'eins') 

ergibt true.


fn:contains-token(
    'Weg Straße Pfad ', 
    'Strasse', 
    'http://www.w3.org/2013/collation/UCA?lang=de;strength=primary')

ergibt ebenfalls true.


fn:contains-token(
                'Weg Straße Pfad ', 
                'Strasse')

ergibt dagegen false.

wg / 17. Februar 2018



Fragen? Anmerkungen? Tips?

Bitte nehmen Sie Kontakt zu mir auf:

Vorname
Nachname
Mailadresse







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/contains.html