How to copy child element n times in XML file using XSLT

Question

I am very new to XSLT. I need to transform and copy child nodes 1000 times and also increment the id node so that they are different each time.

Input XML:

<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" href="test.xsl"?>
<catalog>
    <cd>
        <id>2017</id>
        <artist>Bob Dylan</artist>
        <country>USA</country>
        <company>Columbia</company>
        <price>10.90</price>
        <year>1985</year>
    </cd>
</catalog>

My XSLT: but it only copies once

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

What I need is: Please help

<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet type="text/xsl"   href="test.xsl"?>
<catalog>
    <cd>
        <id>2017</id>
        <artist>Bob Dylan</artist>
        <country>USA</country>
        <company>Columbia</company>
        <price>10.90</price>
        <year>1985</year>
   </cd>
    <cd>
        <id>2018</id>
        <artist>Bob Dylan</artist>
        <country>USA</country>
        <company>Columbia</company>
        <price>10.90</price>
        <year>1985</year>
   </cd>
   <cd>
        <id>2019</id>
        <artist>Bob Dylan</artist>
        <country>USA</country>
        <company>Columbia</company>
        <price>10.90</price>
        <year>1985</year>
   </cd>

    <!-- 997 more times with ID increment +1 each time  -->

</catalog>

Show source
| xml   | xslt   | using   | transform   2017-01-03 22:01 1 Answers

Answers ( 1 )

  1. 2017-01-03 22:01

    In XSLT 1.0, you can achieve this by using a recursive template. So the template repeatedly calls itself, incrementing a parameter each time until it reaches the required limit.

    Try this XSLT (replace the parameter 5 with 1000, as required)

    <xsl:stylesheet version="1.0"  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:param name="total" select="5" />
    
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    
    <xsl:template match="cd" name="cd">
        <xsl:param name="count" select="1" />
        <xsl:copy>
            <xsl:apply-templates select="@*|node()">
                <xsl:with-param name="count" select="$count" />
            </xsl:apply-templates>
        </xsl:copy>
        <xsl:if test="$count &lt; $total">
            <xsl:apply-templates select=".">
                <xsl:with-param name="count" select="$count + 1" />
            </xsl:apply-templates>
        </xsl:if>
    </xsl:template>
    
    <xsl:template match="id">
        <xsl:param name="count" />
        <xsl:copy>
            <xsl:value-of select="number() + $count - 1" />
        </xsl:copy>
    </xsl:template>
    </xsl:stylesheet>
    

    EDIT: If you want the same logic but for other elements under cd, simply amend the template matching id to include them in the match. For example..

    <xsl:template match="id|year">
        <xsl:param name="count" />
        <xsl:copy>
            <xsl:value-of select="number() + $count - 1" />
        </xsl:copy>
    </xsl:template>
    

    See this in action at http://xsltransform.net/gWEamLv

◀ Go back