Search code examples
xsltconditional-statementsxslt-1.0apply-templates

Using XSLT 1.0 apply-templates only on certain attribute values


I'm trying to stay away from a procedural approach with this solution and I'm not sure that's possible.

Here's my XML:

<countData>
<count countId="37" name="Data Response 1">
    <year yearId="2013">
        <month monthId="5">
            <day dayId="23" countVal="6092"/>
            <day dayId="24" countVal="6238"/>
            <day dayId="27" countVal="6324"/>
            <day dayId="28" countVal="6328"/>
            <day dayId="29" countVal="3164"/>
        </month>
            <day dayId="23" countVal="7000"/>
            <day dayId="24" countVal="7000"/>
            <day dayId="27" countVal="7000"/>
            <day dayId="28" countVal="7000"/>
            <day dayId="29" countVal="7000"/>
        </month>
    </year>
</count>
<count countId="39" name="Data Response 2">
    <year yearId="2013">
        <month monthId="5">
            <day dayId="23" countVal="675"/>
            <day dayId="24" countVal="709"/>
            <day dayId="27" countVal="754"/>
            <day dayId="28" countVal="731"/>
            <day dayId="29" countVal="377"/>
        </month>
    </year>
</count>

I want to apply-templates (in this example) for all count/@countIds that are 37 or 39. Here's where I am:

    <xsl:template match="/">

    <xsl:apply-templates mode="TimeFrame"/>

</xsl:template>

<xsl:template match="*" mode="TimeFrame">

    <xsl:if test="count[@countId=37] or count[@countId=39]">
        <magic>Only hitting this once for countId 37</magic>
    </xsl:if>

</xsl:template>

I'm going to have quite a few of these templates with "modes" since I'm processing the same response a multitude of different ways.

Not sure how I'm missing the "range" match and only getting 1.

I'm sure it has to do with my "procedural mind". :)

Any help on this would be great!

Thanks,


Solution

  • Your main template, <xsl:template match="/">, runs only once - namely for the <countData> element.

    Which means that you either forgot to recurse:

    <xsl:template match="*" mode="TimeFrame">
    
        <xsl:if test="count[@countId=37] or count[@countId=39]">
            <magic>Only hitting this once for countId 37</magic>
        </xsl:if>
    
        <xsl:apply-templates mode="TimeFrame"/> <!-- ! -->
    
    </xsl:template>
    

    ...or you failed to set the right context for the the main template:

    <xsl:template match="/countData"><!-- ! -->
    
        <xsl:apply-templates mode="TimeFrame"/>
    
    </xsl:template>
    
    <!-- or, alternatively -->
    
    <xsl:template match="/">
    
        <xsl:apply-templates select="countData/*" mode="TimeFrame"/>
    
    </xsl:template>