This is how you can do it. It is not easy and straightforward I'm afraid, though. The way your input XMl is structured makes it harder to access the relevant nodes.
For example, in several places you need to access nodes that are naturally not in the context. To adress this I use variables and parameters.
But it is quite generic, i.e. you can process an arbitrary number of DATASETS
, Regions
or Districts
. It creates an HTML table to display the counts.
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<xsl:element name="html">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match="DATASETLIST">
<xsl:element name="head">
<xsl:element name="title">
<xsl:text>DATASET counts</xsl:text>
</xsl:element>
</xsl:element>
<xsl:element name="body">
<xsl:element name="table">
<xsl:attribute name="border">1</xsl:attribute>
<xsl:call-template name="tbl"/>
</xsl:element>
</xsl:element>
</xsl:template>
<xsl:template name="tbl">
<xsl:param name="regions" select="distinct-values(DATASET/ROW/Region)"/>
<xsl:param name="rows" select="DATASET/ROW"/>
<xsl:param name="datasets" select="DATASET"/>
<!--header row-->
<xsl:element name="tr">
<xsl:element name="th"/>
<xsl:for-each select="$datasets">
<xsl:element name="th">
<xsl:value-of select="@entity"/>
</xsl:element>
</xsl:for-each>
</xsl:element>
<!--Totals row-->
<xsl:element name="tr">
<xsl:element name="td">
<xsl:element name="b">
<xsl:text>Total</xsl:text>
</xsl:element>
</xsl:element>
<xsl:for-each select="$datasets">
<xsl:element name="td">
<xsl:value-of select="count(ROW)"/>
</xsl:element>
</xsl:for-each>
</xsl:element>
<xsl:element name="tr"/>
<!--region rows-->
<xsl:for-each select="$regions">
<xsl:variable name="region" select="."/>
<xsl:element name="tr">
<xsl:element name="td">
<xsl:element name="b">
<xsl:value-of select="."/>
</xsl:element>
</xsl:element>
<xsl:for-each select="$datasets">
<xsl:element name="td">
<xsl:value-of select="count(ROW/Region[.=$region])"/>
</xsl:element>
</xsl:for-each>
</xsl:element>
<!--district rows-->
<xsl:for-each select="distinct-values($rows[Region=$region]/District)">
<xsl:variable name="district" select="."/>
<xsl:element name="tr">
<xsl:element name="td">
<xsl:value-of select="."/>
</xsl:element>
<xsl:for-each select="$datasets">
<xsl:element name="td">
<xsl:value-of select="count(ROW/District[.=$district])"/>
</xsl:element>
</xsl:for-each>
</xsl:element>
</xsl:for-each>
<xsl:element name="tr"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>