Hi Ragulf,
I have nothing against key's if that is a solution, I have just
never worked with key's in XSL, and is therefore not proficient in
this, but if a solutions with key's is easier, then I will very much
want to learn.
If I understand what you're doing correctly, the key-based (Muenchian)
method would look something like:
<xsl:key name="ElemsByDate"
match="Elem[(_at_)Type = '2' or @Type = '4']"
use="@Date" />
<xsl:key name="ElemsByDateAndID"
match="Elem[(_at_)Type = '2' or @Type = '4']"
use="concat(@Date, ':', ElemID)" />
<xsl:template match="/">
<output>
<!-- select unique Elems by Date -->
<xsl:for-each select="/root/Elements/Elem
[generate-id(key('ElemsByDate', @Date)[1]) =
generate-id(.)]">
<!-- sort by Date -->
<xsl:sort select="substring(@Date,$YearPos,4)" order="descending"/>
<xsl:sort select="substring(@Date,$MonthPos,2)" order="descending"/>
<xsl:sort select="substring(@Date,$DayPos,2)" order="descending"/>
<OutputByDate>
<Date><xsl:value-of select="@Date" /></Date>
<!-- select unique Elems by Date and ID -->
<xsl:for-each select="key('ElemsByDate', @Date)
[generate-id(key('ElemsByDateAndID',
concat(@Date, ':',
ElemID))[1]) =
generate-id(.)]">
<OutputElem>
<ID><xsl:value-of select="ElemID" /></ID>
<xsl:for-each select="key('ElemsByDateAndID',
concat(@Date, ':', ElemID))">
<OutputElemSub>
<Type><xsl:value-of select="@Type" /></Type>
<Name><xsl:value-of select="Name" /></Name>
</OutputElemSub>
</xsl:for-each>
</OutputElem>
</xsl:for-each>
</OutputByDate>
</xsl:for-each>
</output>
</xsl:template>
Note that the keys do the filtering of the <Elem> elements so that the
groups only contain those whose Type is 2 or 4. You won't get a group
appearing if it only contains <Elem> elements whose Type is 1 or 3.
The XSLT 2.0 version is similar, but of course doesn't require keys,
and it might help you understand the logic of the XSLT 1.0 version
above:
<xsl:template match="/">
<output>
<xsl:for-each-group select="/root/Elements/Elem
[(_at_)Type = '2' or @Type = '4']"
group-by="@Date">
<xsl:sort select="substring(@Date,$YearPos,4)" order="descending"/>
<xsl:sort select="substring(@Date,$MonthPos,2)" order="descending"/>
<xsl:sort select="substring(@Date,$DayPos,2)" order="descending"/>
<OutputByDate>
<Date><xsl:value-of select="@Date" /></Date>
<xsl:for-each-group select="current-group()"
group-by="ElemID">
<OutputElem>
<ID><xsl:value-of select="ElemID" /></ID>
<xsl:for-each select="current-group()">
<OutputElemSub>
<Type><xsl:value-of select="@Type" /></Type>
<Name><xsl:value-of select="Name" /></Name>
</OutputElemSub>
</xsl:for-each>
</OutputElem>
</xsl:for-each-group>
</OutputByDate>
</xsl:for-each-group>
</output>
</xsl:template>
Cheers,
Jeni
---
Jeni Tennison
http://www.jenitennison.com/