I'm using XSLT 1.0 and I want to find the distinct combinations of multiple attributes, specifically DATE, RUN and REPORT combinations:
<?xml version="1.0" encoding="utf-8"?>
<Report>
<Rows>
<Row DATE="2020-02-01" RUN="1" REPORT="1" OTHER="there are other attributes" />
<Row DATE="2020-02-01" RUN="2" REPORT="1" OTHER="there are other attributes" />
<Row DATE="2020-02-02" RUN="1" REPORT="2" OTHER="there are other attributes" />
<Row DATE="2020-02-02" RUN="1" REPORT="2" OTHER="there are other attributes" />
<Row DATE="2020-02-03" RUN="2" REPORT="1" OTHER="there are other attributes" />
<Row DATE="2020-02-03" RUN="2" REPORT="1" OTHER="there are other attributes" />
<Row DATE="2020-02-03" RUN="1" REPORT="1" OTHER="there are other attributes" />
<Row DATE="2020-02-03" RUN="1" REPORT="1" OTHER="there are other attributes" />
</Rows>
</Report>
What I need to get to is something more like this:
DATE="2020-02-01" RUN="1" REPORT="1"
DATE="2020-02-01" RUN="2" REPORT="1"
DATE="2020-02-02" RUN="1" REPORT="2"
DATE="2020-02-03" RUN="2" REPORT="1"
DATE="2020-02-03" RUN="1" REPORT="1"
I've been successful at using a test for single attribute groupings in the past, this is just the first time that I need to do across multiple columns.
<xsl:if test="not(preceding-sibling::Row[@RUN = current()/@RUN])">
I'm guessing that I'd need something like a key that concatenates the attributes together
<xsl:key name="comboKey" match="/Report/Rows/Row" use="concat(@DATE,'++',@RUN,'++',@REPORT)"/>
But I just can't get my head around the template matching in XSLT 1.0 (apologies for the noobie question, I'm not as familiar with XSLT 1.0, but I'm learning quickly.
Many thanks in advance for any suggestions!
You have tagged your question correctly as Muenchian Grouping
but a comparison with preceding siblings does not attempt to implement it. You should do something like this instead:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:key name="k1" match="Row" use="concat(@DATE, '|', @RUN, '|', @REPORT)" />
<xsl:template match="/Report">
<distinct>
<xsl:for-each select="Rows/Row[count(. | key('k1', concat(@DATE, '|', @RUN, '|', @REPORT))[1]) = 1]">
<Row DATE="{@DATE}" RUN="{@RUN}" REPORT="{@REPORT}"/>
</xsl:for-each>
</distinct>
</xsl:template>
</xsl:stylesheet>
For an explanation of the method (and why your approach is not a good one), read: http://www.jenitennison.com/xslt/grouping/muenchian.html