Reputation: 53
I am trying to generate a counter and I do it successfully using the position() function in xslt.
How can I create a counter within a range -1001 - 9999 such that the first counter is 1001 in place of 1.
in put xml
<ROOT>
<Row>
<Var>11</Var>
</Row>
<Row>
<Var>11</Var>
</Row>
<Row>
<Var>3</Var>
</Row>
<Row>
<Var>43</Var>
</Row>
<Row>
<Var>51</Var>
</Row>
and the desired o/p is
<ROOT>
<Row>
<Var>11</Var>
<seq>1001</seq>
</Row>
<Row>
<Var>11</Var>
<seq>1002</seq>
</Row>
<Row>
<Var>3</Var>
<seq>1003</seq>
</Row>
<Row>
<Var>43</Var>
<seq>1004</seq>
</Row>
<Row>
<Var>51</Var>
<seq>1005</seq>
</Row>
..
Thanks, Vicky
Upvotes: 0
Views: 428
Reputation: 163458
Note that with XSLT 3.0 you can do
<seq>
<xsl:number start-at="1001" />
</seq>
Upvotes: 0
Reputation: 167706
Well, XPath 2 and later literally allows you to write 1000 to 9999
to create a sequence of those numbers. I am not sure how that fits into your problem as you haven't provided any context like input you have and output you want. In XSLT 3 (not 2) the xsl:number
element often used to count or number things also has a start-at
attribute, see https://www.w3.org/TR/xslt-30/#element-number.
As you seem to want to number elements from the input I think the right approach is to use xsl:number
so with XSLT 3 you can simply do:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0">
<xsl:mode on-no-match="shallow-copy"/>
<xsl:output indent="yes"/>
<xsl:template match="Row">
<xsl:copy>
<xsl:apply-templates/>
<seq>
<xsl:number start-at="1001"/>
</seq>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
http://xsltfiddle.liberty-development.net/jyyiVhq
with XSLT 2 you can of course use xsl:number
in a variable and then at 1000 e.g.
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" version="2.0"
exclude-result-prefixes="xs">
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:output indent="yes"/>
<xsl:template match="Row">
<xsl:copy>
<xsl:apply-templates/>
<seq>
<xsl:variable name="count" as="xs:integer"><xsl:number/></xsl:variable>
<xsl:value-of select="$count + 1000"/>
</seq>
</xsl:copy>
</xsl:template>
</xsl:transform>
http://xsltransform.hikmatu.com/jyyiVhn
I don't think it makes sense to use the to
expression for your use case, it would rather be useful if you wanted to create a couple of new elements e.g.
<xsl:template match="body">
<xsl:copy>
<xsl:for-each select="1001 to 1100">
<seq>
<xsl:value-of select="."/>
</seq>
</xsl:for-each>
</xsl:copy>
</xsl:template>
Upvotes: 1
Reputation: 53
I achieved the req as below:
<xsl:template match="/">
<ROOT>
<xsl:apply-templates />
</ROOT>
</xsl:template>
<xsl:template match="ROOT/Row">
<Row>
<Var>
<xsl:value-of select="Var"/>
</Var>
<seq>
<xsl:value-of select="1000 + position()" />
</seq>
</Row>
</xsl:template>
Upvotes: 1