Пустая пара tr, скорее всего, появляется когда число товаров на странице кратно трем. Отсюда логический вывод, что после обработки последнего item для текущей страницы, запись tr нам выводить не нужно.
Попробуйте дополнить условие вывода следующим образом:
<!-- Позиций в строке -->
<xsl:if test="position() mod 3 = 0 and position() != last()">
<xsl:text disable-output-escaping="yes"></tr> <tr style="background-color:</xsl:text>
<xsl:value-of select="$background_color"/>
<xsl:text disable-output-escaping="yes">;" valign="top"></xsl:text>
</xsl:if>
А еще, на самом деле, неплохо бы предусмотреть вариант вывода одного или двух пустых td в случае, когда число товаров в последней строке меньше трех.
Сделать это можно, например, так:
<!--создадим пустые ячейки если число товаров в последней строке меньше 3х -->
<xsl:if test="position() = last() and position() mod 3 > 0">
<!--если в последней строке 2 товара-->
<xsl:text disable-output-escaping="yes"><td> </td></xsl:text>
<xsl:if test="position() mod 2 = 0">
<!--если в последней строке 1 товар-->
<xsl:text disable-output-escaping="yes"><td> </td></xsl:text>
</xsl:if>
</xsl:if>
Вставлять этот блок нужно перед комментарием "Цвет считаем здесь и по более сложной логике"
Всегда пожалуйста
