В дополнение к ответу Габи вы, возможно, захотите знать, что использование call-template и передача одного параметра, узла, это просто обходной способ сказать apply-templates этому узлу (без сопоставления шаблона). Apply-templates - это обычный способ XSLT делать то, что вы делаете, и он менее многословен.
Итак, ваш начальный шаблон вызова
<xsl:if test='siteMapNode'>
<xsl:call-template name='BuildNavList'>
<xsl:with-param name='siteMapNode' select='siteMapNode'/>
</xsl:call-template>
</xsl:if>
может стать
<xsl:apply-templates select='siteMapNode'/>
, который будет применяться к дочерним узлам контекста с именем siteMapNode.
Тогда ваш рекурсивный шаблон становится
<xsl:template match="siteMapNode">
<li>
<a href="{@url}" title="{@description}">
<xsl:value-of select="@title"/>
</a>
<!-- test for siteMapNode element children, if true then recur -->
<xsl:if test='siteMapNode'>
<ul>
<xsl:apply-templates select="siteMapNode" />
</ul>
</xsl:if>
</li>
</xsl:template>
Обратите внимание, что мы удалили много ссылок на параметр $ siteMapNode, поскольку теперь это узел контекста. Обратите внимание также на шаблоны значений атрибутов, используемые для <a href=""
и title="">
. Гораздо лаконичнее и удобочитаемее!
XSLT действительно удобнее, когда вы понимаете и используете его так, как оно было задумано!