count(cd)
показывает правильный номер. Просто ваша HTML-таблица плохо структурирована.
Одна проблема заключается в том, что закрывающая строка </tr>
находится не в том месте, что приводит к тому, что строка вкладывается в строку.
Но ваша главная проблема в том, что первый компакт-диск должен идти в той же строке, что и тот, в котором указано имя исполнителя.
Попробуйте вместо этого XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<h2>My CD Collection</h2>
<table border="1">
<tr bgcolor="#9acd32">
<th style="text-align:left">Artist</th>
<th style="text-align:left">CD</th>
</tr>
<xsl:for-each select="catalog/artist">
<tr>
<td rowspan="{count(cd)}">
<xsl:value-of select="count(cd)"/>
<xsl:value-of select="name"/>
</td>
<td><xsl:value-of select="cd[1]"/></td>
</tr>
<xsl:for-each select="cd[position() > 1]">
<tr>
<td><xsl:value-of select="."/></td>
</tr>
</xsl:for-each>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Кроме того, вы можете написать это так
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<h2>My CD Collection</h2>
<table border="1">
<tr bgcolor="#9acd32">
<th style="text-align:left">Artist</th>
<th style="text-align:left">CD</th>
</tr>
<xsl:for-each select="catalog/artist">
<xsl:variable name="cds" select="count(cd)" />
<xsl:variable name="artist" select="name" />
<xsl:for-each select="cd">
<tr>
<xsl:if test="position() = 1">
<td rowspan="{$cds}">
<xsl:value-of select="$cds"/>
<xsl:value-of select="$artist"/>
</td>
</xsl:if>
<td><xsl:value-of select="."/></td>
</tr>
</xsl:for-each>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>