Это преобразование XSLT 2.0 :
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/*">
<root>
<xsl:call-template name="directDependents"/>
</root>
</xsl:template>
<xsl:template name="directDependents">
<xsl:param name="pCore" as="element()*"/>
<xsl:variable name="vNewDependents" select=
"/*/element
[not(. intersect $pCore)
and
not(tokenize(@depends, ',')[not(. = $pCore/@name)])
]
"/>
<xsl:if test="$vNewDependents">
<xsl:sequence select="$vNewDependents"/>
<xsl:call-template name="directDependents">
<xsl:with-param name="pCore" select="$pCore | $vNewDependents"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
при применении к (второму) предоставленному документу XML :
<root>
<element name="a" depends="b" />
<element name="b" depends="c" />
<element name="c" />
</root>
дает желаемый, правильный результат :
<root>
<element name="c"/>
<element name="b" depends="c"/>
<element name="a" depends="b"/>
</root>
Обновление : Вот еще «XSLT 2.0 ищет решение» (не проверено - исправит все ошибки, когда я вернусь домой):
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:my="my:my" exclude-result-prefixes="my">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/*">
<root>
<xsl:sequence select="my:directDependents(/..)"/>
</root>
</xsl:template>
<xsl:function name="my:directDependents">
<xsl:param name="pCore" as="element()*"/>
<xsl:sequence select=
"for $vNewDependents in
/*/element
[not(. intersect $pCore)
and
not(tokenize(@depends, ',')[not(. = $pCore/@name)])
]
return
if($vNewDependents)
then
(
$vNewDependents,
my:directDependents($pCore | $vNewDependents)
)
else ()
"/>
</xsl:function>
</xsl:stylesheet>