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

<!--
	Cross-references. Note the distinction betwen these and hyperlinks: a cross-reference is merely something like "see Section 2.3", and doesn't necessarily imply a hyperlink, or vice versa.
	
	The "reference" mode templates generate the main reference text, e.g., "see Section 2.3", "see Figure 1", etc. The "page-reference" mode template generate page reference text, e.g., "on page 23".
-->

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


	<!--
		Top level template for cross-references. There are separate templates below for each type of referenced item, as this is easier to implement.
		
		@label: The label of the item that we're referencing. It must be a valid label in both LaTeX and HTML. [required]
		
		@include-pageref: If "yes", also append a page reference (LaTeX only; this is handled by the "item-page-reference" template below).
	-->
	<template name="reference" match="reference[@label]">
		<common>
			<!-- Find the element whose label is the same as our label. -->
			<xsl:apply-templates select="//*[@label = current()/@label]" mode="reference" />
			<xsl:if test="@include-pageref = ('yes', 'y', 'true', 't', '1')">
				<xsl:apply-templates select="//*[@label = current()/@label]" mode="page-reference" />
			</xsl:if>
		</common>
	</template>
	
	
	<!-- ERROR: reference element with no label. -->
	<template name="broken-reference" match="reference[not( @label )]">
		<common>
			<xsl:message terminate="yes">Reference elements must include a label attribute.</xsl:message>
		</common>
	</template>
	
	
	<!-- Section reference. -->
	<template name="section-reference" match="section" mode="reference">
		<!-- It's probably more consistent to just use \ref* and insert "Section" ourselves rather than let LaTeX do it. -->
		<common formats="/latex/xelatex/">
			<xsl:text>Section~\ref*{</xsl:text>
			<xsl:value-of select="@label" />
			<xsl:text>}</xsl:text>
		</common>
		<common formats="/html/xhtml/">
			<xsl:text disable-output-escaping="yes">Section&amp;nbsp;</xsl:text>
			<xsl:number count="section" level="multiple" format="1.1.1.1.1.1" />
		</common>
	</template>
	
	
	<!-- Figure reference. -->
	<template name="figure-reference" match="figure" mode="reference">
		<common formats="/latex/xelatex/">
			<xsl:text>Figure~\ref*{</xsl:text>
			<xsl:value-of select="@label" />
			<xsl:text>}</xsl:text>
		</common>
		<common formats="/html/xhtml/">
			<xsl:text disable-output-escaping="yes">Figure&amp;nbsp;</xsl:text>
			<xsl:choose>
				<xsl:when test="$showanswers = ('yes', 'y', 'true', 't', '1')">
					<xsl:number count="figure" level="any" format="1" />
				</xsl:when>
				<xsl:otherwise>
					<xsl:number count="figure[not(ancestor::answer) and not(ancestor::omit) and not(ancestor::comment)]" level="any" format="1" />
				</xsl:otherwise>
			</xsl:choose>
		</common>
	</template>
	
	
	<!-- Table reference. -->
	<template name="table-reference" match="table" mode="reference">
		<common formats="/latex/xelatex/">
			<xsl:text>Table~\ref*{</xsl:text>
			<xsl:value-of select="@label" />
			<xsl:text>}</xsl:text>
		</common>
		<common formats="/html/xhtml/">
			<xsl:text disable-output-escaping="yes">Table&amp;nbsp;</xsl:text>
			<xsl:choose>
				<xsl:when test="$showanswers = ('yes', 'y', 'true', 't', '1')">
					<xsl:number count="table" level="any" format="1" />
				</xsl:when>
				<xsl:otherwise>
					<xsl:number count="table[not(ancestor::answer) and not(ancestor::omit) and not(ancestor::comment)]" level="any" format="1" />
				</xsl:otherwise>
			</xsl:choose>
		</common>
	</template>
	
	
	<!-- Exercise reference. -->
	<template name="exercise-reference" match="exercise" mode="reference">
		<common formats="/latex/xelatex/">
			<xsl:text>Exercise~\ref*{</xsl:text>
			<xsl:value-of select="@label" />
			<xsl:text>}</xsl:text>
		</common>
		<common formats="/html/xhtml/">
			<xsl:text disable-output-escaping="yes">Exercise&amp;nbsp;</xsl:text>
			<xsl:choose>
				<xsl:when test="$showanswers = ('yes', 'y', 'true', 't', '1')">
					<xsl:number count="exercise" level="any" format="1" />
				</xsl:when>
				<xsl:otherwise>
					<xsl:number count="exercise[not(ancestor::answer) and not(ancestor::omit) and not(ancestor::comment)]" level="any" format="1" />
				</xsl:otherwise>
			</xsl:choose>
		</common>
	</template>
	
	
	<!--
	    List item reference.
	    
	    There are WAY too many different list element types to properly specify the match. Let's just stick with "item".
	    
	    Items don't have a corresponding "name", so the surrounding text will have to supply it. Make sure to include such text in any hyperlink associated with the reference.
	-->
	<template name="list-item-reference" match="item" mode="reference">
		<common formats="/latex/xelatex/">
			<xsl:text>\ref*{</xsl:text>
			<xsl:value-of select="@label" />
			<xsl:text>}</xsl:text>
		</common>
		<common formats="/html/xhtml/">
			<xsl:choose>
				<xsl:when test="$showanswers = ('yes', 'y', 'true', 't', '1')">
				    <!-- it only really makes sense to count "item" elements within the same list -->
					<xsl:number count="item" level="single" format="1" />
				</xsl:when>
				<xsl:otherwise>
					<xsl:number count="item[not(ancestor::answer) and not(ancestor::omit) and not(ancestor::comment)]" level="single" format="1" />
				</xsl:otherwise>
			</xsl:choose>
		</common>
	</template>
	
	
	<!--
		Common template for item page references, as they're identical for all items. Standalone page references (i.e., not to a specific item) are dealt with below. Only relevant to (Xe)LaTeX as (X)HTML doesn't have pages.
	-->
	<template name="item-page-reference" match="section|figure|table|exercise" mode="page-reference">
		<common formats="/latex/xelatex/">
			<xsl:text> on page~\pageref{</xsl:text>
			<xsl:value-of select="@label" />
			<xsl:text>}</xsl:text>
		</common>
	</template>
	
	
	<!--
		Generate a standalone label for use in direct page references. Any content within the element is ignored.
		
		TODO: Hmm, this seems to generate the correct page number in LaTeX but the hyperlink is to the wrong page (one lower?). Something to worry about later.
		
		@label: The label to be inserted. It must be a valid label in both LaTeX and HTML. [required]
	-->
	<template name="page" match="page[@label]">
		<common formats="/latex/xelatex/">
			<xsl:text>\label{</xsl:text>
			<xsl:value-of select="@label" />
			<xsl:text>}</xsl:text>
		</common>
		<common formats="/html/xhtml/">
			<a id="{@label}"></a>
		</common>
	</template>
	
	<!-- ERROR: page element with no label. -->
	<template name="broken-page" match="page[not( @label )]">
		<common>
			<xsl:message terminate="yes">Page elements must include a label attribute.</xsl:message>
		</common>
	</template>


	<!--
		Standalone direct reference to a page (i.e., not associated with some other item like a figure or table). This only really makes sense in LaTeX, as HTML doesn't have page numbers. For HTML, we fudge things by inserting the string "here", which will make sense if the reference is wrapped with a hyperlink (as they usually should be).
	-->
	<template name="direct-page-reference" match="page[@label]" mode="reference">
		<common formats="/latex/xelatex/">
			<xsl:text>page~\pageref{</xsl:text>
			<xsl:value-of select="@label" />
			<xsl:text>}</xsl:text>
		</common>
		<common formats="/html/xhtml/">
			<xsl:text disable-output-escaping="yes">here</xsl:text>
		</common>
	</template>
	
	
</stylesheet>