Newer
Older
XML / modules / paper-calendar.xml
<?xml version="1.0" encoding="utf-8"?>

<!--
	Elements for generating a teaching calendar for a paper.
-->

<stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

	
	<!--
		The top level calendar element.
		
		@number-of-weeks: The duration of the paper in weeks. [required]
		
		@lectures-per-week: The number of lectures per week in the paper. Each lecture is assumed to occupy exactly one row in the resulting table, so this effectively determines the number of rows in the resulting table that each week occupies. [required]
	-->
	<template match="calendar">
		<common formats="/latex/xelatex/">
			<xsl:if test="not( @number-of-weeks )">
				<xsl:message terminate="yes">
					<xsl:text>Required attribute "number-of-weeks" has not been supplied in calendar.</xsl:text>
				</xsl:message>
			</xsl:if>
			<xsl:if test="not( @lectures-per-week )">
				<xsl:message terminate="yes">
					<xsl:text>Required attribute "lectures-per-week" has not been supplied in calendar.</xsl:text>
				</xsl:message>
			</xsl:if>
			
			<!--
				This is used in a few places to set the width of column cells, etc., that contain numbers. I can't remember why I decided to pick twice the number of weeks as the size, other than to ensure a decent spacing around the numbers?
			-->
			<xsl:text>\newlength{\numberwidth}</xsl:text>
			<xsl:text>\settowidth{\numberwidth}{</xsl:text>
			<xsl:number value="@number-of-weeks * 2" />
			<xsl:text>}</xsl:text>
			<xsl:call-template name="newline-internal" />

			<xsl:text>\begin{center}</xsl:text>
			<xsl:call-template name="newline-internal" />
							
			<!-- TODO: Probably not if standalone! -->
			<xsl:text>\begin{sideways}</xsl:text>
			<xsl:call-template name="newline-internal" />
							
			<xsl:text>\resizebox{24cm}{!}{%</xsl:text>
			<xsl:call-template name="newline-internal" />
							
			<xsl:text>\begin{tabular}{|c|c|c|c|l|c|c|c|c|c|c|}</xsl:text>
			<xsl:call-template name="newline-internal" />
							
			<!--
				Calendar heading. We can't use generate-content-cell for this, because we're doing more complex processing of the cell contents than is possible with generate-content-cell. Here, we're calling three separate templates interspersed with text, whereas generate-content-cell can only accept a simple list of nodes to apply-templates to.
			-->
			<xsl:text>\multicolumn{11}{c}{\LARGE\textbf{</xsl:text>
			<xsl:call-template name="PaperCode" />
			<xsl:text> Paper Calendar, </xsl:text>
			<xsl:call-template name="PaperPeriod" />
			<xsl:text>, </xsl:text>
			<xsl:call-template name="PaperYear" />
			<xsl:text>}}	\\</xsl:text>
			<xsl:call-template name="newline-internal" />
			
			<!--
				Note that using generate-empty-cell here requires about three time as much code as just doing it inline :), but we gain in terms of output consistency.
			-->
			<xsl:call-template name="generate-empty-cell">
				<xsl:with-param name="columns">11</xsl:with-param>
				<xsl:with-param name="rows">1</xsl:with-param>
				<xsl:with-param name="column-format">c</xsl:with-param>
			</xsl:call-template>
			<xsl:text>	\\</xsl:text>
			<xsl:call-template name="newline-internal" />
			
			<xsl:text>\hline</xsl:text>
			<xsl:call-template name="newline-internal" />
			
			<!-- The calendar itself. -->
			<xsl:apply-templates select="header" />
			<xsl:call-template name="newline-internal" />
			
			<xsl:text>\hline\hline</xsl:text>
			<xsl:call-template name="newline-internal" />
			
			<xsl:apply-templates select="body" />
			<xsl:call-template name="newline-internal" />
			
			<xsl:text>\hline\hline</xsl:text>
			<xsl:call-template name="newline-internal" />
			
			<xsl:apply-templates select="footer" />
			<xsl:call-template name="newline-internal" />
			
			<xsl:text>\hline</xsl:text>
			<xsl:call-template name="newline-internal" />

			<xsl:text>\end{tabular}%</xsl:text>
			<xsl:call-template name="newline-internal" />
			
			<xsl:text>}</xsl:text>
			<xsl:call-template name="newline-internal" />
			
			<xsl:text>\end{sideways}</xsl:text>
			<xsl:call-template name="newline-internal" />
			
			<xsl:text>\end{center}</xsl:text>
			<xsl:call-template name="newline-internal" />
		</common>
		<common formats="/html/xhtml/">
			<!-- Calendar heading. -->
			<h2>
				<xsl:call-template name="PaperCode" />
				<xsl:text> Paper Calendar, </xsl:text>
				<xsl:call-template name="PaperPeriod" />
				<xsl:text>, </xsl:text>
				<xsl:call-template name="PaperYear" />
			</h2>
			
			<!-- The calendar itself. -->
			<div class="sans">
				<table class="small calendar" 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 class="calendar">
						<xsl:apply-templates select="header" />
					</thead>
					<tfoot class="calendar">
						<xsl:apply-templates select="footer" />
					</tfoot>
					<tbody class="calendar">
						<xsl:apply-templates select="body" />
					</tbody>
				</table>
			</div>
		</common>
	</template>
	
	
	<!--
		Header/footer rows for the calendar table. To get proper table headings/footings, use HEADING/FOOTING. For other text, use NOTE.
	-->
	<template match="header|footer">
		<common formats="/latex/xelatex/">
			<xsl:apply-templates />
			<xsl:text>	\\</xsl:text>
			
			<!--
				It's left to the parent template to add horizontal rules after the last header/footer element, as what gets output may vary depending on position in the table (e.g., double rule after the last header, but single rule after the last footer).
			-->
			<xsl:if test="position() != last()">
				<xsl:text>	\hline</xsl:text>
			</xsl:if>
			<xsl:call-template name="newline-internal" />
		</common>
		<common formats="/html/xhtml/">
			<tr>
				<xsl:apply-templates />
			</tr>
		</common>
	</template>
	
	
	<!--
		A table heading or footing, bolded, centered, etc. Headings and footings are assumed to occupy a single row only.
		
		@columns: The number of columns that the heading or footing spans.
	-->
	<template match="heading|footing">
		<common formats="/latex/xelatex/">
			<xsl:call-template name="generate-content-cell">
				<!-- I'm slightly amazed that this actually works! -->
				<xsl:with-param name="columns" select="if ( @columns ) then @columns else 1" />
				<xsl:with-param name="rows">1</xsl:with-param>
				<xsl:with-param name="style">\bfseries</xsl:with-param>
			</xsl:call-template>

			<xsl:if test="position() != last()">
				<xsl:call-template name="tabular-column-separator" />
			</xsl:if>
		</common>
		<common formats="/html/xhtml/">
			<!--
				We can't use generate-content-cell here because we need TH rather than TD. This is a one-off anyway.
			-->
			<th class="calendar">
				<xsl:if test="@columns">
					<xsl:attribute name="colspan">
						<xsl:value-of select="@columns" />
					</xsl:attribute>
				</xsl:if>
				<xsl:apply-templates />
			</th>
		</common>
	</template>
	
	
	<!--
		A miscellaneous piece of text to be inserted somewhere in the calendar table. Notes are assumed to occupy a single row only. This is particularly true for LaTeX where we're working within a tabular environment, which means there's no automatic wrapping of long lines anyway.
		
		@columns: The number of columns that the heading or footing spans.
	-->
	<template match="note">
		<common formats="/latex/xelatex/">
			<xsl:call-template name="generate-content-cell">
				<xsl:with-param name="columns" select="if ( @columns ) then @columns else 1" />
				<xsl:with-param name="rows">1</xsl:with-param>
				<xsl:with-param name="align">left</xsl:with-param>
				<xsl:with-param name="column-format">|l|</xsl:with-param>
			</xsl:call-template>
		</common>
		<common formats="/html/xhtml/">
			<xsl:call-template name="generate-content-cell">
				<xsl:with-param name="columns" select="if ( @columns ) then @columns else 1" />
				<xsl:with-param name="rows">1</xsl:with-param>
				<xsl:with-param name="align">left</xsl:with-param>
			</xsl:call-template>
		</common>
	</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.
	-->
	<template match="week">
		<common formats="/latex/xelatex/">
			<xsl:for-each select="row">
				
				<!--
					If we're going to start a new section on this row, draw a rule under the previous section to separate them (editorial: tabular borders in LaTeX are pretty awful compared to HTML). The horrible XPath logic is as follows:
					
						* the current row contains at least one section element; and
							* either
								* there is at least one week preceding the current week; and
								* the immediately preceding week /isn't/ a holiday;
							* or
								* this is not the first row of the current week; and
									* the current week is the first week in the calendar; or
									* the immediately preceding week /is/ a holiday.
					
					(YOUR HEAD ASPLODE.)
				-->
				<xsl:if test="		child::section
								and	(	(	( count( ../preceding-sibling::week ) > 0 )
										and	( not( ../preceding-sibling::week[1]/@holiday ) )
										)
									or	(	( position() > 1 )
										and	(	( count( ../preceding-sibling::week ) = 0 )
											or	( ../preceding-sibling::week[1]/@holiday )
											)
										)
									)">
					<xsl:text>\cline{3-3}</xsl:text>
				</xsl:if>
	
				<!-- Output the week number and dates columns, but only on the first row of the week. -->
				<xsl:choose>
					<xsl:when test="position() = 1">
						<!-- Week number. -->
						<xsl:call-template name="generate-number-cell">
							<xsl:with-param name="number" select="1 + count( preceding::week[not( @holiday )] )" />
						</xsl:call-template>
						<xsl:call-template name="tabular-column-separator" />
		
						<!-- Date range. -->
						<xsl:call-template name="generate-content-cell">
							<xsl:with-param name="nodes" select="../dates" />
						</xsl:call-template>
						<xsl:call-template name="tabular-column-separator" />
					</xsl:when>
					<xsl:otherwise>
						<xsl:call-template name="tabular-column-separator" />
						<xsl:call-template name="tabular-column-separator" />
					</xsl:otherwise>
				</xsl:choose>
				
				<!--
					We have to apply each of the sub-templates manually, not so much to ensure the correct ordering, but so that we can correctly output empty cells when a lecture, laboratory or tutorial element is missing.
				-->
				<xsl:apply-templates select="section" />
				<xsl:call-template name="tabular-column-separator" />
				
				<!--
					Lecture cells span two columns, so we need to explicitly output a two-column empty cell if there's no lecture element for the current row.
				-->
				<xsl:apply-templates select="lecture" />
				<xsl:if test="count( lecture ) = 0">
					<xsl:call-template name="generate-empty-cell">
						<xsl:with-param name="columns">2</xsl:with-param>
						<xsl:with-param name="rows">1</xsl:with-param>
						<xsl:with-param name="column-format">c|</xsl:with-param>
					</xsl:call-template>
				</xsl:if>
				<xsl:call-template name="tabular-column-separator" />
	
				<xsl:apply-templates select="reading" />
				<xsl:call-template name="tabular-column-separator" />
	
				<!--
					Labs and tutorials are similar to lectures, except that they span two columns and all rows for the week, so only the the first row of the week will have a laboratory or tutorial element, empty or otherwise. If this laboratory or tutorial element has content (i.e., isn't empty), then we need to skip over these cells for the remaining rows of the week. If this element is empty (or there's no element at all) then we output a two-column empty cell for all rows.
					
					Note that we use "../row[1]" rather than one of the "preceding" axes, as the latter are effectively indexed in reverse.
				-->
				<xsl:apply-templates select="laboratory" />
				<xsl:if test="count( laboratory ) = 0">
					<xsl:choose>
						<xsl:when test="not( ../row[1]/laboratory/node() )">
							<xsl:call-template name="generate-empty-cell">
								<xsl:with-param name="columns">2</xsl:with-param>
								<xsl:with-param name="rows">1</xsl:with-param>
								<xsl:with-param name="column-format">c|</xsl:with-param>
							</xsl:call-template>
						</xsl:when>
						<xsl:otherwise>
							<xsl:call-template name="tabular-column-separator" />
						</xsl:otherwise>
					</xsl:choose>
				</xsl:if>
				<xsl:call-template name="tabular-column-separator" />
	
				<xsl:apply-templates select="tutorial" />
				<xsl:if test="count( tutorial ) = 0">
					<xsl:choose>
						<xsl:when test="not( ../row[1]/tutorial/node() )">
							<xsl:call-template name="generate-empty-cell">
								<xsl:with-param name="columns">2</xsl:with-param>
								<xsl:with-param name="rows">1</xsl:with-param>
								<xsl:with-param name="column-format">c|</xsl:with-param>
							</xsl:call-template>
						</xsl:when>
						<xsl:otherwise>
							<xsl:call-template name="tabular-column-separator" />
						</xsl:otherwise>
					</xsl:choose>
				</xsl:if>
				<xsl:call-template name="tabular-column-separator" />
				
				<!--
					Assessments always span a single column and span all rows for a week, so no additional special handling is required for missing elements.
				-->
				<xsl:apply-templates select="assessment" />
	
				<!-- Note assumption that a lecture is always a single row. -->
				<xsl:text>	\\</xsl:text>
				<!--
					Put a border beneath a lecture. The horrible XPath logic is as follows:
					
						* either
							* there is at least one week following the current week; and
							* the immediately following week /isn't/ a holiday;
						* or
							* this is not the last row of the current week; and
								* the current week is the last week in the calendar; or
								* the immediately following week /is/ a holiday.
					
					(YOUR HEAD ASPLODE AGAIN.)
				-->
				<xsl:if test="	(	( count( ../following-sibling::week ) > 0 )
								and	( not( ../following-sibling::week[1]/@holiday ) )
								)
								or	(	( position() &lt; last() )
									and	(	( count( ../following-sibling::week ) = 0 )
										or	( ../following-sibling::week[1]/@holiday )
										)
									)">
					<xsl:text> \cline{4-5}</xsl:text>
				</xsl:if>
				
				<!--
					Underline laboratory and tutorial cells. Logic is as above, plus a test whether this is the last row of the week. (KER-SPLODEY.)
				-->
				<xsl:if test="	( position() = ancestor::calendar/@lectures-per-week )
							and	(	(	( count( ../following-sibling::week ) > 0 )
									and	( not( ../following-sibling::week[1]/@holiday ) )
									)
								or	(	( position() &lt; last() )
									and	(	( count( ../following-sibling::week ) = 0 )
										or	( ../following-sibling::week[1]/@holiday )
										)
									)
								)">
					<xsl:text>\cline{1-2}\cline{6-6}\cline{11-11}</xsl:text>
					<xsl:if test="not( ../row[1]/laboratory/@rows )">
						<xsl:text>\cline{7-8}</xsl:text>
					</xsl:if>
					<xsl:if test="not( ../row[1]/tutorial/@rows )">
						<xsl:text>\cline{9-10}</xsl:text>
					</xsl:if>
				</xsl:if>
				
				<xsl:call-template name="newline-internal" />
			</xsl:for-each>
		</common>
		<common formats="/html/xhtml/">
			<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. -->
						<xsl:call-template name="generate-number-cell">
							<!-- TODO: Can this be compressed using XPath? -->
							<xsl:with-param name="colour">
								<xsl:choose>
									<xsl:when test="$current = 'yes'">red</xsl:when>
									<xsl:otherwise>white</xsl:otherwise>
								</xsl:choose>
							</xsl:with-param>
							<xsl:with-param name="number" select="1 + count( preceding::week[not( @holiday )] )" />
						</xsl:call-template>

						<!-- Date range, first row only. -->
						<xsl:call-template name="generate-content-cell">
							<xsl:with-param name="nodes" select="../dates" />
						</xsl:call-template>
					</xsl:if>
	
					<!--
						Apply each of the sub-templates in the correct order.
					-->
					<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>
		</common>
	</template>
	
	
	<!--
		Weeks that are holidays have no week number or date range, just a text description.
	-->
	<template match="week[@holiday]">
		<common formats="/latex/xelatex/">
			<xsl:text>\hline\hline</xsl:text>
			<xsl:call-template name="newline-internal" />
			
			<xsl:call-template name="generate-content-cell">
				<xsl:with-param name="columns">11</xsl:with-param>
				<xsl:with-param name="rows">2</xsl:with-param>
				<xsl:with-param name="column-format">|c|</xsl:with-param>
				<xsl:with-param name="style">\LARGE\sffamily\bfseries</xsl:with-param>
			</xsl:call-template>
			<xsl:text>	\\</xsl:text>
			<xsl:call-template name="newline-internal" />
			
			<xsl:call-template name="generate-empty-cell">
				<xsl:with-param name="columns">11</xsl:with-param>
				<xsl:with-param name="rows">1</xsl:with-param>
				<xsl:with-param name="column-format">|c|</xsl:with-param>
			</xsl:call-template>
			<xsl:text>	\\</xsl:text>
			<xsl:call-template name="newline-internal" />
			
			<xsl:text>\hline\hline</xsl:text>
			<xsl:call-template name="newline-internal" />
		</common>
		<common formats="/html/xhtml/">
			<tr>
				<xsl:call-template name="generate-content-cell">
					<xsl:with-param name="columns">11</xsl:with-param>
					<xsl:with-param name="rows">1</xsl:with-param>
					<xsl:with-param name="colour">blue-ou large</xsl:with-param>
					<xsl:with-param name="style">border: 2px solid #777777; font-style: italic; font-weight: bold;</xsl:with-param>
				</xsl:call-template>
			</tr>
		</common>
	</template>


	<!--
		Output a calendar entry for a lecture. Note that lectures are always assumed to span a single row. Lectures are automatically numbered.
	-->
	<template match="lecture[node() and not( @holiday )]">
		<common formats="/latex/xelatex/">
			<xsl:call-template name="generate-number-cell">
				<xsl:with-param name="rows">1</xsl:with-param>
				<xsl:with-param name="number" select="1 + count( preceding::lecture[node() and not( @holiday )] )" />
			</xsl:call-template>

			<xsl:call-template name="tabular-column-separator" />
			
			<xsl:call-template name="generate-content-cell">
				<xsl:with-param name="rows">1</xsl:with-param>
				<xsl:with-param name="align">left</xsl:with-param>
			</xsl:call-template>
		</common>
		<common formats="/html/xhtml/">
			<xsl:call-template name="generate-number-cell">
				<xsl:with-param name="rows">1</xsl:with-param>
				<xsl:with-param name="colour">ltgrey</xsl:with-param>
				<xsl:with-param name="number" select="1 + count( preceding::week[not( @holiday )] )" />
			</xsl:call-template>

			<xsl:call-template name="generate-content-cell">
				<xsl:with-param name="rows">1</xsl:with-param>
				<xsl:with-param name="colour">ltgrey</xsl:with-param>
				<xsl:with-param name="align">left</xsl:with-param>
			</xsl:call-template>
		</common>
	</template>


	<!--
		Output a calendar entry for a lecture that occurs on a holiday. These aren't numbered.
	-->
	<template match="lecture[@holiday]">
		<common formats="/latex/xelatex/">
			<xsl:call-template name="generate-content-cell">
				<xsl:with-param name="columns">2</xsl:with-param>
				<xsl:with-param name="rows">1</xsl:with-param>
				<xsl:with-param name="style">\sffamily\bfseries</xsl:with-param>
			</xsl:call-template>
		</common>
		<common formats="/html/xhtml/">
			<xsl:call-template name="generate-content-cell">
				<xsl:with-param name="columns">2</xsl:with-param>
				<xsl:with-param name="rows">1</xsl:with-param>
				<xsl:with-param name="colour">blue-ou</xsl:with-param>
				<xsl:with-param name="style">font-style: italic; font-weight: bold;</xsl:with-param>
			</xsl:call-template>
		</common>
	</template>


	<!--
		Output an empty lecture cell.
	-->
	<template match="lecture[not( node() )]">
		<common>
			<xsl:call-template name="generate-empty-cell">
				<xsl:with-param name="columns">2</xsl:with-param>
			</xsl:call-template>
		</common>
	</template>


	<!--
		Output a calendar entry for a laboratory. Laboratories are automatically numbered.
	-->
	<template match="laboratory[node()]">
		<common formats="/latex/xelatex/">
			<xsl:call-template name="generate-number-cell">
				<xsl:with-param name="number" select="1 + count( preceding::laboratory[node()] )" />
			</xsl:call-template>
			
			<xsl:call-template name="tabular-column-separator" />
	
			<xsl:call-template name="generate-content-cell" />
		</common>
		<common formats="/html/xhtml/">
			<xsl:call-template name="generate-number-cell">
				<xsl:with-param name="colour">ltblue</xsl:with-param>
				<xsl:with-param name="number" select="1 + count( preceding::laboratory[node()] )" />
			</xsl:call-template>

			<xsl:call-template name="generate-content-cell">
				<xsl:with-param name="colour">ltblue</xsl:with-param>
			</xsl:call-template>
		</common>
	</template>


	<!--
		Output a calendar entry for a tutorial. Tutorials are automatically numbered.
	-->
	<template match="tutorial[node()]">
		<common formats="/latex/xelatex/">
			<xsl:call-template name="generate-number-cell">
				<xsl:with-param name="number" select="1 + count( preceding::tutorial[node()] )" />
			</xsl:call-template>
			
			<xsl:call-template name="tabular-column-separator" />
	
			<xsl:call-template name="generate-content-cell" />
		</common>
		<common formats="/html/xhtml/">
			<xsl:call-template name="generate-number-cell">
				<xsl:with-param name="colour">medgreen</xsl:with-param>
				<xsl:with-param name="number" select="1 + count( preceding::tutorial[node()] )" />
			</xsl:call-template>

			<xsl:call-template name="generate-content-cell">
				<xsl:with-param name="colour">medgreen</xsl:with-param>
			</xsl:call-template>
		</common>
	</template>


	<!--
		Output an empty laboratory/tutorial cell.
	-->
	<template match="laboratory[not( node() )]|tutorial[not( node() )]">
		<common>
			<xsl:call-template name="generate-empty-cell">
				<xsl:with-param name="columns">2</xsl:with-param>
				<xsl:with-param name="rows" select="if ( @rows ) then @rows else ancestor::calendar/@lectures-per-week" />
			</xsl:call-template>
		</common>
	</template>


	<!--
		Output a calendar entry for a section, reading or asssement. All use the same formatting in (Xe)LaTeX, but assessments are displayed using a different colour in (X)HTML, hence the separate template for those.
	-->
	<template match="calendar//section[node()]|reading[node()]">
		<common formats="/latex/xelatex/">
			<xsl:call-template name="generate-content-cell">
				<xsl:with-param name="rows" select="if ( @rows ) then @rows else ancestor::calendar/@lectures-per-week" />
			</xsl:call-template>
		</common>
		<common formats="/html/xhtml/">
			<xsl:call-template name="generate-content-cell">
				<xsl:with-param name="rows" select="if ( @rows ) then @rows else ancestor::calendar/@lectures-per-week" />
			</xsl:call-template>
		</common>
	</template>
	
	<template match="assessment[node()]">
		<common formats="/latex/xelatex/">
			<xsl:call-template name="generate-content-cell">
				<xsl:with-param name="rows" select="if ( @rows ) then @rows else ancestor::calendar/@lectures-per-week" />
			</xsl:call-template>
		</common>
		<common formats="/html/xhtml/">
			<xsl:call-template name="generate-content-cell">
				<xsl:with-param name="rows" select="if ( @rows ) then @rows else ancestor::calendar/@lectures-per-week" />
				<xsl:with-param name="colour">peach</xsl:with-param>
			</xsl:call-template>
		</common>
	</template>


	<!--
		Output an empty section, reading or assessment cell.
	-->
	<template match="calendar//section[not( node() )]|reading[not( node() )]|assessment[not( node() )]">
		<common>
			<xsl:call-template name="generate-empty-cell">
				<xsl:with-param name="rows" select="if ( @rows ) then @rows else ancestor::calendar/@lectures-per-week" />
			</xsl:call-template>
		</common>
	</template>


	<!--
		Generate a link.
	-->
	<template match="link|assessment//link">
		<common formats="/latex/xelatex/">
			<xsl:apply-templates />
		</common>
		<common formats="/html/xhtml/">
			<a href="{@href}"><xsl:apply-templates /></a>
		</common>
	</template>


<!-- 
	<template match="">
		<common formats="/latex/xelatex/">
		</common>
		<common formats="/html/xhtml/">
		</common>
	</template>


	<template match="">
		<common formats="/latex/xelatex/">
		</common>
		<common formats="/html/xhtml/">
		</common>
	</template>
 -->
	
	<template name="generate-number-cell">
		<common>
			<xsl:param name="columns" as="xs:integer">1</xsl:param>
			<xsl:param name="rows" as="xs:integer" select="ancestor::calendar/@lectures-per-week" />
			<!-- No data type for this one, as there isn't a single top-level numeric primitive type in XML Schema :(. -->
			<xsl:param name="number">0</xsl:param>
		</common>
		<common formats="/latex/xelatex/">
			<xsl:param name="column-format" as="xs:string">c|</xsl:param>

			<xsl:if test="$columns > 1">
				<xsl:text>\multicolumn{</xsl:text>
				<xsl:value-of select="$columns" />
				<xsl:text>}{</xsl:text>
				<xsl:value-of select="$column-format" />
				<xsl:text>}{</xsl:text>
			</xsl:if>
			<xsl:if test="$rows > 1">
				<xsl:text>\multirow{</xsl:text>
				<xsl:value-of select="$rows" />
				<xsl:text>}{*}{</xsl:text>
			</xsl:if>
			
			<xsl:text>\makebox[\numberwidth][c]{</xsl:text>
			<xsl:value-of select="$number" />
			<xsl:text>}</xsl:text>

			<xsl:if test="$rows > 1">
				<xsl:text>}</xsl:text>
			</xsl:if>
			<xsl:if test="$columns > 1">
				<xsl:text>}</xsl:text>
			</xsl:if>
		</common>
		<common formats="/html/xhtml/">
			<xsl:param name="colour" as="xs:string">white</xsl:param>
			
			<td class="{$colour} center calendar" colspan="{$columns}" rowspan="{$rows}">
				<xsl:value-of select="$number" />
			</td>
		</common>
	</template>
	
	
	<!--
		Note when using pre-code in LaTeX to provide formatting: because of the tabular environment, use the declaration forms, not the macros.
	-->
	<template name="generate-content-cell">
		<common>
			<xsl:param name="columns" as="xs:integer">1</xsl:param>
			<xsl:param name="rows" as="xs:integer" select="ancestor::calendar/@lectures-per-week" />
			<xsl:param name="align" as="xs:string">center</xsl:param>
			<!--
				Hmm, it appears that if you specify a parameter as xs:string, you can't supply an empty default value. Even a blank doesn't work! The only way to have an empty default is to not specify a data type. That's pretty damn stupid :(.
			-->
			<xsl:param name="style" />
			<xsl:param name="nodes" select="node()" />
		</common>
		<common formats="/latex/xelatex/">
			<xsl:param name="column-format" as="xs:string">c|</xsl:param>

<!-- 
			<xsl:message>
				<xsl:text>////////// Value of rows = [</xsl:text>
				<xsl:value-of select="$rows" />
				<xsl:text>] //////////</xsl:text>
			</xsl:message>
 -->
			<xsl:if test="$columns > 1">
				<xsl:text>\multicolumn{</xsl:text>
				<xsl:value-of select="$columns" />
				<xsl:text>}{</xsl:text>
				<xsl:value-of select="$column-format" />
				<xsl:text>}{</xsl:text>
			</xsl:if>
			<xsl:if test="$rows > 1">
				<xsl:text>\multirow{</xsl:text>
				<xsl:value-of select="$rows" />
				<xsl:text>}{*}{</xsl:text>
			</xsl:if>
			
 			<!--
 				We need to apply any styling outside the tabular so that it applies to all lines of the tabular (style declarations only last until the next & or \\ in a tabular). Wrap everything up in a group to ensure that it reverts back to the original styling at the end (that should happen anyway, but I'm paranoid).
 			-->
			<xsl:text>{</xsl:text>
			<xsl:value-of select="$style" />

			<xsl:text>\begin{tabular}{</xsl:text>
			<xsl:value-of select="substring( $align, 1, 1 )" />
			<xsl:text>}</xsl:text>
			
			<xsl:apply-templates select="$nodes" />
			
			<xsl:text>\end{tabular}</xsl:text>
			
			<xsl:text>}</xsl:text>

			<xsl:if test="$rows > 1">
				<xsl:text>}</xsl:text>
			</xsl:if>
			<xsl:if test="$columns > 1">
				<xsl:text>}</xsl:text>
			</xsl:if>
		</common>
		<common formats="/html/xhtml/">
			<xsl:param name="colour" as="xs:string">white</xsl:param>
			
			<!-- Alignment is slightly odd in that it's done via a CSS class rather than explicitly. -->
			<td class="{$colour} {$align} calendar" style="{$style}" colspan="{$columns}" rowspan="{$rows}">
				<xsl:apply-templates select="$nodes" />
			</td>
		</common>
	</template>
	
	
	<template name="generate-empty-cell">
		<common>
			<xsl:param name="columns" as="xs:integer">1</xsl:param>
			<xsl:param name="rows" as="xs:integer" select="ancestor::calendar/@lectures-per-week" />
		</common>
		<common formats="/latex/xelatex/">
			<xsl:param name="column-format" as="xs:string">c|</xsl:param>

			<xsl:if test="$columns > 1">
				<xsl:text>\multicolumn{</xsl:text>
				<xsl:value-of select="$columns" />
				<xsl:text>}{</xsl:text>
				<xsl:value-of select="$column-format" />
				<xsl:text>}{</xsl:text>
			</xsl:if>
			<xsl:if test="$rows > 1">
				<xsl:text>\multirow{</xsl:text>
				<xsl:value-of select="$rows" />
				<xsl:text>}{*}{</xsl:text>
			</xsl:if>

			<xsl:call-template name="non-breaking-space" />

			<xsl:if test="$rows > 1">
				<xsl:text>}</xsl:text>
			</xsl:if>
			<xsl:if test="$columns > 1">
				<xsl:text>}</xsl:text>
			</xsl:if>
		</common>
		<common formats="/html/xhtml/">
			<xsl:param name="colour" as="xs:string">medgrey</xsl:param>

			<td class="{$colour} center calendar" colspan="{$columns}" rowspan="{$rows}">
				<xsl:call-template name="non-breaking-space" />
			</td>
		</common>
	</template>
	
	
</stylesheet>