Skip to content

Instantly share code, notes, and snippets.

@sntran
Created January 29, 2015 14:50
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save sntran/f6062244e81e131674db to your computer and use it in GitHub Desktop.
Save sntran/f6062244e81e131674db to your computer and use it in GitHub Desktop.
A Calendar in XSLT
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template name="calendar">
<xsl:param name="month" select="substring($page-modified-date, $date-modified-length - 7, 2)" />
<xsl:param name="year" select="substring($page-modified-date, $date-modified-length - 4, 4)" />
<!-- Default to an empty node list. -->
<xsl:param name="events" select="/.." />
<xsl:variable name="month-name">
<xsl:call-template name="thisMonthtoMonth">
<xsl:with-param name="thisMonth" select="$month"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="offset">
<xsl:call-template name="day-of-the-week">
<xsl:with-param name="day" select="1"/>
<xsl:with-param name="month" select="$month"/>
<xsl:with-param name="year" select="$year"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="total-days">
<xsl:call-template name="days-in-month">
<xsl:with-param name="month" select="$month"/>
<xsl:with-param name="year" select="$year"/>
</xsl:call-template>
</xsl:variable>
<div class="calendar-month" id="month-{($year - 1) * 12 + $month}">
<table summary="Calendar for {$month-name}, {$year}">
<caption>
<xsl:value-of select="$month-name"/>
<xsl:text> </xsl:text>
<xsl:value-of select="$year"/>
</caption>
<tr class="weekdays">
<th abbr="Sunday">Sun</th>
<th abbr="Monday">Mon</th>
<th abbr="Tuesday">Tue</th>
<th abbr="Wednesday">Wed</th>
<th abbr="Thursday">Thu</th>
<th abbr="Friday">Fri</th>
<th abbr="Saturday">Sat</th>
</tr>
<xsl:call-template name="calendar-week">
<xsl:with-param name="offset" select="$offset"/>
<xsl:with-param name="total" select="$total-days"/>
<xsl:with-param name="events" select="$events"/>
</xsl:call-template>
</table>
</div></xsl:template>
<xsl:template name="calendar-week">
<xsl:param name="offset" select="0" />
<xsl:param name="total" />
<xsl:param name="week" select="1" />
<xsl:param name="day" select="1" />
<xsl:param name="events" select="/.." />
<tr>
<xsl:call-template name="calendar-day">
<xsl:with-param name="day" select="$day - $offset"/>
<xsl:with-param name="total" select="$total"/>
<xsl:with-param name="events" select="$events"/>
</xsl:call-template>
</tr>
<xsl:if test="$week &lt; 6">
<xsl:call-template name="calendar-week">
<xsl:with-param name="offset" select="$offset"/>
<xsl:with-param name="total" select="$total"/>
<xsl:with-param name="week" select="$week + 1"/>
<xsl:with-param name="day" select="$week * 7 + 1"/>
<xsl:with-param name="events" select="$events"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
<!-- Recursively prints the date of a particular month. -->
<xsl:template name="calendar-day">
<xsl:param name="count">1</xsl:param>
<xsl:param name="day" />
<xsl:param name="total" />
<xsl:param name="events" select="/.." />
<xsl:variable name="event" select="$events[substring(./title, 9, 2) = $day]" />
<xsl:choose>
<xsl:when test="($day &lt; 1) or ($day &gt; $total)">
<!-- Print an empty slot if the day argument is not on this day of the week -->
<td class="empty"><xsl:text disable-output-escaping="yes">&amp;nbsp;</xsl:text></td>
</xsl:when>
<xsl:otherwise>
<td>
<xsl:choose>
<xsl:when test="$event">
<!-- Label to trigger corresponding radio input if any,
which in turns toggle the corresponding event -->
<label class="icon-circle has-event" for="event-{$event/title}">
<span class="date"><xsl:value-of select="$day"/></span>
</label>
</xsl:when>
<xsl:otherwise>
<label for="event-{substring($events/title, 1, 7)}-{$day}">
<span class="date"><xsl:value-of select="$day"/></span>
</label>
</xsl:otherwise>
</xsl:choose>
</td>
</xsl:otherwise>
</xsl:choose>
<xsl:if test="$count &lt; 7">
<xsl:call-template name="calendar-day">
<xsl:with-param name="count" select="$count + 1" />
<xsl:with-param name="day" select="$day + 1" />
<xsl:with-param name="total" select="$total"/>
<xsl:with-param name="events" select="$events"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
<!-- HELPERS -->
<!-- Given the year, month, and day, return an integer for the day of the week in the range of 0-6, where 0=Sunday -->
<xsl:template name="day-of-the-week">
<xsl:param name="year" />
<xsl:param name="month" />
<xsl:param name="day" />
<xsl:variable name="a" select="floor((14 - $month) div 12)"/>
<xsl:variable name="y" select="$year - $a"/>
<xsl:variable name="m" select="$month + 12 * $a - 2"/>
<xsl:value-of select="($day + $y + floor($y div 4) - floor($y div 100)
+ floor($y div 400) + floor((31 * $m) div 12)) mod 7"/>
</xsl:template>
<!-- Given a month and a year, determine the number of days in the month. -->
<xsl:template name="days-in-month">
<xsl:param name="month" />
<xsl:param name="year" />
<xsl:choose>
<xsl:when test="$month = 2 and
not($year mod 4) and
($year mod 100 or not($year mod 400))">
<xsl:value-of select="29"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of
select="substring('312831303130313130313031',
2 * $month - 1,2)"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment