Reputation: 3305
Below I have an XML file with a list of events. What I want to achieve is to group them by City with New York always being on top of the list. Other cities are supposed to be sorted by name and then events sorted by date. I can do that all (with some hack) besides sorting other cities.
<Events>
<Event id="1">
<Title>Concert1</Title>
<Date>2017-01-05 12:00</Date>
<City>Seattle</City>
</Event>
<Event id="2">
<Title>Concert2</Title>
<Date>2017-01-05 11:00</Date>
<City>Los Angeles</City>
</Event>
<Event id="3">
<Title>Concert3</Title>
<Date>2017-01-05 14:00</Date>
<City>New York</City>
</Event>
<Event id="4">
<Title>Concert4</Title>
<Date>2017-01-05 19:00</Date>
<City>Austin</City>
</Event>
<Event id="5">
<Title>Concert5</Title>
<Date>2017-01-05 15:00</Date>
<City>New York</City>
</Event>
<Event id="6">
<Title>Concert6</Title>
<Date>2017-01-05 12:00</Date>
<City>Austin</City>
</Event>
</Events>
And an XLS (1.0) file that uses muenchian grouping to group events by City. Also in order to extract New York to the top of the list, I made 2 separate for-each loops:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" encoding="UTF-8" indent="yes"/>
<xsl:key name="groups" match="City" use="."/>
<xsl:template match="/Events">
<xsl:apply-templates select="Event/City[generate-id() = generate-id(key('groups', .)[1])]"/>
</xsl:template>
<!-- NEW YORK -->
<xsl:template match="City[text()='New York']">
<xsl:variable name="currentGroup" select="."/>
<b><xsl:value-of select="$currentGroup"/></b><br/>
<xsl:for-each select="key('groups', $currentGroup)">
<xsl:sort select="../Date"/>
<i>+ <xsl:value-of select="../Date"/> <xsl:value-of select="../Title"/></i><br/>
</xsl:for-each>
</xsl:template>
<!-- OTHER CITIES -->
<xsl:template match="City[text()!='New York']">
<xsl:variable name="currentGroup" select="."/>
<b><xsl:value-of select="$currentGroup"/></b><br/>
<xsl:for-each select="key('groups', $currentGroup)">
<xsl:sort select="../Date"/>
<i>+ <xsl:value-of select="../Date"/> <xsl:value-of select="../Title"/></i><br/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Currently the "other cities" are in a input order. How do I group and sort above XML so that the HTML result would be like this:
New York
+ 14:00 Concert3
+ 15:00 Concert5
Austin
+ 12:00 Concert6
+ 19:00 Concert4
Los Angeles
+ 11:00 Concert2
Seattle
+ 12:00 Concert1
Upvotes: 0
Views: 210
Reputation: 167716
I am not sure why your posted code would output "New York" events first but it should be easy with
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" encoding="UTF-8" indent="yes"/>
<xsl:key name="groups" match="City" use="."/>
<xsl:template match="/Events">
<xsl:apply-templates select="key('groups', 'New York')[1]"/>
<xsl:apply-templates select="Event/City[generate-id() = generate-id(key('groups', .)[1])][. != 'New York']">
<xsl:sort select="."/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="City">
<xsl:variable name="currentGroup" select="."/>
<b><xsl:value-of select="$currentGroup"/></b><br/>
<xsl:for-each select="key('groups', $currentGroup)">
<xsl:sort select="../Date"/>
<i>+ <xsl:value-of select="../Date"/> <xsl:value-of select="../Title"/></i><br/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Upvotes: 2