Newer
Older
XML / html_calendar.xsl
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

	<xsl:output method="html" encoding="ISO-8859-1" media-type="text/html" doctype-public="-//W3C//DTD HTML 4.01//EN" doctype-system="http://www.w3.org/TR/html4/strict.dtd" />

	<xsl:param name="standalone">yes</xsl:param>

	<xsl:param name="department">INFO</xsl:param>

	<xsl:param name="paper"/>

	<xsl:strip-space elements="*"/>

	<xsl:variable name="rows-per-week">
		<xsl:value-of select="/calendar/@rows-per-week"/>
		<xsl:if test="not(/calendar/@rows-per-week)">2</xsl:if>
	</xsl:variable>

	<xsl:variable name="number-of-weeks">
		<xsl:value-of select="/calendar/@number-of-weeks"/>
		<xsl:if test="not(/calendar/@number-of-weeks)">13</xsl:if>
	</xsl:variable>
	
	<!--
		This is the number of columns in the output table.
	 -->
	<xsl:variable name="number-of-columns">11</xsl:variable>
	

	<xsl:template match="/">
		<xsl:choose>
			<xsl:when test="$standalone = 'yes'">
				<HTML>
					<HEAD>
						<TITLE>
							<xsl:apply-templates select="calendar/paper"/>
							<xsl:text> Paper Schedule, </xsl:text>
							<xsl:apply-templates select="calendar/period"/>
							<xsl:text> </xsl:text>
							<xsl:apply-templates select="calendar/year"/>
						</TITLE>
						<xsl:element name="LINK">
							<xsl:attribute name="REL">
								<xsl:text>Stylesheet</xsl:text>
							</xsl:attribute>
							<xsl:attribute name="HREF">
								<xsl:text>http://info-nts-12.otago.ac.nz/</xsl:text>
								<xsl:value-of select="$department"/>
								<xsl:value-of select="$paper"/>
								<xsl:text>/db_styles.css</xsl:text>
							</xsl:attribute>
							<xsl:attribute name="TYPE">
								<xsl:text>text/css</xsl:text>
							</xsl:attribute>
						</xsl:element> <!-- LINK -->
						<xsl:element name="STYLE">
							<xsl:attribute name="TYPE">
								<xsl:text>text/css</xsl:text>
							</xsl:attribute>
							<xsl:attribute name="TITLE">
								<xsl:text>text/css</xsl:text>
							</xsl:attribute>
							<xsl:comment>
								<xsl:text>TABLE { border-collapse: collapse; }</xsl:text>
								<xsl:text>THEAD, TBODY, TFOOT { border: 2px solid #777777; }</xsl:text>
								<xsl:text>TH, TD { border: 1px solid #777777; }</xsl:text>
							</xsl:comment>
						</xsl:element> <!-- STYLE -->
					</HEAD>
					<BODY>
						<xsl:apply-templates/>
						<HR />
						<ADDRESS>
							<xsl:apply-templates select="calendar/@cvs-id"/>
						</ADDRESS>
					</BODY>
				</HTML>
			</xsl:when>
			<xsl:otherwise>
				<xsl:apply-templates/>
			</xsl:otherwise>
		</xsl:choose>
	</xsl:template>
	
	<xsl:template match="calendar">
		<!-- Page heading. -->
		<H2>
			<xsl:apply-templates select="paper"/>
			<xsl:text> Paper Calendar, </xsl:text>
			<xsl:apply-templates select="period"/>
			<xsl:text> </xsl:text>
			<xsl:apply-templates select="year"/>
		</H2>
		
		<!-- The calendar itself. -->
		<DIV CLASS="sans">
			<TABLE CLASS="small" SUMMARY="Paper calendar with relevant links" CELLSPACING="0">
				<!--
					I was going to generate COL elements here, but they
					don't seem to be supported by all browsers. Damn. The same
					applies for THEAD/TFOOT/TBODY, but I may as well leave them in
					for the browsers that do support them.
				-->
				<THEAD>
					<xsl:apply-templates select="header"/>
				</THEAD>
				<TFOOT>
					<xsl:apply-templates select="footer"/>
				</TFOOT>
				<TBODY>
					<xsl:apply-templates select="body"/>
				</TBODY>
			</TABLE>
		</DIV>
	</xsl:template>
	
	<!--
		Header/footer rows for the calendar table. To get proper table
		headings/footings, use HEADING/FOOTING. For other text, use NOTE.
	-->
	<xsl:template match="header|footer">
		<TR>
			<xsl:apply-templates/>
		</TR>
	</xsl:template>
	
	<!--
		A table heading or footing, coloured appropriately, bolded,
		centered, etc.
	-->
	<xsl:template match="heading|footing">
		<TH>
			<xsl:if test="@columns">
				<xsl:attribute name="COLSPAN">
					<xsl:value-of select="@columns"/>
				</xsl:attribute>
			</xsl:if>
			<xsl:apply-templates/>
		</TH>
	</xsl:template>
	
	<!--
		A miscellaneous piece of text to be inserted somewhere in the
		calendar table.
	-->
	<xsl:template match="note">
		<TD>
			<xsl:if test="@columns">
				<xsl:attribute name="COLSPAN">
					<xsl:value-of select="@columns"/>
				</xsl:attribute>
			</xsl:if>
			<xsl:apply-templates/>
		</TD>
	</xsl:template>
	
	<!--
		A week in the calendar. Each week has an associated number
		(automatically generated) and a date range, and spans some
		defined number of rows (default 2). The week number and
		date range are only generated for the first of these rows.
	-->
	<xsl:template match="week">
		<xsl:variable name="current" select="@current"/>
		<xsl:for-each select="row">
			<TR>
				<!-- Output the week number and dates columns. -->
				<xsl:if test="position() = 1">
					<!-- Week number, first row only. -->
					<TD>
						<xsl:attribute name="CLASS">
							<xsl:choose>
								<xsl:when test="$current = 'yes'">red-center</xsl:when>
								<xsl:otherwise>white-center</xsl:otherwise>
							</xsl:choose>
						</xsl:attribute>
						<xsl:attribute name="ROWSPAN">
							<xsl:value-of select="$rows-per-week"/>
						</xsl:attribute>
						<xsl:number value="1 + count(preceding::week[not(@holiday)])"/>
					</TD>
	
					<!-- Date range, first row only. -->
					<TD CLASS="white-center">
						<xsl:attribute name="ROWSPAN">
							<xsl:value-of select="$rows-per-week"/>
						</xsl:attribute>
						<xsl:apply-templates select="../dates"/>
					</TD>
				</xsl:if>

				<!--
					Apply each of the sub-templates in the correct order.
					Missing elements don't matter.
				-->
				<xsl:apply-templates select="section"/>
				<xsl:apply-templates select="lecture"/>
				<xsl:apply-templates select="reading"/>
				<xsl:apply-templates select="laboratory"/>
				<xsl:apply-templates select="tutorial"/>
				<xsl:apply-templates select="assessment"/>
			</TR>
		</xsl:for-each>
	</xsl:template>
	
	<!--
		Weeks that are holidays have no week number or date range, just
		a text description.
	-->
	<xsl:template match="week[@holiday]">
		<TR>
			<TD CLASS="blue-ou-center" STYLE="border: 2px solid #777777;">
				<xsl:attribute name="COLSPAN">
					<xsl:value-of select="$number-of-columns"/>
				</xsl:attribute>
				<STRONG CLASS="large"><EM><xsl:apply-templates/></EM></STRONG>
			</TD>
		</TR>
	</xsl:template>
	
	<!--
		Output the date range for a week. We need a separate template
		because it's likely to have embedded ENDASH elements.
	-->
	<xsl:template match="dates">
		<xsl:apply-templates/>
	</xsl:template>
	
	<!--
		Output a calendar entry for a lecture. Note that lectures are
		always assumed to span a single row. Lectures are automatically
		numbered.
	-->
	<xsl:template match="lecture[node() and not(@holiday)]">
		<TD CLASS="ltgrey-center">
			<xsl:number value="1 + count(preceding::lecture[node() and not(@holiday)])"/>
		</TD>
		<TD CLASS="ltgrey-left" ROWSPAN="1">
			<xsl:apply-templates/>
		</TD>
	</xsl:template>
	
	<!--
		Output a calendar entry for a lecture that occurs on a holiday.
		These aren't numbered.
	-->
	<xsl:template match="lecture[@holiday]">
		<TD CLASS="blue-ou-center" COLSPAN="2">
			<STRONG><EM><xsl:apply-templates/></EM></STRONG>
		</TD>
	</xsl:template>
	
	<!--
		Output an empty lecture cell.
	-->
	<xsl:template match="lecture[not(node())]">
		<TD CLASS="medgrey-center" COLSPAN="2">
			<xsl:text disable-output-escaping="yes">&amp;nbsp;</xsl:text>
		</TD>
	</xsl:template>
	
	<!--
		Output a calendar entry for a laboratory. Laboratories are
		automatically numbered.
	-->
	<xsl:template match="laboratory[node()]">
		<xsl:variable name="num-rows">
			<xsl:value-of select="@rows"/>
			<xsl:if test="not(@rows)">
				<xsl:value-of select="$rows-per-week"/>
			</xsl:if>
		</xsl:variable>
		<TD CLASS="ltblue-center">
			<xsl:attribute name="ROWSPAN">
				<xsl:value-of select="$num-rows"/>
			</xsl:attribute>
			<xsl:number value="1 + count(preceding::laboratory[node()])"/>
		</TD>
		<TD CLASS="ltblue-center">
			<xsl:attribute name="ROWSPAN">
				<xsl:value-of select="$num-rows"/>
			</xsl:attribute>
			<xsl:apply-templates/>
		</TD>
	</xsl:template>
	
	<!--
		Output an empty laboratory cell.
	-->
	<xsl:template match="laboratory[not(node())]">
		<TD CLASS="medgrey-center" COLSPAN="2">
			<xsl:attribute name="ROWSPAN">
				<xsl:value-of select="@rows"/>
				<xsl:if test="not(@rows)">
					<xsl:value-of select="$rows-per-week"/>
				</xsl:if>
			</xsl:attribute>
			<xsl:text disable-output-escaping="yes">&amp;nbsp;</xsl:text>
		</TD>
	</xsl:template>
	
	<!--
		Output a calendar entry for a tutorial. Tutorials are
		automatically numbered.
	-->
	<xsl:template match="tutorial[node()]">
		<xsl:variable name="num-rows">
			<xsl:value-of select="@rows"/>
			<xsl:if test="not(@rows)">
				<xsl:value-of select="$rows-per-week"/>
			</xsl:if>
		</xsl:variable>
		<TD CLASS="medgreen-center">
			<xsl:attribute name="ROWSPAN">
				<xsl:value-of select="$num-rows"/>
			</xsl:attribute>
			<xsl:number value="1 + count(preceding::tutorial[node()])"/>
		</TD>
		<TD CLASS="medgreen-center">
			<xsl:attribute name="ROWSPAN">
				<xsl:value-of select="$num-rows"/>
			</xsl:attribute>
			<xsl:apply-templates/>
		</TD>
	</xsl:template>
	
	<!--
		Output an empty tutorial cell.
	-->
	<xsl:template match="tutorial[not(node())]">
		<TD CLASS="medgrey-center" COLSPAN="2">
			<xsl:attribute name="ROWSPAN">
				<xsl:value-of select="@rows"/>
				<xsl:if test="not(@rows)">
					<xsl:value-of select="$rows-per-week"/>
				</xsl:if>
			</xsl:attribute>
			<xsl:text disable-output-escaping="yes">&amp;nbsp;</xsl:text>
		</TD>
	</xsl:template>
	
	<!--
		Output a calendar entry for a section or reading (both use the same
		formatting).
	-->
	<xsl:template match="section[node()]|reading[node()]">
		<TD CLASS="white-center">
			<xsl:attribute name="ROWSPAN">
				<xsl:value-of select="@rows"/>
				<xsl:if test="not(@rows)">
					<xsl:value-of select="$rows-per-week"/>
				</xsl:if>
			</xsl:attribute>
			<xsl:apply-templates/>
		</TD>
	</xsl:template>
	
	<!--
		Output an empty section or reading cell.
	-->
	<xsl:template match="section[not(node())]|reading[not(node())]">
		<TD CLASS="medgrey-center">
			<xsl:attribute name="ROWSPAN">
				<xsl:value-of select="@rows"/>
				<xsl:if test="not(@rows)">
					<xsl:value-of select="$rows-per-week"/>
				</xsl:if>
			</xsl:attribute>
			<xsl:text disable-output-escaping="yes">&amp;nbsp;</xsl:text>
		</TD>
	</xsl:template>
	
	<!--
		Output a calendar entry for an assessment.
	-->
	<xsl:template match="assessment[node()]">
		<TD CLASS="peach-center">
			<xsl:attribute name="ROWSPAN">
				<xsl:value-of select="@rows"/>
				<xsl:if test="not(@rows)">
					<xsl:value-of select="$rows-per-week"/>
				</xsl:if>
			</xsl:attribute>
			<xsl:apply-templates/>
		</TD>
	</xsl:template>
	
	<!--
		Output an empty assessment cell.
	-->
	<xsl:template match="assessment[not(node())]">
		<TD CLASS="medgrey-center">
			<xsl:attribute name="ROWSPAN">
				<xsl:value-of select="@rows"/>
				<xsl:if test="not(@rows)">
					<xsl:value-of select="$rows-per-week"/>
				</xsl:if>
			</xsl:attribute>
			<xsl:text disable-output-escaping="yes">&amp;nbsp;</xsl:text>
		</TD>
	</xsl:template>
	
	
	<!--
		Generate a link.
	-->
	<xsl:template match="link">
		<A HREF="{@href}"><xsl:apply-templates/></A>
	</xsl:template>
	
	<xsl:template match="assessment//link">
		<A HREF="{@href}"><xsl:apply-templates/></A>
	</xsl:template>
	
	
	<!--
		Wrap quotes around a string. If the attribute SINGLE is set to
		"yes", use single quotes instead of double. Use numeric entity
		references because not all browsers support &ldquo;, &rdquo;,
		&lsquo; and &rsquo;.
	-->
	<xsl:template match="quote">
		<xsl:choose>
			<xsl:when test="@single = 'yes'">
				<xsl:text disable-output-escaping="yes">&amp;lsquo;</xsl:text>
			</xsl:when>
			<xsl:otherwise>
				<xsl:text disable-output-escaping="yes">&amp;ldquo;</xsl:text>
			</xsl:otherwise>
		</xsl:choose>
		<xsl:apply-templates/>
		<xsl:choose>
			<xsl:when test="@single = 'yes'">
				<xsl:text disable-output-escaping="yes">&amp;rsquo;</xsl:text>
			</xsl:when>
			<xsl:otherwise>
				<xsl:text disable-output-escaping="yes">&amp;rdquo;</xsl:text>
			</xsl:otherwise>
		</xsl:choose>
	</xsl:template>
	
	<!--
		Output an ampersand entity (&amp;).
	-->
	<xsl:template match="ampersand">
		<xsl:text disable-output-escaping="yes">&amp;amp;</xsl:text>
	</xsl:template>
	
	<!--
		Output an en-dash entity (&#8211; because not all browsers support
		&ndash;).
	-->
	<xsl:template match="endash">
		<xsl:text disable-output-escaping="yes">&amp;ndash;</xsl:text>
	</xsl:template>
	
	<!--
		Output a section symbol entity (&#167; because not all browsers support
		&sect;).
	-->
	<xsl:template match="sect">
		<xsl:text disable-output-escaping="yes">&amp;sect;</xsl:text>
	</xsl:template>
	
	<!--
		Output a hash character.
	-->
	<xsl:template match="hash">
		<xsl:text>#</xsl:text>
	</xsl:template>
	
	<!--
		Miscellaneous HTML elements to be mapped straight through.
	-->
	<xsl:template match="strong">
		<STRONG><xsl:apply-templates/></STRONG>
	</xsl:template>
	
	<xsl:template match="em">
		<EM><xsl:apply-templates/></EM>
	</xsl:template>
	
	<xsl:template match="b">
		<B><xsl:apply-templates/></B>
	</xsl:template>
	
	<xsl:template match="i">
		<I><xsl:apply-templates/></I>
	</xsl:template>
	
	<xsl:template match="u">
		<SPAN STYLE="text-decoration: underline;"><xsl:apply-templates/></SPAN>
	</xsl:template>
	
	<xsl:template match="br">
		<BR />
	</xsl:template>
	
</xsl:stylesheet>