Search
Web Braintrove
Site Navigation
Home
Products
Tags
Levels
Dates
Authors
5 MOST RECENT
Locate the Design Checker Task Pane in InfoPath 2010
Locate Conditional Formatting and Custom Validation in InfoPath 2010
Conditionally Display Different Values In a Single Expression Box
Create a Button With a Blank Label
Create Shared Rules
5 MOST POPULAR
Access a Method in a Master Page with Code-Behind
Pass Query String Parameters to an ASP.NET Xml Control
Prevent Namespace Prefixes from Being Copied to the Output
Create Groups in a Drop-Down List Box
Configure IIS 7 for Custom Error Pages
5 MOST FORGOTTEN
Install Windows 7 Beta onto a Virtual Machine
Group Dates by Year, Month and Day
Configure Lab Color Mode Defaults for Braintrove Articles
Create a Monochromatic Dream Text Effect Using Styles
Combine Multiple Sums Into a Single Function
Books
XSLT and XPath On The Edge, Unlimited Edition
HTML Utopia : Designing Without Tables Using CSS
Extreme Programming with Ant: Building and Deploying Java Applications with JSP, EJB, XSLT, XDoclet, and JUnit
Oracle HTML DB Handbook
HTML & XHTML: The Definitive Guide
Magazines
Inside Web Development
Visual Basic & Net Journal
Asp.netpro
SQL Server Magazine
.net
Microsoft MVP
This article has been viewed 721 times.

Group Dates by Year, Month and Day

Page 1 of 2
Written by Gregory Scot Collins
Thursday, 17 August 2006, 1:35 AM
This article has been tested to work with the following products and versions. No guarantee of compatibility, with or without modification, is offered for products or versions other than those listed.
When working with lists of date-oriented items, such as calendar events, birthdays, etc., it often becomes desirable to group list items by their date. This article focuses on grouping by date parts, but could easily be altered to group by any kind of data. We will present a short list of holiday calendar events grouped by year, month and then day.

Create the Events.xml file

We need a simple XML file to transform that contains our list of holiday calendar events. Copy the contents of Listing 1 into a text editor, and then save the file as Events.xml.

Create the Calendar.xsl file

Now we need a transform to group the list of holiday events by date. This transform will first identify a unique set of years from the event dates. Below each year we will display a unique set of months for that year, utilizing a named template to display the full name of the month. Below each month we could simply list event details preceded by the day, but instead we will once more group by a unique set of days before listing the event details.
Copy the contents of Listing 2 into a text editor, and then save the file as Calendar.xsl. Be sure to save it in the same folder as the Events.xml file.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 
<xsl:output method="html" indent="no"/>
 
<xsl:template match="Events">
    <style>.indent {margin-left:20px;}</style>
    <div>Holiday Event Calendar:</div><br/>
    <xsl:apply-templates select="Event" mode="Year">
        <xsl:sort select="@date" data-type="text" order="ascending"/>
    </xsl:apply-templates>
</xsl:template>
 
<xsl:template match="Event" mode="Year">
    <xsl:if test="not(preceding-sibling::Event[substring(@date,1,4) = substring(current()/@date,1,4)])">
        <div><xsl:value-of select="substring(@date,1,4)"/></div>
        <div class="indent">
            <xsl:apply-templates select="../Event[substring(@date,1,4) = substring(current()/@date,1,4)]" mode="Month">
                <xsl:sort select="@date" data-type="text" order="ascending"/>
            </xsl:apply-templates>
        </div>
    </xsl:if>
</xsl:template>
 
<xsl:template match="Event" mode="Month">
    <xsl:if test="not(preceding-sibling::Event[substring(@date,1,7) = substring(current()/@date,1,7)])">
        <div>
            <xsl:call-template name="MonthName">
                <xsl:with-param name="MONTH" select="substring(@date,6,2)"/>
            </xsl:call-template>
        </div>
        <div class="indent">
            <xsl:apply-templates select="../Event[substring(@date,1,7) = substring(current()/@date,1,7)]" mode="Day">
                <xsl:sort select="@date" data-type="text" order="ascending"/>
            </xsl:apply-templates>
        </div>
    </xsl:if>
</xsl:template>
 
<xsl:template match="Event" mode="Day">
    <xsl:if test="not(preceding-sibling::Event[@date = current()/@date])">
        <div><xsl:value-of select="number(substring(@date,9,2))"/></div>
        <div class="indent">
            <xsl:apply-templates select="../Event[@date = current()/@date]" mode="Details">
                <xsl:sort select="@date" data-type="text" order="ascending"/>
            </xsl:apply-templates>
        </div>
    </xsl:if>
</xsl:template>
 
<xsl:template match="Event" mode="Details">
    <div><xsl:value-of select="concat(@description, ' (', @location, ')')"/></div>
</xsl:template>
 
<xsl:template name="MonthName">
    <xsl:param name="MONTH"/>
    <xsl:choose>
        <xsl:when test="$MONTH = '01'">January</xsl:when>
        <xsl:when test="$MONTH = '02'">February</xsl:when>
        <xsl:when test="$MONTH = '03'">March</xsl:when>
        <xsl:when test="$MONTH = '04'">April</xsl:when>
        <xsl:when test="$MONTH = '05'">May</xsl:when>
        <xsl:when test="$MONTH = '06'">June</xsl:when>
        <xsl:when test="$MONTH = '07'">July</xsl:when>
        <xsl:when test="$MONTH = '08'">August</xsl:when>
        <xsl:when test="$MONTH = '09'">September</xsl:when>
        <xsl:when test="$MONTH = '10'">October</xsl:when>
        <xsl:when test="$MONTH = '11'">November</xsl:when>
        <xsl:when test="$MONTH = '12'">December</xsl:when>
    </xsl:choose>
</xsl:template>
 
</xsl:stylesheet>
Listing 2. The Calendar.xsl file.
Bookmark this Article
StumbleUpon  Stumble It!
Digg  Digg It!
del.icio.us  del.icio.us
List of Figures
Listing 1 - The Events.xml file.
Listing 2 - The Calendar.xsl file.
Listing 3 - Filtering works correctly but does not account for date parts.
Listing 4 - Filtering fails because the substring() function prevents the preceding-sibling axis from working correctly.
Article Tags
Great Deals
TigerDirect Exclusive Deals, Limited Time Offers, Act Now And Save!
Find all current special offers on Adobe products.
Try SugarSync Free!
Join WebHost4Life.com
TigerDirect
Computers4SURE (4SURE.com - An Office Depot Co.)
Copyright © 2006-2010 Braintrove. All rights reserved. Braintrove, braintrove.com, and the Braintrove logo are trademarks of Gregory Scot Collins in the United States and/or other countries. The names of actual companies and products mentioned herein may be the trademarks of their respective owners. Any rights not expressly granted herein are reserved.