【问题标题】:how to get the second (third...) occurence of a substring in xslt?如何在 xslt 中获得子字符串的第二次(第三次...)出现?
【发布时间】:2013-06-05 14:22:54
【问题描述】:

我有一个用等号(=)分隔的长字符串作为分隔符,如下所示:

AAA=BBBBB=CCCCCCCCCCCCCCCC=D=FFFFF=GG=H

子字符串可以有任意长度。如果我想获得第一个子字符串,我可以使用 substring-before 函数,如下所示:

<xsl:value-of select="substring-before($vari, '=')"/> 

但是有没有办法只获得第二个(第三个等)子字符串? 我需要 BBBBB 而不是 AAA=BBBBB 和 CCCCCCCCCCCCCCCC 而不是 AAA=BBBBB=CCCCCCCCCCCCCCCC 所以 substring-before-last 不起作用。

【问题讨论】:

    标签: string xslt substring


    【解决方案1】:

    仅供参考,如果您有 EXSLT's String extension elements 可用,您可以执行以下操作:

    <xsl:value-of select="str:tokenize($vari, '=')[2]" />
    

    使用上面的字符串,这将返回BBBBB

    在 XPath 2.0 中,这个函数是内置的:

    <xsl:value-of select="tokenize($vari, '=')[2]" />
    

    【讨论】:

      【解决方案2】:

      使用 xslt-1.0: 这可以通过 substring-after 和 substring-before 的组合来完成。
      试试:

      <xsl:value-of select="substring-before(
                      substring-after ($vari, , '=')
                     , '=')"/>                    
      

      对于 BBBBB
      或者:

      <xsl:value-of select="substring-before(
                       substring-after ( substring-after ($vari,  '='),  '=')
                       , '=')"/>                  
      

      对于CCCCCCCCCCCCCCCC。

      注意:未测试。

      使用 xslt-2.0 可能会有更好的方法。

      【讨论】:

      • 谢谢,它有效。丑得要命,但可能是 xslt 的错。
      【解决方案3】:

      这是一个 xslt-1.0 解决方案,它不需要使用扩展,并且可以使用任意分隔符长度和分隔符出现:

      <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      
        <xsl:template match="/">
          <xsl:call-template name="substring-nth-occurrence-position">
            <xsl:with-param name="string">aaa_#bbb_#ccc_#dddd_#ee</xsl:with-param>
            <xsl:with-param name="substr">_#</xsl:with-param>
            <xsl:with-param name="occurrence">3</xsl:with-param>
          </xsl:call-template>      
        </xsl:template>      
      
        <xsl:template name="substring-nth-occurrence-position">
          <xsl:param name="string"/>
          <xsl:param name="substr"/>
          <xsl:param name="occurrence"/>
          <xsl:param name="current_iteration" select="1"/> 
          <xsl:param name="accumulated_length" select="0"/> 
      
          <xsl:choose>
            <!-- in case occurrence is greater than the number of instances of substr return 0 -->
            <xsl:when test="not(contains($string, $substr))">0</xsl:when>
      
            <xsl:otherwise>
              <!-- determine the position of the next instance of substr in the (remaining part of ) string and add it to accumulated_length-->
              <xsl:variable name="v.accumulated_length_new">
                <xsl:variable name="v.idx.of.substr">
                  <xsl:call-template name="instr">
                    <xsl:with-param name="string" select="$string"/>
                    <xsl:with-param name="substr" select="$substr"/>     
                  </xsl:call-template>              
                </xsl:variable>    
      
                <xsl:value-of select="$accumulated_length + $v.idx.of.substr"></xsl:value-of>
              </xsl:variable> 
      
              <!-- if current_iteration equals occurrence then return accumulated length... -->
              <xsl:choose>
                <xsl:when test="$current_iteration= $occurrence ">
                  <xsl:value-of select="$v.accumulated_length_new" />
                </xsl:when>  
      
                <!-- ... else run another iteration-->            
                <xsl:otherwise>
                  <xsl:call-template name="substring-nth-occurrence-position">
                    <xsl:with-param name="string" select="substring-after($string, $substr)"/>
                    <xsl:with-param name="substr" select="$substr"/>
                    <xsl:with-param name="occurrence" select="$occurrence"/>                 
                    <xsl:with-param name="current_iteration" select="$current_iteration + 1"/> 
                    <xsl:with-param name="accumulated_length" select="$v.accumulated_length_new + string-length($substr) - 1"/>                 
                  </xsl:call-template>    
                </xsl:otherwise>
              </xsl:choose>  
            </xsl:otherwise>
          </xsl:choose>
        </xsl:template>    
      
      
        <!-- returns the position of the first occurrence of a substring in a string -->
        <xsl:template name="instr">
          <xsl:param name="string"/>
          <xsl:param name="substr"/>
          <xsl:value-of select="contains($string,$substr)*(1 + string-length(substring-before($string,$substr)))"  />
        </xsl:template>  
      
      </xsl:stylesheet>
      

      (上例执行结果为14)。

      【讨论】:

        猜你喜欢
        • 2018-02-05
        • 2012-07-11
        • 2020-06-07
        • 1970-01-01
        • 1970-01-01
        • 2020-02-26
        • 1970-01-01
        • 2020-10-30
        • 1970-01-01
        相关资源
        最近更新 更多