Это преобразование :
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="Variation[@Id = 1]">
<xsl:apply-templates mode="printName"
select="ancestor::TestCase"/>
</xsl:template>
<xsl:template match="TestCase" mode="printName">
<xsl:if test="not(position()=1)">
<xsl:text> </xsl:text>
</xsl:if>
<xsl:value-of select="@Name"/>
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
при применении к предоставленному документу XML :
<Module Name="DacInPlaceUpgradeLtmTest" Desc="" >
<TestCase Name="ExecuteInPlaceUpgradeTest">
<TestCase Name="BugRepro">
<TestCase Name="295130">
<Variation Id="1" Desc="Sql - EmptyAlterScript"/>
<Variation Id="2" Desc="Sql - EmptyDatabase"/>
</TestCase>
</TestCase>
</TestCase>
</Module>
дает желаемый, правильный результат :
ExecuteInPlaceUpgradeTest BugRepro 295130
II. Решение XPath 2.0 / XSLT 2.0
//TestCase[Variation]
/ancestor-or-self::TestCase
/@Name/string(.)
Вышеупомянутое выражение XPath 2.0 при оценке на вышеуказанном XML-документе дает именно нужный, правильный результат :
ExecuteInPlaceUpgradeTest BugRepro 295130
Может использоваться в следующем решении XSLT 2.0 :
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="/">
<xsl:sequence select=
"//TestCase[Variation]
/ancestor-or-self::TestCase
/@Name/string(.)
"/>
</xsl:template>
</xsl:stylesheet>