How to generate range(sequence) of values from giv

2019-07-28 05:01发布

Please suggest, to generate range of numbers from two values.

I used call-template methods. Please advice. I am using XSLT 2.

XML:

<article>
 <range>3-7</range>
</article>

XSLT:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="//range">
 <xsl:variable name="var1" select="substring-before(., '-')"/>
 <xsl:variable name="var2" select="substring-after(., '-')"/>

 <range>
      <xsl:attribute name="ID">
           <xsl:call-template name="tmpPageRange">
                <xsl:with-param name="stPage" select="$var1"/>
                <xsl:with-param name="lstPage" select="$var2"/>
                <xsl:with-param name="presentvalue" select="$var1"/>
           </xsl:call-template>
      </xsl:attribute>
      <xsl:value-of select="."/>
 </range>
</xsl:template>

      <xsl:template name="tmpPageRange">
           <xsl:param name="stPage"/>
           <xsl:param name="lstPage"/>
           <xsl:param name="presentvalue"/>

           <xsl:if test="number($stPage) &lt; number($lstPage)">
                <xsl:value-of select="concat($presentvalue, ' ')"/>
                <xsl:call-template name="tmpPageRange">
                     <xsl:with-param name="stPage" select="number($stPage) + 1"/>
                     <xsl:with-param name="lstPage"/>
                     <xsl:with-param name="presentvalue" select="$stPage"/>
                </xsl:call-template>
           </xsl:if>
      </xsl:template>
 </xsl:stylesheet>

Required OutPut:

<range ID="3 4 5 6 7">3-7</range>

标签: xslt
2条回答
欢心
2楼-- · 2019-07-28 05:37

You can use the following:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs">
<xsl:template match="article/range">
    <range>
        <xsl:attribute name="ID">
            <xsl:for-each select="xs:integer(tokenize(.,'-')[1]) to xs:integer(tokenize(.,'-')[2])">
                <xsl:value-of select="."/>
                <xsl:if test="position() != last()">
                    <xsl:text> </xsl:text>
                </xsl:if>
            </xsl:for-each>
        </xsl:attribute>
        <xsl:value-of select="."/>
    </range>
</xsl:template>
</xsl:stylesheet>
查看更多
看我几分像从前
3楼-- · 2019-07-28 05:43

Following on from Lingamurthy CS's answer, there are various shortcuts that XSLT 2.0 offers that allow you to shorten this substantially. In fact for your specific requirement you can roll it right the way up into an attribute value template:

<range ID="{xs:integer(tokenize(.,'-')[1]) to xs:integer(tokenize(.,'-')[2])}">
  <xsl:value-of select="."/>
</range>

The XSLT 2.0 rule for converting a sequence of atomic values to a string in an AVT is to convert each item to a string individually and then output the resulting sequence separated by spaces. If you wanted a different separator (or no separator at all) then you could use xsl:attribute, which can take a separator attribute to override the default (single space) separator, e.g.

<range>
  <xsl:attribute name="ID"
           select="xs:integer(tokenize(.,'-')[1]) to xs:integer(tokenize(.,'-')[2])"
           separator="," />
  <xsl:value-of select="."/>
</range>

would produce <range ID="3,4,5,6,7">3-7</range>

查看更多
登录 后发表回答