Это легко. XSLT-процессор выполняет всю рекурсию и циклы за вас, все, что вам нужно сделать, это указать шаблоны для узлов, которые вы хотите обрабатывать.
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<!-- <items> with <item> children becomes <ul> -->
<xsl:template match="items[item]">
<ul>
<xsl:apply-templates select="item" />
</ul>
</xsl:template>
<!-- <items> without <item> children is not handled -->
<xsl:template match="items[not(item)]" />
<!-- <item> with @name becomes <li> -->
<xsl:template match="item[@name]">
<li>
<xsl:value-of select ="@name" />
<xsl:apply-templates select="items" />
</li>
</xsl:template>
<!-- <item> without @name becomes <li>, too -->
<xsl:template match="item[not(@name)]">
<li>
<xsl:value-of select ="id" />
<xsl:apply-templates select="items" />
</li>
</xsl:template>
</xsl:stylesheet>
<xsl:apply-templates>
всегда является рекурсивным / итеративным шагом в XSLT. Он берет любые узлы, которые соответствуют его выражению select
, и находит шаблоны для них.
Ваша задача - создать соответствующее выражение select
, предоставить шаблон для каждого узла, который вы хотите обработать, и иначе уйти с дороги. ;-) Не поддавайтесь желанию втиснуть все в один большой шаблон или используйте <xsl:for-each>
только потому, что это удобно - это не так. Отдельные шаблоны создают более многократно используемый и обслуживаемый, менее глубоко вложенный код, а процессоры XSLT оптимизированы для обработки шаблонов, так что это может быть даже более эффективным подходом.