2010-06-29 5 views
6

Étant donné un numéro de formulaire comme:XSLT: Trouver la dernière occurence dans une chaîne

ABC_12345_Q-10

Je veux finir avec:

abc12345

donc je dois trouver le position du second trait de soulignement

Notez qu'il n'y a pas de motif ou de longueur standard pour l'une des "sections" entre les traits de soulignement (donc je ne peux pas utiliser la sous-chaîne pour simplifier y éliminer la dernière section).

XPath 2.0 solutions ok

+0

Qu'est-ce qui est arrivé avec le premier trait de soulignement dans votre échantillon? – Lucero

+0

Bonne question (+1). Voir ma réponse pour les solutions XPath 2.0 et XSLT 1.0 au problème plus général lorsque le nombre de caractères de soulignement n'est pas connu à l'avance. :) –

Répondre

2
concat(
    substring-before($s, '_'), 
    substring-before(substring-after($s, '_'), '_') 
) 

Autre possibilité:

string-join(tokenize($s, '_')[position() <= 2], '') 
+0

Ceux-ci ne fonctionnera pas, car ils donneront ABC12345Q-10 –

+0

Les deux semblent fonctionner correctement. – johkar

11

@Pavel_Minaev a fourni des solutions XPath 1.0 amd XPath 2.0 qui fonctionnent si l'on sait à l'avance que le nombre de underscores est 2.

Voici des solutions pour le problème plus difficile, où le nombre de undrscores n'est pas connu statiquement (peut être un nombre quelconque):

XPath 2.0:

translate(substring($s, 
        1, 
        index-of(string-to-codepoints($s), 
          string-to-codepoints('_') 
          )[last()] -1 
        ), 
      '_', 
      '' 
     ) 

XSLT 1.0:

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

    <xsl:variable name="s" select="'ABC_12345_Q-10'"/> 
    <xsl:template match="/"> 
    <xsl:call-template name="stripLast"> 
    <xsl:with-param name="pText" select="$s"/> 
    </xsl:call-template> 
    </xsl:template> 

    <xsl:template name="stripLast"> 
    <xsl:param name="pText"/> 
    <xsl:param name="pDelim" select="'_'"/> 

    <xsl:if test="contains($pText, $pDelim)"> 
     <xsl:value-of select="substring-before($pText, $pDelim)"/> 
     <xsl:call-template name="stripLast"> 
     <xsl:with-param name="pText" select= 
      "substring-after($pText, $pDelim)"/> 
     <xsl:with-param name="pDelim" select="$pDelim"/> 
     </xsl:call-template> 
    </xsl:if> 
    </xsl:template> 
</xsl:stylesheet> 

lorsque cette transformation est appliqué à un document XML (non utilisé) , le résultat désiré et correct est produit:

ABC12345 
4

solution plus facile à XSLT 2.0:

codepoints-to-string(reverse(string-to-codepoints(
    substring-before(
     codepoints-to-string(reverse(string-to-codepoints($s))), '_')))) 

Cela vous donnera tout avant la dernière occurrence de votre delimiter (le trait de soulignement).

0

GENERALISEE un -

substring($string,1, string-length($string)-string-length(str:split($string, '_')[count(str:split($string, '_'))])) 

idée est d'obtenir l'indice de la dernière occurrence par chaîne de division.

Index de la dernière occurrence = chaîne de longueur ($ string) - longueur de la dernière chaîne après division

+0

Une solution qui dépend d'une fonction d'extension prise en charge par quelques processeurs n'est guère "généralisée". –

Questions connexes