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

<!--
	Output a string containing the date that the document was last built. This is implemented in three parts:
	
		1. A "private" internal template that can only be called directly via call-template.
		
		2. A "public" template that matches build-date elements in the document.
		
		3. A "private" function to generate the actual date string in the desired format.
	
	These templates use the stylesheet global variable $date-built, which is set to the current date-time when the stylesheet is executed. They also use the global $document-name variable, which contains the name of the document currently being processed.
-->

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


	<!--
		First, the internal template (1 above). This includes all the logic for outputting a build date string in the required form. The only time this should be explicitly called is for the automatic build date footers that can appear at the end of a document. 
		
		$format: How to format the build date.
			'short' => Output "YYYY-MM-DD".
			'long' => Output "YYYY-MM-DD hh:mm:ss". [default]
			date picture string => Output the date in the specified format (see http://www.w3.org/TR/xslt20/#date-picture-string).
		
		$style: The presentation style of the build date.
			'inline' => Output the build date inline with the surrounding text. [default]
			'footer' => Output the build date in a footer with some additional text, normally for inclusion at the end of a document.
	-->
	<template name="build-date-internal">
		<common>
			<xsl:param name="format">long</xsl:param>
			<xsl:param name="style">inline</xsl:param>
		</common>
		<common formats="/html/xhtml/">
			<xsl:choose>
				<xsl:when test="$style eq 'inline'">
					<xsl:value-of select="infosci:generate-build-date( $format )" />
				</xsl:when>
				<xsl:when test="$style eq 'footer'">
					<address>
						<xsl:value-of select="$document-name" />
						<xsl:text>, last built </xsl:text>
						<xsl:value-of select="infosci:generate-build-date( $format )" />
					</address>
				</xsl:when>
				<xsl:otherwise>
					<xsl:message terminate="yes">
						<xsl:text>Unrecognised value "</xsl:text>
						<xsl:value-of select="$style" />
						<xsl:text>" for build-date/$style.</xsl:text>
					</xsl:message>
				</xsl:otherwise>
			</xsl:choose>
		</common>
		<common formats="/latex/xelatex/">
			<xsl:choose>
				<xsl:when test="$style eq 'inline'">
					<xsl:value-of select="infosci:generate-build-date( $format )" />
				</xsl:when>
				<xsl:when test="$style eq 'footer'">
					<xsl:text>\vfill</xsl:text>
					<xsl:call-template name="newline-internal" />
					<xsl:call-template name="newline-internal" />
					<xsl:text>{\scriptsize \hfill \verb+</xsl:text>
					<xsl:value-of select="$document-name" />
					<xsl:text>, last built </xsl:text>
					<xsl:value-of select="infosci:generate-build-date( $format )" />
					<xsl:text>+}</xsl:text>
					<xsl:call-template name="newline-internal" />
					<xsl:call-template name="newline-internal" />
				</xsl:when>
				<xsl:otherwise>
					<xsl:message terminate="yes">
						<xsl:text>Unrecognised value "</xsl:text>
						<xsl:value-of select="$style" />
						<xsl:text>" for build-date/$style.</xsl:text>
					</xsl:message>
				</xsl:otherwise>
			</xsl:choose>
		</common>
	</template>
	
	<!--
		Second, the "public" template (2 above). This is essentially just a wrapper around the internal template, with some additional logic to handle differences between LaTeX and HTML handling.
		
		In particular, we need to consider the case where /document/@auto-latex-build-date = "no", which suppresses the final build-date footer in generated LaTeX documents (which is generated by the internal template above). This is needed to resolve issues with weird footer placement due to floating items like tables and figures. The build date can then be explicitly inserted, if desired, using a build-date element in the document, which will be processed by the public template below.
		
		This suppression doesn't apply to HTML, so the final auto-generated build-date footer will always be produced in HTML documents, regardless. We therefore want to suppress the processing of explicit build-date elements in HTML documents, otherwise we'll end up with more or less the inverse of the LaTeX situation: build-date footers in weird locations within the document (and probably ill-formed HTML to boot).
		
		This template therefore suppresses calls to the internal template where applicable.
		
		@format: How to format the build date.
			'short' => Output "YYYY-MM-DD hh:mm:ss". [default]
			'long' => Output "Last built: YYYY-MM-DD hh:mm:ss".
			date picture string => Output the date in the specified format (see http://www.w3.org/TR/xslt20/#date-picture-string).
		
		@style: The presentation style of the build date.
			'inline' => Output the build date inline with the surrounding text. [default]
			'footer' => Output the build date in a footer, normally for inclusion at the end of a document.
	-->
	<template name="build-date" match="build-date">
		<common formats="/html/xhtml/">
			<xsl:choose>
				<xsl:when test="( @style eq 'footer' ) and ( /document/@auto-latex-build-date = ('no', 'n', 'false', 'f', '0') )" />
				<xsl:otherwise>
					<xsl:call-template name="build-date-internal">
						<xsl:with-param name="format" select="if ( @format ) then @format else 'short'" />
						<xsl:with-param name="style" select="if ( @style ) then @style else 'inline'" />
					</xsl:call-template>
				</xsl:otherwise>
			</xsl:choose>
		</common>
		<common formats="/latex/xelatex/">
			<xsl:call-template name="build-date-internal">
				<xsl:with-param name="format" select="if ( @format ) then @format else 'short'" />
				<xsl:with-param name="style" select="if ( @style ) then @style else 'inline'" />
			</xsl:call-template>
		</common>
	</template>
	
	<!--
		Finally, a utility function to modularise the generation of the actual date value, as it's identical for all formats.
		
		$format: How to format the build date.
			'short' => Output "YYYY-MM-DD hh:mm:ss". [default]
			'long' => Output "Last built: YYYY-MM-DD hh:mm:ss".
			date picture string => Output the date in the specified format (see http://www.w3.org/TR/xslt20/#date-picture-string).
	-->
	<function name="infosci:generate-build-date" as="xs:string">
		<common>
			<xsl:param name="format" />
			
			<xsl:choose>
				<xsl:when test="$format eq 'short'">
					<xsl:sequence select="format-dateTime( $date-built, '[Y0001]-[M01]-[D01]' )" />
				</xsl:when>
				<xsl:when test="$format eq 'long'">
					<xsl:sequence select="format-dateTime( $date-built, '[Y0001]-[M01]-[D01] [H01]:[m01]:[s01]' )" />
				</xsl:when>
				<!-- Assume it's a date picture string otherwise. -->
				<xsl:otherwise>
					<xsl:sequence select="format-dateTime( $date-built, $format )" />
				</xsl:otherwise>
			</xsl:choose>
		</common>
	</function>


</stylesheet>