如何在xslt中获得第二个(第三个)子串的出现?

时间:2013-06-05 14:22:55

标签: string xslt substring

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

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

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

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

但有没有办法只获得第二个,(第三个等)子字符串? 我需要 BBBBB 而不是AAA = BBBBB和 CCCCCCCCCCCCCCCC 而不是AAA = BBBBB = CCCCCCCCCCCCCCCC所以在前一个子串之前不能工作。

3 个答案:

答案 0 :(得分: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]" />

答案 1 :(得分:0)

使用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,  '='),  '=')
                 , '=')"/>                  

对于CCCCCCCCCCCCCC。

注意:未经测试。

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

答案 2 :(得分:0)

这是一个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)。