<?xml version="1.0" encoding="UTF-8"?>
<!-- $Id: xslidy.xsl 284 2007-03-12 22:15:57Z dret $ -->
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<!-- XSLidy - Erik Wilde (http://dret.net/netdret/) - http://dret.net/projects/xslidy/ -->
<!-- XSLidy is licensed under the GNU Lesser General Public License (LGPL). See http://creativecommons.org/licenses/LGPL/2.1/ for licensing details. -->
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://www.w3.org/1999/xhtml" xmlns:html="http://www.w3.org/1999/xhtml" xmlns:xslidy="http://dret.net/xmlns/xslidy/1" xpath-default-namespace="http://dret.net/xmlns/xslidy/1" exclude-result-prefixes="xs xslidy html">
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- this is the output method for xslidy presentations. -->
	<xsl:output name="slides" method="xhtml" encoding="UTF-8" doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" omit-xml-declaration="yes" indent="no" exclude-result-prefixes="xs xslidy html"/>
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- this is the output method for toc files. -->
	<xsl:output name="toc" encoding="US-ASCII" method="xhtml" indent="no" omit-xml-declaration="yes" exclude-result-prefixes="xs xslidy html"/>
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<xsl:strip-space elements="xslidy presentation part slide layout class list"/>
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- this parameter allows to generate only a specified set (comma-separated ids) of presentations rather than the complete set. -->
	<xsl:param name="presentation" select="'*'"/>
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- controls whether 'warning' messages should be output as well (default is 'error' messages only). -->
	<xsl:param name="messages" select="'error'"/>
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- controls whether slide notes should be included or removed. -->
	<xsl:param name="notes" select="'include'"/>
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<xsl:variable name="stdin" select="/"/>
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- these variables are used for indicating the current xslidy version in the generated output files. -->
	<xsl:variable name="version" select="'0.5'"/>
	<xsl:variable name="svnid" select="'$Id: xslidy.xsl 284 2007-03-12 22:15:57Z dret $'"/>
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<xsl:variable name="index-elements" select="/xslidy/index/category/@element"/>
	<xsl:key name="categoryKey" match="xslidy/index/category" use="@element"/>
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<xsl:key name="structureIdKey" match="presentation | part | slide" use="@id"/>
	<xsl:key name="counterKey" match="counter" use="@id"/>
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- the following variable is necessary for counting slides. basically, it is processing all non-external presentations with a tunnel parameter, so that any code using the slidenumber function can safely determine in which pass it is being called. (a "tunnel mode" be more elegant here, but unfortunately this is not supported by XSLT 2.0.) -->
	<xsl:variable name="presentations">
		<xsl:for-each select="/xslidy/presentation[empty(@external)]">
			<xsl:copy>
				<xsl:attribute name="id" select="generate-id()"/>
				<xsl:apply-templates select=".">
					<!-- this tunnel parameter is required for avoiding a circular variable definition in the slidenumber function. -->
					<xsl:with-param name="slide-count" select="'no'" tunnel="yes"/>
				</xsl:apply-templates>
			</xsl:copy>
		</xsl:for-each>
	</xsl:variable>
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- the following variables are for defining parameter defaults and their inclusion from "xslidy" processing instructions in the input document. please note that xslidy does not allow parameters to be passed as real xslt parameters. -->
	<xsl:variable name="param-defaults" xmlns="http://dret.net/xmlns/xslidy/1">
		<param name="counter-separator" value=": "/>
		<param name="counter-format" value="full"/>
		<param name="extension-file" value="html"/>
		<param name="extension-link" value="html"/>
		<param name="img-path" value="."/>
		<param name="link-author" value=""/>
		<param name="link-contents" value=""/>
		<param name="link-glossary" value=""/>
		<param name="link-home" value=""/>
		<param name="listing-class" value="listing"/>
		<param name="listing-path" value="."/>
		<param name="outline-class" value="outline"/>
		<param name="outline-title" value="Presentation Outline"/>
		<param name="outlink-mark" value="all"/>
		<param name="outlink-style" value="→ *"/>
		<param name="part-slide-count" value="1"/>
		<param name="part-slide-text" value=" (* Slides)"/>
		<param name="slidy-prefix" value="http://www.w3.org/Talks/Tools/Slidy/"/>
		<param name="style-uri" value="http://www.w3.org/Talks/Tools/Slidy/w3c-blue.css"/>
		<param name="xslidy-prefix" value="http://dret.net/projects/xslidy/latest/"/>
	</xsl:variable>
	<xsl:variable name="param-input" xmlns="http://dret.net/xmlns/xslidy/1">
		<xsl:for-each select="/processing-instruction('xslidy')">
			<!-- the following xpaths are not really readable, but xml/xpath's escape mechanisms make this necessary... -->
			<xsl:if test="matches(., concat('^\i\c*\s*=\s*(&quot;|', &quot;'&quot;, ').*\1\s*$'))">
				<param>
					<xsl:attribute name="name" select="replace(., concat('(\i\c*)\s*=\s*(&quot;|', &quot;'&quot;, ').*\2\s*$'), '$1')"/>
					<xsl:attribute name="value" select="replace(., concat('\i\c*\s*=\s*(&quot;|', &quot;'&quot;, ')(.*)\1\s*$'), '$2')"/>
				</param>
			</xsl:if>
		</xsl:for-each>
	</xsl:variable>
	<xsl:variable name="param-array" xmlns="http://dret.net/xmlns/xslidy/1">
		<xsl:for-each select="( $param-defaults | $param-input )/param">
			<xsl:choose>
				<xsl:when test="count(( $param-defaults | $param-input )/param[@name eq current()/@name]) gt 1">
					<xsl:if test=".. is $param-input and empty(preceding-sibling::param[@name eq current()/@name])">
						<xsl:copy>
							<xsl:for-each select="@*">
								<xsl:copy/>
							</xsl:for-each>
						</xsl:copy>
					</xsl:if>
				</xsl:when>
				<xsl:otherwise>
					<xsl:copy>
						<xsl:for-each select="@*">
							<xsl:copy/>
						</xsl:for-each>
					</xsl:copy>
				</xsl:otherwise>
			</xsl:choose>
		</xsl:for-each>
	</xsl:variable>
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<xsl:template match="/">
		<xsl:if test="exists(xslidy/@version) and ( $version ne xslidy/@version)">
			<xsl:call-template name="message">
				<xsl:with-param name="text" select="('&#xA;Transforming an', xslidy/@version, 'document with XSLidy', $version, 'may cause unexpected behavior...')"/>
				<xsl:with-param name="level" select="'warning'"/>
			</xsl:call-template>
		</xsl:if>
		<xsl:call-template name="message">
			<xsl:with-param name="text" select="('&#xA;Running XSLidy', $version, 'with the following options:')"/>
			<xsl:with-param name="level" select="'warning'"/>
		</xsl:call-template>
		<xsl:for-each select="$param-array/param">
			<xsl:sort select="@name"/>
			<xsl:call-template name="message">
				<xsl:with-param name="text" select="concat('  ', @name, ' = &quot;', @value, '&quot;')"/>
				<xsl:with-param name="level" select="'warning'"/>
			</xsl:call-template>
		</xsl:for-each>
		<xsl:call-template name="message">
			<xsl:with-param name="text" select="''"/>
			<xsl:with-param name="level" select="'warning'"/>
		</xsl:call-template>
		<!-- iterate over all toc elements and generate a file for each of them. -->
		<xsl:for-each select="/xslidy/toc[exists(@name)]">
			<xsl:call-template name="message">
				<xsl:with-param name="text" select="string(@name)"/>
			</xsl:call-template>
			<xsl:result-document format="toc" href="{@name}">
				<xsl:apply-templates>
					<xsl:with-param name="toc-id" select="@id" tunnel="yes"/>
				</xsl:apply-templates>
			</xsl:result-document>
		</xsl:for-each>
		<!-- a presentation is processed only if it has at least one slide or part, is not external, if all presentations are selected, or if it appears in the list of presentations to be generated. -->
		<xsl:for-each select="/xslidy/presentation[exists( slide | part )][empty(@external)][$presentation = '*' or @id = tokenize($presentation, '\s*,\s*')]">
			<xsl:variable name="content-slides" select="count(.//slide)"/>
			<xsl:variable name="total-slides" select="count($presentations/presentation[@id eq generate-id(current())]/html:div[contains(@class, 'slide')])"/>
			<xsl:call-template name="message">
				<xsl:with-param name="text" select="concat(xslidy:presentationfilename(.), ' (', $content-slides, '+', $total-slides - $content-slides, '=', $total-slides, ' slides)')"/>
			</xsl:call-template>
			<xsl:result-document format="slides" href="{xslidy:presentationfilename(.)}">
				<xsl:text>&#xA;</xsl:text>
				<xsl:comment>
					<xsl:text> Do not edit by hand! Generated by XSLidy </xsl:text>
					<xsl:value-of select="concat($version, ' (', $svnid, ')')"/>
					<xsl:text> on </xsl:text>
					<xsl:value-of select="current-dateTime()"/>
					<xsl:text> </xsl:text>
				</xsl:comment>
				<xsl:text>&#xA;</xsl:text>
				<xsl:comment> For more information about XSLidy please visit http://dret.net/projects/xslidy/. </xsl:comment>
				<html>
					<xsl:if test="xslidy:lang(.) ne ''">
						<xsl:attribute name="lang" select="xslidy:lang(.)"/>
						<xsl:attribute name="xml:lang" select="xslidy:lang(.)"/>
					</xsl:if>
					<head>
						<title>
							<xsl:value-of select="xslidy:title(., 'title', 'long', 'string')"/>
							<xsl:if test="string-length(xslidy:title(., 'author', 'long', 'string')) > 0">
								<xsl:text> ; </xsl:text>
								<xsl:value-of select="xslidy:title(., 'author', 'long', 'string')"/>
							</xsl:if>
							<xsl:if test="string-length(xslidy:title(., 'affiliation', 'long', 'string')) > 0">
								<xsl:text> ; </xsl:text>
								<xsl:value-of select="xslidy:title(., 'affiliation', 'long', 'string')"/>
							</xsl:if>
						</title>
						<!-- if a copyright notice is set explicitly, it will be used for the copyright notice instead of the default (date/author). -->
						<meta name="copyright" content="Copyright &#169; { if ( xslidy:title(., 'copyright', 'long', 'string') ne '' ) then xslidy:title(., 'copyright', 'long', 'string') else concat(xslidy:title(., 'date', 'long', 'string'), ' ', xslidy:title(., 'author', 'long', 'string'))}"/>
						<link rel="stylesheet" type="text/css" media="screen, projection" href="{ if ( xslidy:param('slidy-prefix') eq '' ) then '.' else xslidy:param('slidy-prefix') }{ if ( not(ends-with(xslidy:param('slidy-prefix'), '/')) ) then '/' else '' }slidy.css"/>
						<link rel="stylesheet" type="text/css" media="screen, projection" href="{xslidy:param('style-uri')}"/>
						<link rel="stylesheet" type="text/css" media="screen, projection, print" href="{ if ( xslidy:param('xslidy-prefix') eq '' ) then '.' else xslidy:param('xslidy-prefix') }{ if ( not(ends-with(xslidy:param('xslidy-prefix'), '/')) ) then '/' else '' }xslidy.css"/>
						<xsl:if test="xslidy:param('link-author') ne ''">
							<!-- if the user configured a link to a "author" document, include a link to it. -->
							<link rel="author" href="{xslidy:param('link-author')}"/>
						</xsl:if>
						<xsl:if test="xslidy:param('link-contents') ne ''">
							<!-- if the user configured a link to a "contents" document, include a link to it. -->
							<link rel="contents" href="{xslidy:param('link-contents')}" title="{xslidy:title(/xslidy, 'title', 'short', 'string')}"/>
						</xsl:if>
						<xsl:if test="xslidy:param('link-glossary') ne ''">
							<!-- if the user configured a link to a "glossary" document, include a link to it. -->
							<link rel="glossary" href="{xslidy:param('link-glossary')}"/>
						</xsl:if>
						<xsl:if test="xslidy:param('link-home') ne ''">
							<!-- if the user configured a link to a "home" document, include a link to it. -->
							<link rel="home" href="{xslidy:param('link-home')}" title="{xslidy:title(/xslidy, 'title', 'short', 'string')}"/>
						</xsl:if>
						<xsl:variable name="next" select="following-sibling::presentation[exists( slide | part | @external )][1]"/>
						<!-- if there is a "next" presentation, include a link to it. -->
						<xsl:if test="exists($next)">
							<link rel="next" href="{ if ( exists($next/@external) ) then $next/@external else xslidy:presentationlinkname($next) }" title="{xslidy:title($next, 'title', 'short', 'string')}"/>
						</xsl:if>
						<xsl:variable name="last" select="following-sibling::presentation[exists( slide | part | @external )][last()]"/>
						<!-- if there is a "last" presentation, include a link to it. -->
						<xsl:if test="exists($last)">
							<link rel="last" href="{ if ( exists($last/@external) ) then $last/@external else xslidy:presentationlinkname($last) }" title="{xslidy:title($last, 'title', 'short', 'string')}"/>
						</xsl:if>
						<xsl:variable name="prev" select="preceding-sibling::presentation[exists( slide | part | @external )][1]"/>
						<!-- if there is a "previous" presentation, include a link to it. -->
						<xsl:if test="exists($prev)">
							<link rel="prev" href="{ if ( exists($prev/@external) ) then $prev/@external else xslidy:presentationlinkname($prev) }" title="{xslidy:title($prev, 'title', 'short', 'string')}"/>
						</xsl:if>
						<xsl:variable name="first" select="preceding-sibling::presentation[exists( slide | part | @external )][last()]"/>
						<!-- if there is a "first" presentation, include a link to it. -->
						<xsl:if test="exists($first)">
							<link rel="start" href="{ if ( exists($first/@external) ) then $first/@external else xslidy:presentationlinkname($first) }" title="{xslidy:title($first, 'title', 'short', 'string')}"/>
							<!-- officially, this is called "start", but opera does not recognize "start" and instead needs this to be called "first". -->
							<link rel="first" href="{ if ( exists($first/@external) ) then $first/@external else xslidy:presentationlinkname($first) }" title="{xslidy:title($first, 'title', 'short', 'string')}"/>
						</xsl:if>
						<script type="text/javascript" src="{ if ( xslidy:param('slidy-prefix') eq '' ) then '.' else xslidy:param('slidy-prefix') }{if ( not(ends-with(xslidy:param('slidy-prefix'), '/')) ) then '/' else ''}slidy.js"/>
						<!-- style and script elements are copied from the xslidy element and the current presentation element. -->
						<xsl:for-each select="/xslidy/( style | script | html:style | html:script ) | style | script | html:style | html:script">
							<xsl:choose>
								<!-- style elements referring to external stylesheets must be mapped to xhtml <link rel="stylesheet" href="" .../>. -->
								<xsl:when test="local-name() eq 'style' and exists(@src)">
									<link rel="stylesheet" href="{@src}">
										<xsl:apply-templates select="@*[local-name() ne 'src']"/>
									</link>
								</xsl:when>
								<xsl:otherwise>
									<xsl:element name="{local-name()}">
										<xsl:apply-templates select="@* | node()"/>
									</xsl:element>
								</xsl:otherwise>
							</xsl:choose>
						</xsl:for-each>
					</head>
					<body>
						<xsl:apply-templates select="."/>
					</body>
				</html>
			</xsl:result-document>
		</xsl:for-each>
	</xsl:template>
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- the presentation template generates everything which is inside the html/body of a presentation (i.e., backgrounds and a bunch of slides). -->
	<xsl:template match="presentation">
		<!-- this variable contains the flattened layout structure for the current presentation. -->
		<xsl:variable name="layout">
			<xsl:apply-templates select="../layout | class" mode="layout"/>
			<!-- selecting "../layout" is according to the schema, selecting "class" supports people who (illegally) ignore the "layout/class" structure. -->
			<xsl:apply-templates select="../class" mode="layout"/>
		</xsl:variable>
		<xsl:for-each select="$layout/class">
			<div class="background{ if ( exists(@id) ) then concat(' ', @id) else '' }">
				<xsl:apply-templates/>
			</div>
		</xsl:for-each>
		<xsl:if test="exists(@cover)">
			<xsl:choose>
				<xsl:when test="empty($layout/slide[@cover eq current()/@cover])">
					<xsl:call-template name="message">
						<xsl:with-param name="text" select="concat('No layout/slide defined for cover=&quot;', @cover, '&quot;')"/>
					</xsl:call-template>
				</xsl:when>
				<xsl:otherwise>
					<xsl:if test="count($layout/slide[@cover eq current()/@cover]) gt 1">
						<xsl:call-template name="message">
							<xsl:with-param name="text" select="concat('More than one layout/slide defined for cover=&quot;', @cover, '&quot;')"/>
						</xsl:call-template>
					</xsl:if>
					<xsl:apply-templates select="$layout/slide[@cover eq current()/@cover][1]">
						<xsl:with-param name="layout" select="$layout" tunnel="yes"/>
						<xsl:with-param name="cover" select="true()"/>
						<xsl:with-param name="context" select="." tunnel="yes"/>
					</xsl:apply-templates>
				</xsl:otherwise>
			</xsl:choose>
		</xsl:if>
		<xsl:apply-templates select="part | slide">
			<xsl:with-param name="layout" select="$layout" tunnel="yes"/>
		</xsl:apply-templates>
	</xsl:template>
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- layout may point to layout documents via the @src attribute, or they may contain class elements (or both). -->
	<xsl:template match="layout" mode="layout">
		<xsl:if test="exists(@src)">
			<xsl:if test="empty(document(@src)//layout)">
				<xsl:call-template name="message">
					<xsl:with-param name="text" select="concat('&quot;', @src, '&quot; does not contain an element &quot;layout&quot;')"/>
				</xsl:call-template>
			</xsl:if>
			<xsl:apply-templates select="document(@src)//layout" mode="layout"/>
		</xsl:if>
		<xsl:apply-templates select="slide | class" mode="layout"/>
	</xsl:template>
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- layout/slide and class elements are copied into the new location ($layout). -->
	<xsl:template match="layout/slide | class" mode="layout">
		<xsl:if test="empty(parent::layout)">
			<xsl:call-template name="message">
				<xsl:with-param name="text" select="concat('&quot;class&quot; elements should be wrapped in &quot;layout&quot;, not in &quot;', local-name(parent::*), '&quot;')"/>
			</xsl:call-template>
		</xsl:if>
		<xsl:copy-of select="."/>
	</xsl:template>
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- the title group elements are expanded when found within a slide and empty (apart from attributes as defined by the schema). -->
	<xsl:template match="slide//*[local-name() = ('title', 'author', 'affiliation', 'date', 'copyright', 'location', 'occasion')][count(@* | node()) eq count(@level | @form)]">
		<xsl:param name="context" select="." tunnel="yes"/>
		<!-- set the @level parameter to the default value if not supplied. -->
		<xsl:variable name="level-value" select="if ( exists(@level) ) then string(@level) else 'slide'"/>
		<!-- for layout slides (which are invoked from the $layout variable, thus not from the input document), force $level to be either 'xslidy' or 'presentation' (default). the if () part would have been better using the "is" node comparison, but saxon seems to have a problem with that. -->
		<xsl:variable name="level" select="if ( (/) is $stdin ) then $level-value else if ( $level-value eq 'xslidy' ) then 'xslidy' else 'presentation'"/>
		<xsl:variable name="content" select="xslidy:title($context/ancestor-or-self::*[local-name() eq $level][1], local-name(), if ( @form eq 'short' ) then 'short' else 'long', 'nodes' )"/>
		<!-- if a text-based form has been asked for, generate a string, otherwise copy the nodes of the result. -->
		<xsl:choose>
			<xsl:when test="@form = ('text' , 'short')">
				<xsl:value-of select="$content"/>
			</xsl:when>
			<xsl:otherwise>
				<xsl:apply-templates select="$content/node()"/>
			</xsl:otherwise>
		</xsl:choose>
	</xsl:template>
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- part structures nested deeper than two levels are ignored. this could be overwritten by a more ambitious stylesheet... -->
	<xsl:template match="part">
		<xsl:apply-templates select="slide | part"/>
	</xsl:template>
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<xsl:template match="presentation/part | presentation/part/part">
		<xsl:param name="slide-count" tunnel="yes"/>
		<xsl:if test="not(@outline eq 'no')">
			<div class="slide{ if ( string-length(xslidy:param('outline-class')) gt 0 ) then concat(' ', xslidy:param('outline-class')) else '' }" id="{generate-id()}">
				<h1>
					<xsl:value-of select="xslidy:param('outline-title')"/>
					<!-- this text is invisible on the slide, but visible in the contents window of slidy. -->
					<span style="display : none">
						<xsl:value-of select="concat(' (', xslidy:title(., 'title', 'long', 'string'),')')"/>
					</span>
				</h1>
				<ol class="outline">
					<xsl:variable name="current" select="current()"/>
					<xsl:for-each select="ancestor::presentation/part">
						<li>
							<xsl:if test="( . is $current ) or ( . is $current/.. )">
								<xsl:attribute name="class">expand<xsl:if test=". is $current"> outline-current</xsl:if></xsl:attribute>
							</xsl:if>
							<xsl:choose>
								<xsl:when test=". is $current">
									<xsl:apply-templates select="xslidy:title(., 'title', 'long', 'nodes')/node()"/>
								</xsl:when>
								<xsl:otherwise>
									<!-- the if expression is required because a link to a non-outline part must point to the first resulting slide of that part. -->
									<a href="#({xslidy:slidenumber( if ( not(@outline eq 'no') ) then . else ( descendant::slide | descendant::part[not(@outline eq 'no')] )[1], $slide-count)})" title="go to part &quot;{xslidy:title(., 'title', 'long', 'string')}&quot;">
										<xsl:apply-templates select="xslidy:title(., 'title', 'long', 'nodes')/node()"/>
									</a>
								</xsl:otherwise>
							</xsl:choose>
							<xsl:if test="xslidy:param('part-slide-count') = ('all', '1', '2')">
								<xsl:value-of select="concat(substring-before(xslidy:param('part-slide-text'), '*'), count(descendant::slide), substring-after(xslidy:param('part-slide-text'), '*'))"/>
							</xsl:if>
							<xsl:if test="exists(part)">
								<ol>
									<xsl:for-each select="part">
										<li>
											<xsl:if test=". is $current">
												<xsl:attribute name="class" select="'outline-current'"/>
											</xsl:if>
											<xsl:choose>
												<xsl:when test=". is $current">
													<xsl:apply-templates select="xslidy:title(., 'title', 'long', 'nodes')/node()"/>
												</xsl:when>
												<xsl:otherwise>
													<a href="#({xslidy:slidenumber(., $slide-count)})" title="go to part &quot;{xslidy:title(., 'title', 'long', 'string')}&quot;">
														<xsl:apply-templates select="xslidy:title(., 'title', 'long', 'nodes')/node()"/>
													</a>
												</xsl:otherwise>
											</xsl:choose>
											<xsl:if test="xslidy:param('part-slide-count') = ('all', '2')">
												<xsl:value-of select="concat(substring-before(xslidy:param('part-slide-text'), '*'), count(descendant::slide), substring-after(xslidy:param('part-slide-text'), '*'))"/>
											</xsl:if>
										</li>
									</xsl:for-each>
								</ol>
							</xsl:if>
						</li>
					</xsl:for-each>
				</ol>
			</div>
		</xsl:if>
		<!-- after generating the outline slide (if requested), continue by processing all slides and parts which are children of the part. -->
		<xsl:apply-templates select="slide | part"/>
	</xsl:template>
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- map slides to an enclosing div containing everything which is contained in the slide element. -->
	<xsl:template match="slide">
		<xsl:param name="layout" tunnel="yes"/>
		<xsl:param name="cover" select="false()"/>
		<xsl:if test="exists(@class)">
			<!-- the following loop iterates over all xs:tokens found in @class (the regex is the xs:token definition from the schema for schemas) and issues warnings if they refer to undefined classes. -->
			<xsl:analyze-string select="@class" regex="(\i\c*)">
				<xsl:matching-substring>
					<xsl:if test="empty($layout/class[@id eq regex-group(1)])">
						<xsl:call-template name="message">
							<xsl:with-param name="text" select="concat('Found slide with undefined class=&quot;', regex-group(1), '&quot; (but there may be a CSS class)')"/>
							<xsl:with-param name="level" select="'warning'"/>
						</xsl:call-template>
					</xsl:if>
				</xsl:matching-substring>
			</xsl:analyze-string>
		</xsl:if>
		<!-- if the slide is the first child of a no-outline part, it should get the part's id, too. -->
		<xsl:variable name="no-outline-part-parent" select=".[empty(preceding-sibling::slide)]/parent::part[@outline eq 'no']"/>
		<!-- the @class information is simply copied through. -->
		<div class="slide{ if ( exists(@class) ) then concat(' ', normalize-space(@class)) else ''}" id="{generate-id()}{ if ( exists($no-outline-part-parent) )  then concat(' ', generate-id($no-outline-part-parent)) else '' }">
			<xsl:apply-templates select="node()"/>
		</div>
	</xsl:template>
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- non-empty slide/title elements are mapped to html h1 elements (which are then selected by slidy css magic). -->
	<xsl:template match="slide/title[exists(node())]">
		<h1>
			<xsl:apply-templates select="@*[not(local-name() = ('short'))] | node()"/>
		</h1>
	</xsl:template>
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- links are mapped to html links, they may be used within or across presentations. -->
	<xsl:template match="link">
		<xsl:param name="slide-count" tunnel="yes"/>
		<xsl:choose>
			<xsl:when test="empty(key('structureIdKey', @href))">
				<xsl:call-template name="message">
					<xsl:with-param name="text" select="concat('There is no ( presentation | part | slide ) with id=&quot;', @href, '&quot;')"/>
				</xsl:call-template>
			</xsl:when>
			<xsl:when test="count(key('structureIdKey', @href)) > 1">
				<xsl:call-template name="message">
					<xsl:with-param name="text" select="concat('There is more than one ( presentation | part | slide ) with id=&quot;', @href, '&quot;')"/>
				</xsl:call-template>
			</xsl:when>
			<xsl:otherwise>
				<xsl:variable name="presentation-name" select="if ( ancestor::presentation is key('structureIdKey', @href)/ancestor-or-self::presentation ) then '' else xslidy:presentationlinkname(key('structureIdKey', @href)/ancestor-or-self::presentation)"/>
				<a href="{ if ( string-length($presentation-name) eq 0 ) then '' else $presentation-name }{ if ( exists(key('structureIdKey', @href)/self::presentation) ) then '' else concat('#(', xslidy:slidenumber( if ( not(@outline eq 'no') ) then key('structureIdKey', @href) else key('structureIdKey', @href)/( descendant::slide | descendant::part[not(@outline eq 'no')] )[1], $slide-count), ')')}">
					<!-- if there the outlink-style specifies a class and there is no class attribute, set it using the outlink-style. -->
					<xsl:if test="xslidy:param('outlink-mark') = ('link', 'all') and matches(xslidy:param('outlink-style'), 'class(.*)') and empty(@class)">
						<xsl:attribute name="class" select="substring-before(substring-after(xslidy:outlink-style(), 'class('), ')')"/>
					</xsl:if>
					<!-- copy class and style attributes, if present. -->
					<xsl:copy-of select="@class | @style"/>
					<xsl:choose>
						<!-- if the link contains text, set the link target's title as the a element's tool tip. -->
						<xsl:when test="exists(node())">
							<xsl:attribute name="title" select="xslidy:title(key('structureIdKey', @href), 'title', 'long', 'string')"/>
						</xsl:when>
						<!-- if the link is empty but cross-presentation, set the target presentation's title as the a element's tool tip. -->
						<xsl:when test="not(ancestor::presentation is key('structureIdKey', @href)/ancestor-or-self::presentation)">
							<xsl:attribute name="title" select="xslidy:title(key('structureIdKey', @href)/ancestor-or-self::presentation, 'title', 'long', 'string')"/>
						</xsl:when>
					</xsl:choose>
					<!-- same test as after the link contents. -->
					<xsl:if test="(string-length($presentation-name) ne 0) and (xslidy:param('outlink-mark') = ('link', 'all')) and not(matches(xslidy:param('outlink-style'), 'class(.*)'))">
						<xsl:copy-of select="substring-before(xslidy:outlink-style(), '*')"/>
					</xsl:if>
					<xsl:choose>
						<xsl:when test="empty(node())">
							<xsl:apply-templates select="xslidy:title(key('structureIdKey', @href), 'title', 'long', 'nodes')/node()"/>
						</xsl:when>
						<xsl:otherwise>
							<xsl:apply-templates/>
						</xsl:otherwise>
					</xsl:choose>
					<!-- same test as before the link contents. -->
					<xsl:if test="(string-length($presentation-name) ne 0) and (xslidy:param('outlink-mark') = ('link', 'all')) and not(matches(xslidy:param('outlink-style'), 'class(.*)'))">
						<xsl:copy-of select="substring-after(xslidy:outlink-style(), '*')"/>
					</xsl:if>
				</a>
			</xsl:otherwise>
		</xsl:choose>
	</xsl:template>
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- links are mapped to html links, they may be used within or across presentations. -->
	<xsl:template match="a | html:a">
		<xsl:element name="a" namespace="http://www.w3.org/1999/xhtml">
			<!-- if there the outlink-style specifies a class and the link is absolute (roughly, the test is not 100% reliable) and there is no class attribute, set it using the outlink-style. -->
			<xsl:if test="xslidy:param('outlink-mark') = ('a', 'all') and ( starts-with(@href, 'http:') or starts-with(@href, 'https:') or starts-with(@href, 'ftp:') or starts-with(@href, 'mailto:') or not(contains(@href, ':')) )  and matches(xslidy:param('outlink-style'), 'class(.*)') and empty(@class)">
				<xsl:attribute name="class" select="substring-before(substring-after(xslidy:outlink-style(), 'class('), ')')"/>
			</xsl:if>
			<xsl:apply-templates select="@*"/>
			<!-- if the title attribute is not set by the user, add a title containing the link's target uri. -->
			<xsl:if test="empty(@title)">
				<xsl:attribute name="title" select="@href"/>
			</xsl:if>
			<!-- only insert the outlink-style text before and after the a element if the element contains non-whitespace text nodes, if required by the parameter setting, if either a relative uri or an explicit http link, and if the outlink-style is a text style. -->
			<xsl:if test="( normalize-space(string(.)) ne '' ) and xslidy:param('outlink-mark') = ('a', 'all') and ( starts-with(@href, 'http:') or not(contains(@href, ':'))  and not(matches(xslidy:param('outlink-style'), 'class(.*)')))">
				<xsl:copy-of select="substring-before(xslidy:outlink-style(), '*')"/>
			</xsl:if>
			<xsl:apply-templates select="node()"/>
			<xsl:if test="( normalize-space(string(.)) ne '' ) and xslidy:param('outlink-mark') = ('a', 'all') and ( starts-with(@href, 'http:') or not(contains(@href, ':'))  and not(matches(xslidy:param('outlink-style'), 'class(.*)')))">
				<xsl:copy-of select="substring-after(xslidy:outlink-style(), '*')"/>
			</xsl:if>
		</xsl:element>
	</xsl:template>
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- the listing element includes text files (optionally only parts of them) and by default creates a link to the original file. -->
	<xsl:template match="listing">
		<xsl:variable name="filename" select="xslidy:prefixed-uri(., xslidy:param('listing-path'), @src)"/>
		<xsl:variable name="fileuri" select="resolve-uri($filename, document-uri(/))"/>
		<xsl:variable name="listing">
			<pre class="{xslidy:param('listing-class')}{ if ( exists(@class) ) then concat(' ', @class) else '' }">
				<xsl:choose>
					<xsl:when test="if ( exists(@encoding) ) then unparsed-text-available($fileuri, @encoding) else unparsed-text-available($fileuri)">
						<xsl:choose>
							<xsl:when test="not(matches(@line, '\d+(\-\d+)?'))">
								<!-- tokenize the input file by lines and output them as newline-separated list of strings. -->
								<xsl:variable name="listing" select="string-join(tokenize( if ( exists(@encoding) ) then unparsed-text($fileuri, @encoding) else unparsed-text($fileuri), '\r?\n'), '&#xa;')"/>
								<xsl:value-of select="if (@tab eq 'retain' ) then $listing else replace($listing, '\t', ' ')"/>
							</xsl:when>
							<xsl:otherwise>
								<!-- tokenize the input file by lines, filter the specified lines by @lines, and output them as newline-separated list of strings. -->
								<xsl:variable name="listing" select="string-join(tokenize( if ( exists(@encoding) ) then unparsed-text($fileuri, @encoding) else unparsed-text($fileuri), '\r?\n')[(position() ge number(tokenize(current()/@line, '\-')[1])) and (position() le number(tokenize(current()/@line, '\-')[last()]))], '&#xa;')"/>
								<xsl:value-of select="if (@tab eq 'retain' ) then $listing else replace($listing, '\t', ' ')"/>
							</xsl:otherwise>
						</xsl:choose>
					</xsl:when>
					<xsl:otherwise>
						<xsl:variable name="filenotfound" select="concat('Could not find listing file &quot;', $filename, '&quot;')"/>
						<xsl:value-of select="concat('[ ', $filenotfound, ' ]')"/>
						<xsl:call-template name="message">
							<xsl:with-param name="text" select="$filenotfound"/>
							<xsl:with-param name="level" select="'warning'"/>
						</xsl:call-template>
					</xsl:otherwise>
				</xsl:choose>
			</pre>
		</xsl:variable>
		<xsl:choose>
			<xsl:when test="exists(@href) and (@href eq '')">
				<!-- if there is an empty @href, do not generate a link. -->
				<xsl:copy-of select="$listing/html:pre"/>
			</xsl:when>
			<xsl:when test="exists(@href)">
				<!-- if the listing specifies a non-empty @href, a link to this URI is generated. -->
				<a href="{@href}" title="{ if ( exists(@title) ) then @title else @href }">
					<xsl:copy-of select="$listing/html:pre"/>
				</a>
			</xsl:when>
			<xsl:otherwise>
				<!-- if the listing specifies a valid line range, this is mapped to the correspondig text fragment identifier. -->
				<a href="{$filename}{ if ( matches(@line, '\d+(\-\d+)?') ) then concat('#line=', number(tokenize(@line, '\-')[1])-1, ',', number(tokenize(@line, '\-')[last()])) else '' }" title="{ if ( exists(@title) ) then @title else concat(@src, if ( matches(@line, '\d+(\-\d+)?') ) then concat(' (line ', @line, ')') else '' )}">
					<xsl:copy-of select="$listing/html:pre"/>
				</a>
			</xsl:otherwise>
		</xsl:choose>
	</xsl:template>
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- lists in xslidy are simply there to enable nested lists without the mixed content structure imposed by html's lists. -->
	<xsl:template match="list">
		<xsl:element name="{ if ( @type eq 'ol' ) then 'ol' else 'ul' }" namespace="http://www.w3.org/1999/xhtml">
			<xsl:apply-templates select="@*[not(local-name() eq 'type')] | li"/>
		</xsl:element>
	</xsl:template>
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- xslidy attempts to "fix lists" by moving non-li elements into li elements (as required by xhtml). thus, non-li children are taken care of in the handling of li elements, and they must be ignored here. -->
	<xsl:template match="ul | ol | html:ul | html:ol">
		<xsl:element name="{local-name()}" namespace="http://www.w3.org/1999/xhtml">
			<xsl:apply-templates select="@* | li"/>
		</xsl:element>
	</xsl:template>
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- list/li must be handled explicitly to move content from "between" li elements "into" (ul|ol)/li. this template also matches li elements for regular html lists (ul|ol) and therefore "fixes" illegally structured html lists. -->
	<xsl:template match="li | html:li">
		<xsl:element name="li" namespace="http://www.w3.org/1999/xhtml">
			<!-- the following xpath selects the li attributes, the li child nodes, and all elements following the li element up to the next li sibling. -->
			<xsl:apply-templates select="@* | node() | ( following-sibling::* intersect  ( if ( exists(following-sibling::*[local-name() eq 'li'][1]) ) then following-sibling::*[local-name() eq 'li'][1]/preceding-sibling::* else following-sibling::* ))"/>
		</xsl:element>
	</xsl:template>
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- replaces an img's @src with a prefixed uri if requested by the img-src-prefix processing instruction. -->
	<xsl:template match="img/@src | html:img/@src">
		<xsl:attribute name="src">
			<xsl:value-of select="xslidy:prefixed-uri(., xslidy:param('img-path'), string(.))"/>
		</xsl:attribute>
	</xsl:template>
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- if an image is not a link (i.e., has no @href attribute) and is not contained in a link, turn it into a link to its @src. -->
	<xsl:template match="img[empty(@href)][empty(ancestor::a | ancestor::html:a)] | html:img[empty(@href)][empty(ancestor::a | ancestor::html:a)]">
		<a class="img">
			<xsl:attribute name="href">
				<!-- the @src attribute must be processed (not copied!) because it may need to be prefixed with the img-src-prefix. -->
				<xsl:apply-templates select="@src"/>
			</xsl:attribute>
			<xsl:if test="empty(@title)">
				<!-- if the img does not specify a @title, provide a default text as the link's @title. -->
				<xsl:attribute name="title" select="'View Image'"/>
			</xsl:if>
			<img>
				<xsl:apply-templates select="@*"/>
				<xsl:if test="empty(@alt) and exists(@title)">
					<!-- if there is no @alt attribute, but there is a @title attribute, reuse the @title attribute's value and create an @alt attribute. -->
					<xsl:attribute name="alt" select="@title"/>
				</xsl:if>
			</img>
		</a>
	</xsl:template>
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- return a prefixed uri if the uri contains no slash and the prefix is not empty or '.' (the default). -->
	<xsl:function name="xslidy:prefixed-uri">
		<xsl:param name="context"/>
		<xsl:param name="prefix"/>
		<xsl:param name="uri"/>
		<xsl:variable name="return">
			<xsl:if test="not(contains($uri, '/')) and not($prefix = ('', '.'))">
				<xsl:value-of select="replace($prefix, '\*', xslidy:presentationname($context/ancestor-or-self::presentation[1]))"/>
				<xsl:if test="not(ends-with($prefix, '/'))">/</xsl:if>
			</xsl:if>
			<xsl:value-of select="$uri"/>
		</xsl:variable>
		<xsl:sequence select="string($return)"/>
	</xsl:function>
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- return the closest xml:lang attribute value (if valid) or an empty string. -->
	<xsl:function name="xslidy:lang">
		<xsl:param name="context"/>
		<xsl:variable name="lang" select="$context/ancestor-or-self::*[exists(@xml:lang)][1]/@xml:lang"/>
		<!-- the weird regex is the xs:language pattern from the schema for schemas. -->
		<xsl:value-of select="if ( matches($lang, '^[a-zA-Z]{1,8}(-[a-zA-Z0-9]{1,8})*$') ) then $lang else ''"/>
	</xsl:function>
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- return the most recent value of one of the titleGroup elements from the xslidy schema. return the short value if asked for and present, otherwise return the element's content. if $value is set to 'string', return the string value, otherwise (set to 'nodes') return the sequence of nodes found in the titleGroup. -->
	<xsl:function name="xslidy:title">
		<xsl:param name="context"/>
		<xsl:param name="name"/>
		<xsl:param name="form"/>
		<xsl:param name="value"/>
		<xsl:variable name="title" select="($context/ancestor-or-self::*/*[local-name() eq $name])[last()]"/>
		<xsl:copy-of select="if ( ($form eq 'short') and exists($title/@short) ) then string($title/@short) else if ( $value eq 'nodes' ) then $title else normalize-space(string-join($title/descendant-or-self::text(), ''))"/>
	</xsl:function>
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- return a parameter value based on the parameter name. -->
	<xsl:function name="xslidy:param">
		<xsl:param name="name"/>
		<xsl:value-of select="$param-array/param[@name eq $name]/@value"/>
	</xsl:function>
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- returns the name of the presentation based on the context and the position. if there is a @name, take the @name, if not, take the @id, if there is no @id, generate a name. -->
	<xsl:function name="xslidy:presentationname">
		<xsl:param name="presentation"/>
		<xsl:value-of select="if ( exists($presentation/@name) ) then $presentation/@name else if ( exists($presentation/@id) ) then $presentation/@id else concat('presentation-', count($presentation/preceding::presentation)+1)"/>
	</xsl:function>
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- returns the name of the presentation based on the context and the position. -->
	<xsl:function name="xslidy:presentationfilename">
		<xsl:param name="context"/>
		<xsl:value-of select="concat(xslidy:presentationname($context/ancestor-or-self::presentation[1]), if ( xslidy:param('extension-file') eq '' or starts-with(xslidy:param('extension-file'), '.') ) then '' else '.', xslidy:param('extension-file'))"/>
	</xsl:function>
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- returns the name of the presentation based on the context and the position. -->
	<xsl:function name="xslidy:presentationlinkname">
		<xsl:param name="context"/>
		<xsl:variable name="presentation" select="$context/ancestor-or-self::presentation[1]"/>
		<!-- if no @external attribute is present for the presentation, the linkname is computed; otherwise it is the value of the @external attribute. -->
		<xsl:value-of select="if ( empty($presentation/@external) ) then concat(xslidy:presentationname($presentation), if ( xslidy:param('extension-link') eq '' or starts-with(xslidy:param('extension-link'), '.') ) then '' else '.', xslidy:param('extension-link')) else $presentation/@external"/>
	</xsl:function>
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- returns the value of the outlink-style parameter. -->
	<xsl:function name="xslidy:outlink-style">
		<xsl:value-of select="xslidy:param('outlink-style')"/>
	</xsl:function>
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- returns the number of the slide or a part's outline slide within its presentation (necessary for links). -->
	<xsl:function name="xslidy:slidenumber">
		<xsl:param name="context"/>
		<xsl:param name="slide-count"/>
		<!-- the slide count counts the effective slides in the generated variable and thus only works if being called from outside the $presentations variable. this is checked with the $slide-count parameter, which must be set to the $slide-count tunnel parameter value in the calling template. -->
		<xsl:if test="$slide-count ne 'no'">
			<!-- the predicate tests whether @id contains the generate-id() value (simple substring matching broke because of ids being substrings of others). -->
			<xsl:variable name="current-slide" select="$presentations//html:div[generate-id($context/ancestor-or-self::*[local-name() = ('part', 'slide')][1]) = tokenize(@id, ' ')]"/>
			<xsl:value-of select="count($current-slide/preceding::html:div[contains(@class, 'slide')][ancestor::presentation is $current-slide/ancestor::presentation]) + 1"/>
		</xsl:if>
	</xsl:function>
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- move every element which is not handled otherwise from the xslidy namespace to the xhtml namespace. before doing that, check wether the element is an indexing element and has to be mapped to an xhtml span. -->
	<xsl:template match="xslidy:*">
		<xsl:choose>
			<xsl:when test="local-name() = $index-elements">
				<!-- if the element is listed as an indexing element, it is mapped to a span with the @class set as specified. -->
				<span class="{key('categoryKey', local-name(), $stdin)/@class}">
					<xsl:apply-templates select="node()"/>
				</span>
			</xsl:when>
			<xsl:otherwise>
				<!-- otherwise, the element is simply copied through, assuming that it is an xhtml element. -->
				<xsl:element name="{local-name()}" namespace="http://www.w3.org/1999/xhtml">
					<xsl:apply-templates select="@* | node()"/>
				</xsl:element>
			</xsl:otherwise>
		</xsl:choose>
	</xsl:template>
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- if an element carries an @href attribute, the @href is moved to an a element which contains the original element. if there is a @title attribute, this is also moved. the list of element names in the template's match pattern is the list of html elements which may carry an @href attribute. -->
	<xsl:template match="*[@href][not(local-name() = ('a', 'link', 'area', 'base', 'listing'))]">
		<a href="{@href}" class="{local-name()}">
			<xsl:if test="exists(@title)">
				<xsl:copy-of select="@title"/>
			</xsl:if>
			<xsl:element name="{local-name()}" namespace="{ if ( namespace-uri() != '' ) then namespace-uri() else '' }">
				<xsl:apply-templates select="@*[not(local-name() = ('href' , 'title'))] | node()"/>
			</xsl:element>
		</a>
	</xsl:template>
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- carefully copy element names (avoiding that unnecessary namespace nodes are dragged along to the result document). -->
	<xsl:template match="*">
		<xsl:element name="{local-name()}" namespace="{ if ( namespace-uri() != '' ) then namespace-uri() else '' }">
			<xsl:apply-templates select="@* | node()"/>
		</xsl:element>
	</xsl:template>
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- recursively copy all nodes which are not handled by other templates. -->
	<xsl:template match="@* | text() | comment() | processing-instruction()">
		<xsl:copy/>
	</xsl:template>
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- for for-each-presentation elements in toc elements, loop over all presentation elements to generate the toc file. -->
	<xsl:template match="toc//for-each-presentation">
		<xsl:variable name="context" select="."/>
		<xsl:for-each select="/xslidy/presentation">
			<xsl:apply-templates select="$context/*">
				<xsl:with-param name="context" select="." tunnel="yes"/>
			</xsl:apply-templates>
		</xsl:for-each>
	</xsl:template>
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- for toc elements in toc elements, replace the toc element with the corresponding toc elements content from the presentation. -->
	<xsl:template match="toc//toc">
		<xsl:param name="context" tunnel="yes"/>
		<xsl:param name="toc-id" tunnel="yes"/>
		<xsl:apply-templates select="$context/toc[@id eq ( if (exists(current()/@id)) then current()/@id else $toc-id )]/node()"/>
	</xsl:template>
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- this enables conditional processing in tocs, only generating the if-toc's content if the correspondig toc is present. -->
	<xsl:template match="toc//if-toc">
		<xsl:param name="context" tunnel="yes"/>
		<xsl:param name="toc-id" tunnel="yes"/>
		<xsl:choose>
			<xsl:when test="exists($context/toc[@id eq ( if (exists(current()/@id)) then current()/@id else $toc-id )])">
				<xsl:apply-templates select="node()"/>
			</xsl:when>
		</xsl:choose>
	</xsl:template>
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- note elements are mapped to a div (unless $notes has been set to 'remove' them), the note's contents are processed as usual. -->
	<xsl:template match="slide//note">
		<xsl:choose>
			<xsl:when test="$notes eq 'include'">
				<!-- this is the class that must be picked up in the javascript and css code for properly handling notes. -->
				<div class="note">
					<xsl:apply-templates select="node()"/>
				</div>
			</xsl:when>
			<xsl:otherwise>
				<!-- everything other than 'include' is treated as if 'remove' had been specified. -->
				<xsl:comment> an xslidy note has been removed here </xsl:comment>
			</xsl:otherwise>
		</xsl:choose>
	</xsl:template>
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- for toc elements in presentation content, replace the toc element with the corresponding toc elements content from the presentation. -->
	<xsl:template match="slide//toc | part//toc">
		<xsl:apply-templates select="ancestor::presentation/toc[@id eq current()/@id]/node()"/>
	</xsl:template>
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- a presentation-link generates the link to the current presentation within a for-each-presentation structure (if the presentation is empty, it produces nothing). -->
	<xsl:template match="for-each-presentation//presentation-link">
		<xsl:param name="context" tunnel="yes"/>
		<xsl:variable name="link-uri" select="concat( if ( exists(@prefix) and empty($context/ancestor-or-self::presentation/@external) ) then @prefix else '' , xslidy:presentationlinkname($context))"/>
		<xsl:choose>
			<!-- do not produce a presentation-link if the presentation is empty and not external. -->
			<xsl:when test="empty($context/ancestor-or-self::presentation//(slide | part)) and empty($context/ancestor-or-self::presentation[@external])"/>
			<xsl:when test="exists(@element) and @element eq ''">
				<!-- if the presentation-link explicitly requests to not produce a link element, only the $link-uri is generated as text -->
				<xsl:value-of select="$link-uri"/>
			</xsl:when>
			<xsl:otherwise>
				<!-- if no @element or a non-empty @element has been specified, generate an element for the link. -->
				<xsl:element name="{ if ( exists(@element) ) then @element else 'a' }">
					<xsl:attribute name="{ if ( exists(@attribute) ) then @attribute else 'href' }" select="$link-uri"/>
					<!-- the contents of the presentation-link are processed as usual. -->
					<xsl:apply-templates select="@*[not(local-name() = ('element', 'attribute', 'prefix'))] | node()"/>
				</xsl:element>
			</xsl:otherwise>
		</xsl:choose>
	</xsl:template>
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- when appearing in a toc element, the title group elements must be treated in a special way. -->
	<xsl:template match="toc//*[local-name() = ('title', 'author', 'affiliation', 'date', 'copyright', 'location', 'occasion')][count(@* | node()) eq count(@level | @form)]">
		<xsl:param name="context" tunnel="yes"/>
		<xsl:variable name="content" select="xslidy:title($context, local-name(), if ( @form eq 'short' ) then 'short' else 'long', 'nodes' )"/>
		<!-- if a text-based form has been asked for, generate a string, otherwise copy the nodes of the result. -->
		<xsl:choose>
			<xsl:when test="@form = ('text' , 'short')">
				<xsl:value-of select="$content"/>
			</xsl:when>
			<xsl:otherwise>
				<xsl:apply-templates select="$content/node()"/>
			</xsl:otherwise>
		</xsl:choose>
	</xsl:template>
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- the slides element generates the number of slides in a presentation within a toc element. -->
	<xsl:template match="toc//slides">
		<xsl:param name="context" tunnel="yes"/>
		<!-- get the expanded presentation fom $presentations and count the number of slide divs inside this presentation. -->
		<xsl:variable name="slides" select="count($presentations/presentation[@id eq generate-id($context)]/descendant::html:div[contains(@class, 'slide')])"/>
		<!-- only produce a slide count if the presentation is not empty and not external. -->
		<xsl:if test="exists($context/ancestor-or-self::presentation//(slide | part)) and not(exists($context/ancestor-or-self::presentation[@external]))">
			<!-- take the element content and replace the first asterisk with the slide count. -->
			<xsl:value-of select="replace(text(), '\*', string($slides))"/>
		</xsl:if>
	</xsl:template>
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- the counter element is used for setting counters (@id) as well as for referencing them (@ref). -->
	<xsl:template match="presentation//counter">
		<xsl:param name="slide-count" tunnel="yes"/>
		<!-- get the expanded presentation fom $presentations and count the number of slide divs inside this presentation. -->
		<xsl:choose>
			<xsl:when test="exists(@ref) and exists(@id)">
				<xsl:call-template name="message">
					<xsl:with-param name="text" select="'@ref and @id are not allowed on the same &lt;counter>'"/>
					<xsl:with-param name="level" select="'error'"/>
				</xsl:call-template>
				<xsl:text>???</xsl:text>
			</xsl:when>
			<xsl:when test="not(exists(@ref | @id))">
				<xsl:call-template name="message">
					<xsl:with-param name="text" select="'one of @ref and @id must be present on a &lt;counter>'"/>
					<xsl:with-param name="level" select="'error'"/>
				</xsl:call-template>
				<xsl:text>???</xsl:text>
			</xsl:when>
			<xsl:when test="exists(@id)">
				<xsl:choose>
					<xsl:when test="exists(node()) and exists(@title)">
						<xsl:call-template name="message">
							<xsl:with-param name="text" select="'a &lt;counter> may have @title or content, but not both'"/>
							<xsl:with-param name="level" select="'error'"/>
						</xsl:call-template>
						<xsl:text>???</xsl:text>
					</xsl:when>
					<xsl:when test="exists(node())">
						<xsl:value-of select="xslidy:print_counter(., @form)"/>
						<xsl:value-of select="xslidy:param('counter-separator')"/>
						<xsl:copy-of select="node()"/>
					</xsl:when>
					<xsl:when test="exists(@title)">
						<span title="{@title}">
							<xsl:value-of select="xslidy:print_counter(., @form)"/>
						</span>
					</xsl:when>
					<xsl:otherwise>
						<xsl:value-of select="xslidy:print_counter(., @form)"/>
					</xsl:otherwise>
				</xsl:choose>
			</xsl:when>
			<xsl:when test="exists(@ref)">
				<xsl:variable name="ref-target" select="key('counterKey', @ref)[@name eq current()/@name]"/>
				<!-- find ount whether the counter's @id has been set in another presentation.  -->
				<xsl:variable name="presentation-name" select="if ( ancestor::presentation is $ref-target/ancestor::presentation ) then '' else xslidy:presentationlinkname(key('counterKey', @ref)[@name eq current()/@name]/ancestor::presentation)"/>
				<a href="{ if ( string-length($presentation-name) eq 0 ) then '' else $presentation-name }#({ xslidy:slidenumber( $ref-target, $slide-count )})">
					<xsl:if test="exists($ref-target/node() | $ref-target/@title)">
						<xsl:attribute name="title" select="if ( exists($ref-target/node()) ) then string($ref-target/node()) else $ref-target/@title"/>
					</xsl:if>
					<xsl:value-of select="xslidy:print_counter(., @form)"/>
				</a>
			</xsl:when>
		</xsl:choose>
	</xsl:template>
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- this function outputs a counter value in the specified format, the context must be set to a counter element. -->
	<xsl:function name="xslidy:print_counter">
		<xsl:param name="context"/>
		<xsl:param name="form"/>
		<xsl:choose>
			<xsl:when test="exists($context/@id)">
				<xsl:value-of select="if ( not($form eq 'short') and xslidy:param('counter-format') eq 'full' ) then concat(count($context/preceding::presentation) + 1, '.') else ''"/>
				<xsl:value-of select="count($context/preceding::counter[@name eq $context/@name][ancestor::presentation is $context/ancestor::presentation]) + 1"/>
			</xsl:when>
			<xsl:when test="exists($context/@ref)">
				<xsl:value-of select="xslidy:print_counter(key('counterKey', $context/@ref, $context/ancestor::node()[last()])[@name eq $context/@name], $form)"/>
			</xsl:when>
		</xsl:choose>
	</xsl:function>
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
	<xsl:template name="message">
		<xsl:param name="text"/>
		<!-- message level may be 'warning' or 'error' (default). -->
		<xsl:param name="level" select="'error'"/>
		<xsl:param name="slide-count" tunnel="yes"/>
		<xsl:if test="$slide-count ne 'no'">
			<xsl:if test="not($level eq 'warning' and $messages eq 'error')">
				<xsl:message select="$text"/>
			</xsl:if>
		</xsl:if>
	</xsl:template>
</xsl:stylesheet>
