Происходит следующее: вы сопоставляете любой элемент file
, затем применяете шаблоны к его родительскому элементу dir
, который соответствует шаблону по умолчанию для элементов, который применяет шаблоны ко всем его дочерним элементам, что приводит к другому совпадению того же file
и начала бесконечной рекурсии.
(Обратите внимание, что ваш шаблон для элементов dir
никогда ничего не соответствует, потому что он ищет только элементы dir
, которые являются дочерними для корневого узла, которого у вас нет.)
Следующая таблица стилей:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="dir" mode="path">
<xsl:value-of select="@name" />
<xsl:text>/</xsl:text>
</xsl:template>
<xsl:template match="file">
<xsl:apply-templates select="ancestor::dir" mode="path"/>
<xsl:value-of select="@name" />
</xsl:template>
</xsl:stylesheet>
Создает следующий вывод:
a.txt
aaa/b.txt
aaa/c.txt
bbb/ccc/d.txt
Редактировать: Я думаю, что обычно лучше продвигаться вперед по документу, когда можно избежать возврата. Следующая таблица стилей выдает тот же результат, что и выше, но она более эффективна и элегантна:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="dir">
<xsl:param name="prev" select="''" />
<xsl:apply-templates>
<xsl:with-param name="prev" select="concat($prev, @name, '/')" />
</xsl:apply-templates>
</xsl:template>
<xsl:template match="file">
<xsl:param name="prev" select="''" />
<xsl:value-of select="concat($prev, @name)" />
</xsl:template>
</xsl:stylesheet>