Search code examples
xslt-1.0nested-loops

Count the number of nested child nodes


I want to find the number of RegisterValueData elements inside the below structure for all the NewConsumptionData and RegisterConsumptionData elements, so a single figure.

<ConsumptionData>
<NewConsumptionData>
    <FromDate>2021-02-02T00:00:00</FromDate>
    <RegistersValues>
        <RegisterConsumptionData>
            <Timeframe>TOTAL_HOUR</Timeframe>
            <Values>
                <RegisterValueData>
                    <Quality>NONVALIDATED</Quality>
                </RegisterValueData>
                <RegisterValueData>
                    <Quality>VALIDATED</Quality>
                </RegisterValueData>
            </Values>
        </RegisterConsumptionData>
        <RegisterConsumptionData>
            <Timeframe>TOTAL_HOUR</Timeframe>
            <Values>
                <RegisterValueData>
                    <Quality>NONVALIDATED</Quality>
                </RegisterValueData>
                <RegisterValueData>
                    <Quality>VALIDATED</Quality>
                </RegisterValueData>
            </Values>
        </RegisterConsumptionData>
    </RegistersValues>
</NewConsumptionData>
<NewConsumptionData>
    <FromDate>2021-02-02T00:00:00</FromDate>
    <RegistersValues>
        <RegisterConsumptionData>
            <Timeframe>TOTAL_HOUR</Timeframe>
            <Values>
                <RegisterValueData>
                    <Quality>NONVALIDATED</Quality>
                </RegisterValueData>
                <RegisterValueData>
                    <Quality>VALIDATED</Quality>
                </RegisterValueData>
            </Values>
        </RegisterConsumptionData>
        <RegisterConsumptionData>
            <Timeframe>TOTAL_HOUR</Timeframe>
            <Values>
                <RegisterValueData>
                    <Quality>NONVALIDATED</Quality>
                </RegisterValueData>
                <RegisterValueData>
                    <Quality>VALIDATED</Quality>
                </RegisterValueData>
            </Values>
        </RegisterConsumptionData>
    </RegistersValues>
</NewConsumptionData>

What seems simple I cannot get my head around this. I am trying a recursive function (If that's the right way) but not sure how to set up the parameters and prevent it looping indefinitely.


Solution

  • You can easily use the count() function to count child or descendant nodes:

    XSLT 1.0

    <xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    
    <xsl:template match="/">
        <result>
            <xsl:value-of select="count(//RegisterValueData)" />
        </result>   
    </xsl:template>
    
    </xsl:stylesheet>
    

    or a little more efficiently:

    <xsl:template match="/ConsumptionData">
        <result>
            <xsl:value-of select="count(NewConsumptionData/RegistersValues/RegisterConsumptionData/Values/RegisterValueData)" />
        </result>   
    </xsl:template>
    

    Result

    <?xml version="1.0" encoding="UTF-8"?>
    <result>8</result>