 <p>Use the alternative <code>&lt;xsl:for-each&gt;</code> notation to loop over a set of integers:</p> <pre><code>&lt;xsl:for-each select="1 to 5"&gt; ... '.' will be an integer from 1 to 5 here &lt;/xsl:for-each&gt; </code></pre> <p>To create the filename from this, use</p> <pre><code>... fs:exists(fs:new(concat('/images/',$imageproductid,'_00', ., '.jpg') </code></pre> <p>and to create a properly named new element, use <code>&lt;xsl:element&gt;</code>:</p> <pre><code>&lt;xsl:element name="{concat('IMAGE', .)}"&gt; .. &lt;IMAGEx&gt; contents .. &lt;/xsl:element&gt; </code></pre> <p>You need the notation <code>{..}</code> here because <code>name</code> must be a valid QName (<a href="https://www.w3.org/TR/xslt20/#element-element" rel="nofollow">W3C, "11.2 Creating Element Nodes Using <code>xsl:element</code>"</a>), which I take as "the <em>literal</em> text must be a valid possible element name".</p> <p>Putting that together, you end up with this concise code:</p> <pre><code>&lt;xsl:template match="product"&gt; &lt;xsl:apply-templates /&gt; &lt;xsl:variable name="imageproductid" select="code" /&gt; &lt;xsl:for-each select="1 to 5"&gt; &lt;xsl:variable name="filename" select="concat('/images/',$imageproductid,'_00', ., '.jpg')" /&gt; &lt;xsl:if test="fs:exists(fs:new($filename))"&gt; &lt;xsl:element name="{concat('IMAGE', .)}"&gt; &lt;xsl:value-of select="$filename" /&gt; &lt;/xsl:element&gt; &lt;/xsl:if&gt; &lt;/xsl:for-each&gt; &lt;/xsl:template&gt; </code></pre>