XSLT: Finding last occurence in a string

前端 未结 4 1975
轮回少年
轮回少年 2020-12-18 00:55

Given a form number like:

ABC_12345_Q-10

I want to end up with:

ABC12345

So I need to find the position o

相关标签:
4条回答
  • 2020-12-18 00:59

    Generalized one -

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

    Idea is to get the index of last occurrence by splitting string.

    Index of last occurrence = string-length($string) - length of last string after split

    0 讨论(0)
  • 2020-12-18 01:02

    @Pavel_Minaev has provided XPath 1.0 amd XPath 2.0 solutions that work if it is known in advance that the number of underscores is 2.

    Here are solutions for the more difficult problem, where the number of undrscores isn't statically known (may be any number):

    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>
    

    when this transformation is applied to any XML document (not used), the desired, correct result is produced:

    ABC12345
    
    0 讨论(0)
  • 2020-12-18 01:18
    concat(
        substring-before($s, '_'),
        substring-before(substring-after($s, '_'), '_')
    )
    

    Alternatively:

    string-join(tokenize($s, '_')[position() <= 2], '')
    
    0 讨论(0)
  • 2020-12-18 01:18

    Easier solution in XSLT 2.0:

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

    With 'substring-before' you will get everything after the last occurrence of your delimiter (the underscore). If you use 'substring-after' instead, you will get everything before the last occurrence of your deliminator.

    0 讨论(0)
提交回复
热议问题