Getting a substring AFTER the last occurrence of a character in XSLT

后端 未结 3 1152
悲&欢浪女
悲&欢浪女 2021-01-02 07:26

I have a string in an XML file that looks similar to this:

M:Namespace.Class.Method(Something a, Something b)

The number of peri

相关标签:
3条回答
  • 2021-01-02 07:51

    Here is a more efficient solution O(N) vs. O(N^2) for the accepted answer:

    <xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:output method="text"/>
    
     <xsl:template match="text()" name="skipAfterDots">
      <xsl:param name="pTotalString" select="."/>
      <xsl:param name="pTotalLength" select="string-length(.)"/>
      <xsl:param name="pPosition" select="1"/>
      <xsl:param name="pLastFound" select="-1"/>
    
      <xsl:choose>
        <xsl:when test="$pPosition > $pTotalLength">
          <xsl:value-of select="substring($pTotalString, $pLastFound + 1)"/>
        </xsl:when>
        <xsl:otherwise>
          <xsl:variable name="vIsDot" select=
           "substring($pTotalString, $pPosition, 1) = '.'"/>
    
          <xsl:call-template name="skipAfterDots">
            <xsl:with-param name="pTotalString" select="$pTotalString"/>
            <xsl:with-param name="pTotalLength" select="$pTotalLength"/>
            <xsl:with-param name="pLastFound" select=
            "$pLastFound * not($vIsDot) + $pPosition * $vIsDot"/>
            <xsl:with-param name="pPosition" select="$pPosition+1"/>
          </xsl:call-template>
        </xsl:otherwise>
      </xsl:choose>
     </xsl:template>
    </xsl:stylesheet>
    

    When this transformation is applied on the following XML document:

    <t>M:Namespace.Class.Method(Something a, Something b)</t>
    

    the wanted, correct result is produced:

    Method(Something a, Something b)
    

    Explanation:

    This solution doesn't contain any call to the substring-after() function. Instead, at each step only the one character of the string is compared for equality with the dot character. Because there are at most N characters, this is O(N) -- linear complexity.

    On the contrary, the accepted answer calls the substring-after() function on every step. In the worst case there could be N dots and thus this would be O(N^N) -- quadratic complexity.

    Note: We make the reasonable assumption that in both solutions locating the k-th character of a string is O(1).

    0 讨论(0)
  • 2021-01-02 08:04

    If you do know that you have exactly two dots in your strings then you can try:

    <xsl:value-of select="substring-after(substring-after($str, '.'), '.')" /> 
    
    0 讨论(0)
  • 2021-01-02 08:05

    In XSLT 1.0 you will need to use a recursive template, like this:

      <xsl:template name="substring-after-last">
        <xsl:param name="string" />
        <xsl:param name="delimiter" />
        <xsl:choose>
          <xsl:when test="contains($string, $delimiter)">
            <xsl:call-template name="substring-after-last">
              <xsl:with-param name="string"
                select="substring-after($string, $delimiter)" />
              <xsl:with-param name="delimiter" select="$delimiter" />
            </xsl:call-template>
          </xsl:when>
          <xsl:otherwise><xsl:value-of 
                      select="$string" /></xsl:otherwise>
        </xsl:choose>
      </xsl:template>
    

    and invoke it like this:

    <xsl:call-template name="substring-after-last">
      <xsl:with-param name="string" select="'M:Namespace.Class.Method(Something a, Something b)'" />
      <xsl:with-param name="delimiter" select="'.'" />
    </xsl:call-template>
    

    In XSLT 2.0, you can use the tokenize() function and simply select the last item in the sequence:

    tokenize('M:Namespace.Class.Method(Something a, Something b)','\.')[last()]
    
    0 讨论(0)
提交回复
热议问题