Newer
Older
XML / xml2xslt.xsl
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet
	version="2.0"
	xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
	xmlns:xsl-out="[irrelevant]"
	xmlns:exsl="http://exslt.org/common"
>

	<!--
		XSLT transformation for a master XML document defining how to
		transform elements in the course handbook source into HTML and
		LaTeX.  Hmm, meta-stylesheet?!
	-->
	
	<!--	<xsl:output method="text" encoding="utf-8" media-type="text/xml" /> -->
	<xsl:output method="xml" encoding="utf-8" cdata-section-elements="html" />

	<!--
		What format are we generating a styesheet for?
		Possible values: html, xhtml, latex (includes pdflatex), xelatex.
	-->
	<xsl:param name="format">html</xsl:param>

	<!--
		Define an alias for the xsl namespace to avoid confusion when
		generating xsl: elements in the output of this stylesheet.
	-->
	<xsl:namespace-alias stylesheet-prefix="xsl-out" result-prefix="xsl" />

	<!--
		Some useful variables. (Could some of these become callable templates?)
	-->
	<xsl:variable name="newline">
<xsl:text>
</xsl:text>
	</xsl:variable>

	<xsl:variable name="space"><xsl:text> </xsl:text></xsl:variable>
	

	<xsl:template match="/">
		
		<xsl-out:stylesheet version="2.0" exclude-result-prefixes="exsl">
		
		<xsl-out:strip-space elements="*" />

		<xsl-out:param name="subject-code">INFO</xsl-out:param>
		<xsl-out:param name="paper-number" />
		<xsl-out:param name="paper-year" />
		<xsl-out:param name="paper-period" />
		
		<xsl-out:param name="showanswers" select="'no'" />
		
		<xsl-out:param name="base-path">.</xsl-out:param>

		<!-- copy in the generated Oracle documentation code -->
		<xsl:copy-of select="document('oracle-docs.xsl')/stylesheet/*" />
		<!-- <xsl:include href="oracle-docs.xsl" /> -->

		<!--
			We're going to use the text encoding in a few different places,
			so let's work out what it should be now.
		-->
		<xsl:variable name="text-encoding">
			<xsl:choose>
			
				<xsl:when test="($format = 'latex') or ($format = 'html')">
					<xsl:text>iso-8859-1</xsl:text>
				</xsl:when>
				
				<xsl:when test="($format = 'xelatex') or ($format = 'xhtml')">
					<xsl:text>utf-8</xsl:text>
				</xsl:when>
				
				<xsl:otherwise>
					<xsl:message terminate="yes">
						<xsl:text>Sorry, unknown format: </xsl:text><xsl:value-of select="$format" />
					</xsl:message>
				</xsl:otherwise>
			
			</xsl:choose>
		</xsl:variable>

		<!-- root-level documents should say what type/class of document they are (lecture, tutorial, generic, ...).  Do we want to call this a class or a type? -->
		<!--
		<xsl:variable name="doctype"><xsl:value-of select="/document/@type" /></xsl:variable>
		-->
		
		<!--
			First, output the document preamble according to format.
			This is generally different for each output format.
		-->
		<xsl:choose>
			
			<!--
				The HTML formats are fairly simple: the only things that
				change are the doctypes, version number and text encoding.
			-->
			<xsl:when test="$format = 'html'">
			
				<xsl-out:output
					method="html"
					encoding="{$text-encoding}"
					version="4.01"
					media-type="text/html"
					doctype-public="-//W3C//DTD HTML 4.01 Transitional//EN"
					doctype-system="http://www.w3.org/TR/html4/loose.dtd"
				/>
				
			</xsl:when>
			
			<xsl:when test="$format = 'xhtml'">
			
				<xsl-out:output
					method="xml"
					encoding="{$text-encoding}"
					byte-order-mark="no"
					version="1.1"
					media-type="text/html"
					doctype-public="-//W3C//DTD XHTML 1.1//EN"
					doctype-system="http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"
				/>
				
			</xsl:when>
			
			<!--
				The LaTeX formats, however have a bunch of miscellaneous
				boilerplate that appears at the start of every documents, and
				requires more complex interleaving because of hyperref.
				Since we need to stuff this into a template later on, we
				define this using a callable template, so that we can do
				useful things like apply-templates within it (which wouldn't
				work if we just used a variable).
			-->
			<xsl:when test="$format = 'latex'">
			
				<xsl-out:output method="text" encoding="{$text-encoding}" media-type="text/plain" />	

				<!--
					Set to no if you want this to be included inside another
					document. Appears here because it's used in the document
					preamble.
				-->
				<xsl-out:param name="standalone">yes</xsl-out:param>
				
				<xsl-out:template name="latex-preamble">
\usepackage{mathpazo} % mathpple is deprecated
\usepackage[T1]{fontenc}
\usepackage{textcomp}
<xsl-out:apply-templates select="environment/latex-packages" />
% Safer to specify the hyperref options directly rather than relying on
% the default hyperref.cfg, as XeLaTeX seems to ignore it :(.
\usepackage[	pdftex,%
				pdfpagemode=UseNone,%
				colorlinks,%
				urlcolor=blue,%
				linkcolor=red,%
				breaklinks	]{hyperref}

\renewcommand{\ttdefault}{blg}
				</xsl-out:template>
				
			</xsl:when>
			
			<xsl:when test="$format = 'xelatex'">
			
				<xsl-out:output method="text" encoding="{$text-encoding}" media-type="text/plain" />	

				<!--
					Set to no if you want this to be included inside another
					document. Appears here because it's used in the document
					preamble.
				-->
				<xsl-out:param name="standalone">yes</xsl-out:param>
				
				<xsl-out:template name="latex-preamble">
\usepackage{fontspec}
\usepackage{xunicode}
\usepackage{xltxtra}
\usepackage{textcomp} % ???
<xsl-out:apply-templates select="environment/latex-packages" />
% Safer to specify the hyperref options directly rather than relying on
% the default hyperref.cfg, as XeLaTeX seems to ignore it :(.
\usepackage[	xetex,%
				pdfpagemode=UseNone,%
				colorlinks,%
				urlcolor=blue,%
				linkcolor=red,%
				breaklinks	]{hyperref}

\defaultfontfeatures{Mapping=tex-text}
\setmainfont{TeX Gyre Pagella}
\setmonofont[Scale=MatchLowercase]{Letter Gothic 12 Pitch}
				</xsl-out:template>
				
			</xsl:when>
			
			<!--
				No need for an otherwise, as weird formats will have already
				been trapped by the definition of the text-encoding variable
				above.
			-->
			
		</xsl:choose>
		
		<!--
			Next, output the main document body according to format.
			This is generally the same across similar formats.
		-->
		<xsl:choose>

			<xsl:when test="($format = 'html') or ($format = 'xhtml')">
			
				<!-- *** (X)HTML Output *** -->
				
				<!-- Old version: before using xsl:namespace-alias: -->
				<!--
				<xsl-out:element name="xsl:output">
					<xsl-out:attribute name="method">html</xsl-out:attribute>
					<xsl-out:attribute name="encoding">UTF-8</xsl-out:attribute>
					<xsl-out:attribute name="media-type">text/html</xsl-out:attribute>
					<xsl-out:attribute name="doctype-public">-//W3C//DTD HTML 4.01 Transitional//EN</xsl-out:attribute>
				</xsl-out:element>
				-->
				
				<!-- Default to PNG images for web dispay. -->
				<xsl-out:param name="image-format">png</xsl-out:param>

			<!-- Nope, includes can only appear as a child of xsl:stylesheet. -->
			<!-- <xsl-out:include href="xml2html-root.xsl" /> -->
				
				<xsl-out:template match="/document">
					<xsl-out:comment> THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT! </xsl-out:comment>
					<html>
						<head>
							<xsl-out:element name="link">
								<xsl-out:attribute name="rel">
									<xsl-out:text>Stylesheet</xsl-out:text>
								</xsl-out:attribute>
								<xsl-out:attribute name="href">
									<xsl-out:text>http://info-nts-12.otago.ac.nz/</xsl-out:text>
									<xsl-out:value-of select="$subject-code" />
									<xsl-out:value-of select="$paper-number" />
									<xsl-out:text>/db_styles.css</xsl-out:text>
								</xsl-out:attribute>
								<xsl-out:attribute name="type">
									<xsl-out:text>text/css</xsl-out:text>
								</xsl-out:attribute>
							</xsl-out:element>
							<xsl-out:element name="meta">
								<xsl-out:attribute name="http-equiv">
									<xsl-out:text>Content-type</xsl-out:text>
								</xsl-out:attribute>
								<xsl-out:attribute name="content">
									<xsl-out:text>text/html;charset=</xsl-out:text>
									<xsl:value-of select="$text-encoding" />
								</xsl-out:attribute>
							</xsl-out:element>
							<title>
								<xsl-out:apply-templates select="title" mode="preamble" />
							</title>
						</head>
						<body>
							<xsl-out:apply-templates />

							<!-- How best to approach this - certain elements that need special handling (e.g. title, author) shouldn't be passed through here as well. -->
							<!-- How about we just match certain elements that we know can be handled safely, e.g. sections, paragraphs, ...?  (...and their aliases?) -->
							<!-- Are introductions just another section, or should there be an introduction element? -->
							
							<!-- The solution is to get cleverer with our templates, e.g., multiple templates for <title> that have different match patterns (document/title, section/title). -->
							<!-- We also need to define an empty template for the <document-metadata> element so that its contents get ignored. -->
							<!-- Once these are done, we can just go apply-templates and forget about it. -->
							
							<hr />
							<!--
								Since HTML doesn't support footnotes as such, we
								instead include them as endnotes at the end of
								the document.
							-->
							<xsl-out:if test="count(//footnote) &gt; 0">
								<h3>Notes</h3>
								<xsl-out:apply-templates select="//footnote" mode="list" />
								<hr />
							</xsl-out:if>
							<address>
								<xsl-out:apply-templates select="copyright" />
								<xsl-out:apply-templates select="/document/@cvs-id" />
							</address>
						</body>
					</html>
				</xsl-out:template>
			</xsl:when>

			<xsl:when test="($format = 'latex') or ($format = 'xelatex')">
			
				<!-- Set to pdf if using PDFLaTeX, otherwise eps. -->
				<xsl-out:param name="image-format">pdf</xsl-out:param>

				<!-- *** LaTeX Source Output *** -->
				<!-- Should this produce a LaTeX source fragment or an entire valid source document? -->
				<xsl-out:template match="/document">
					<xsl-out:choose>

						<xsl-out:when test="$standalone = 'yes'">
% THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT!

\documentclass[12pt,a4paper]{article}

\usepackage[margin=1in]{geometry}
\usepackage{multirow}
\usepackage{graphicx}
\usepackage{verbatim} % needed for \verbatiminput
\usepackage{relalg} % needed for join operators
\usepackage{pifont}

<xsl-out:call-template name="latex-preamble" />

<xsl-out:apply-templates select="environment/latex-commands" />

\newenvironment{answer}{\par\vspace{0.5em}\itshape}{\normalfont\vspace{1.5em}}

<xsl-out:apply-templates select="title" mode="preamble" />
<xsl-out:apply-templates select="author" mode="preamble" />
<xsl-out:apply-templates select="date" mode="preamble" />

\begin{document}
	\maketitle

	<xsl-out:apply-templates />

	\vfill
	{\scriptsize \hfill \verb+<xsl-out:apply-templates select="/document/@cvs-id" />+}
\end{document}
						</xsl-out:when>
						<!-- Not standalone: -->
						<!-- Hmm, maybe this should go in format-master.xml... -->
						<xsl-out:when test="/document/@class = 'tutorial'">
							\tutorial{<xsl-out:apply-templates select="/document/title" mode="chapter" />}
							<!-- <xsl-out:apply-templates select="/tutorial/introduction" />
							<xsl-out:for-each select="/tutorial/section"> -->
							<xsl-out:apply-templates select="*[not(self::title)]" />
							<!-- </xsl-out:for-each> -->

						\vfill {\scriptsize \hfill \verb+<xsl-out:value-of select="/document/@cvs-id" />+}
						</xsl-out:when>
						<xsl-out:when test="/document/@class = 'laboratory'">
							\lab{<xsl-out:apply-templates select="/document/title" mode="chapter" />}
							<!-- <xsl-out:apply-templates select="/laboratory/introduction" />
							<xsl-out:for-each select="/tutorial/section"> -->
							<xsl-out:apply-templates select="*[not(self::title)]" />
							<!-- </xsl-out:for-each> -->

							\vfill {\scriptsize \hfill \verb+<xsl-out:value-of select="/document/@cvs-id" />+}
						</xsl-out:when>
						<xsl-out:otherwise>
							<!-- maybe we should assume that we're in a book documentclass and issue a \chapter here? -->
							\general{<xsl-out:apply-templates select="/document/title" mode="chapter" />}
							<xsl-out:apply-templates select="*[not(self::title)]" />
						</xsl-out:otherwise>
					</xsl-out:choose>
				</xsl-out:template>
				
			<!--
				<xsl-out:element name="xsl:output">
					<xsl-out:attribute name="method">text</xsl-out:attribute>
					<xsl-out:attribute name="encoding">UTF-8</xsl-out:attribute>
					<xsl-out:attribute name="media-type">text/plain</xsl-out:attribute>
				</xsl-out:element>
				-->
				
			</xsl:when>
			
			<!--
				No need for an otherwise, as weird formats will have already
				been trapped by the definition of the text-encoding variable
				above.
			-->
			
		</xsl:choose>


		<xsl:apply-templates />

		</xsl-out:stylesheet>
	</xsl:template>


	<!-- General-purpose template-producing template. -->
	<!--<xsl:template match="template"><![CDATA[<xsl-out:template name="]]><xsl-out:value-of select="name" /><![CDATA[" match="]]><xsl-out:value-of select="match" /><![CDATA[">]]><xsl-out:copy-of select="*[local-name(.)=$format]" /><![CDATA[</xsl-out:template>]]></xsl-out:template>-->

	<xsl:template match="template">
		<xsl-out:template>
		
			<!--
				Much easier to just copy all attributes across verbatim rather
				than copying specific named attributes, because we might want
				to use attributes that weren't originally anticipated.
				
				Might this be a problem in future?
			-->
			<xsl:copy-of select="@*" />
			
			<!-- Copy across code that is common to ALL formats. -->
			<xsl:copy-of select="common[not(@formats)]/node()" />
			
			<!-- Copy across code that is specific to the current format. -->
			<xsl:copy-of select="common[contains(@formats, concat('/', $format, '/'))]/node()" />
			<xsl:copy-of select="*[name(.)=$format]/node()" />
			
		</xsl-out:template>
	</xsl:template>



	
	<!--
		This template produces a template that calls another template, i.e.
		it implements a template alias.
		
		The generated template probably doesn't need a name, but we'll put one
		in anyway.
	-->

	<xsl:template match="alias">
		<xsl-out:template>
			<xsl:attribute name="name"><xsl:value-of select="@source" /></xsl:attribute>
			<xsl:attribute name="match"><xsl:value-of select="@source" /></xsl:attribute>
			<xsl-out:call-template>
				<xsl:attribute name="name"><xsl:value-of select="@target" /></xsl:attribute>
			</xsl-out:call-template>
		</xsl-out:template>
	</xsl:template>
	

	<!--
		This template produces a template for processing style-oriented markup,
		such as empahsis, foreign terms, and quotations.
	-->
	<!--
	<xsl:template match="d">
	</xsl-out:template match>
	-->

	<!--
		This template produces a template for processing an element that
		refers to a hyperlink.
	-->
	<xsl:template match="hyperlink">
	</xsl:template>
	
</xsl:stylesheet>