I'm seeking to match the first item in a list but also include the first item in a full list without calling the first item template
given an xml file:
<page>
<set>
<item><name>One</name></item>
<item><name>Two</name></item>
</set>
</page>
and xslt
<xsl:template match="page">
<xsl:apply-templates select="set/item[1]"/>
<xsl:apply-templates select="set"/>
</xsl:template>
<xsl:template match="set">
<xsl:apply-templates select="item"/>
</xsl:template>
<!-- match only the first item -->
<xsl:template match="set/item[1]">
FIZZ
</xsl:template>
<!-- match all the items including the first one -->
<xsl:template match="item">
BUZZ
</xsl:template>
My goal is to get FIZZ BUZZ BUZZ. But I get FIZZ FIZZ BUZZ. suggesting that the set/item[1]
is called from the <xsl:apply-templates select="item"/>
im ok with dropping the set
if needed so the xml would be
<item><name>One</name></item>
<item><name>One</name></item>
It's similar but different to the following question: xslt matching first x items of filtered result set
Your initial template:
<xsl:template match="page">
<xsl:apply-templates select="set/item[1]"/>
<xsl:apply-templates select="set"/>
</xsl:template>
applies templates to the first item twice: once directly, and once as part of set
.
Every time you apply templates to a set of nodes, the processor searches for the template that best matches each node in the selected set and applies it. So a template matching set/item[1]
will be chosen for the first item
every time it is processed.
If you want different processing for the first item
only once, and then include it with the rest of the set for further processing, you will need to use some other method - e.g. a different mode:
<xsl:template match="page">
<xsl:apply-templates select="set/item[1]" mode="first"/>
<xsl:apply-templates select="set"/>
</xsl:template>
<xsl:template match="item" mode="first">
FIZZ
</xsl:template>
<xsl:template match="item">
BUZZ
</xsl:template>