Я могу придумать, как этого добиться, но это не выглядит красиво, и, надеюсь, кто-то придумает лучший способ ...
Во-первых, я определил переменную с уровнем текущего узла
<xsl:variable name="level">
<xsl:value-of select="count(ancestor::*)"/>
</xsl:variable>
Далее, сопоставьте все потомки или текущий узел, которые оказались конечными узлами и не имеют никаких предков (включая самого себя, но только до текущего уровня) с атрибутом @trg = 'rr' как указано.
<xsl:apply-templates select=".//*[not(node())][not(ancestor-or-self::*[count(ancestor::*) > $level][@trg='rr'])]">
<xsl:with-param name="currentLevel" select="$level"/>
</xsl:apply-templates>
Сопоставив конечные узлы, вы сможете вернуть путь родительских узлов обратно к текущему узлу.
Вот полная таблица стилей
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:apply-templates select="root/t"/>
</xsl:template>
<xsl:template match="t">
<!-- The level of the current node -->
<xsl:variable name="level">
<xsl:value-of select="count(ancestor::*)"/>
</xsl:variable>
<paths>
<!-- Match all leaf nodes where there is not an ancestor (up to the current node) with the attribute @trg = 'rr' -->
<xsl:apply-templates select=".//*[not(node())][not(ancestor-or-self::*[count(ancestor::*) > $level][@trg='rr'])]">
<xsl:with-param name="currentLevel" select="$level"/>
</xsl:apply-templates>
</paths>
</xsl:template>
<!-- For leaf nodes, write out the ancestor path to a specified level -->
<xsl:template match="*[not(node())]">
<xsl:param name="currentLevel"/>
<path>
<xsl:for-each select="ancestor::*[count(ancestor::*) >= $currentLevel]">
<xsl:value-of select="name()"/>
<xsl:text>/</xsl:text>
</xsl:for-each>
<xsl:value-of select="name()"/>
</path>
</xsl:template>
</xsl:stylesheet>
При применении к данному XML возвращаются следующие результаты
<paths>
<path>t/a1/b2/c2</path>
<path>t/a2/b3/c3</path>
</paths>