GitBucket
4.21.2
Toggle navigation
Snippets
Sign in
Files
Branches
1
Releases
1
Issues
Pull requests
Labels
Priorities
Milestones
Wiki
Forks
nigel.stanger
/
XML
Browse code
• Added basic longtable support to enable tabulars to break over pages.
• Renamed row/@no-page-break to row/@page-break, and reversed sense of value to match.
master
1 parent
e13caaa
commit
7e8d6b03d4fc630ba65d61912f5e476c8fcfa1e1
Nigel Stanger
authored
on 13 Feb 2017
Patch
Showing
2 changed files
modules/tabular.xml
xml2xslt.xsl
Ignore Space
Show notes
View
modules/tabular.xml
<?xml version="1.0" encoding="utf-8"?> <!-- Tabular structures (LaTeX {tabular}, HTML <table>). Note that this is distinct from "tables" in general, which correspond to the {table} environment in LaTeX (i.e., floating). --> <stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- Tabular structures (LaTeX {tabular}, HTML <table>). @align: The alignment of the table as a whole. 'left' [default] 'center' | 'centre' 'right' @valign (LaTeX only): Vertical alignment of the tabular within the paragraph. 'top' 'center' | 'centre' [default] 'bottom' @border (HTML only): Width of cell border for HTML tables. @scale (LaTeX only): Scaling factor for the tabular. @rotate (LaTeX only): Rotation angle of tabular in degrees anti-clockwise. @long-table (LaTeX only): Use the longtable environment instead of tabular so it can span multiple pages. 'no' [default] 'yes' @caption (LaTeX only): Only valid for long tables (@long-table = 'yes'); ignored otherwise. --> <template name="tabular" match="tabular"> <common formats="/latex/xelatex/"> <!-- spacing --> <xsl:call-template name="newline-internal" /> <xsl:call-template name="newline-internal" /> <!-- Overall tabular alignment. --> <xsl:if test="@align"> <xsl:text>\begin{</xsl:text> <xsl:choose> <xsl:when test="@align = ('left', 'right')"> <xsl:text>flush</xsl:text><xsl:value-of select="@align" /> </xsl:when> <xsl:when test="@align = ('center', 'centre')"> <xsl:text>center</xsl:text> </xsl:when> </xsl:choose> <xsl:text>}</xsl:text> </xsl:if> <!-- tabular rotation --> <xsl:if test="@rotate"> <xsl:text>\rotatebox{</xsl:text> <xsl:value-of select="@rotate" /> <xsl:text>}{</xsl:text> </xsl:if> <!-- tabular scaling --> <xsl:if test="@scale"> <xsl:text>\scalebox{</xsl:text> <xsl:value-of select="@scale" /> <xsl:text>}{</xsl:text> </xsl:if> <xsl:text>\begin{</xsl:text> <xsl:value-of select=" if (@long-table = ('yes', 'y', 'true', 't', '1')) then 'longtable' else 'tabular'" /> <xsl:text>}</xsl:text> <!-- vertical alignment --> <xsl:if test="@valign = ('top', 'bottom')"> <xsl:text>[</xsl:text> <xsl:value-of select="substring(@valign, 1, 1)" /> <xsl:text>]</xsl:text> </xsl:if> <xsl:text>{</xsl:text> <xsl:apply-templates select="tabular-columns" /> <xsl:text>}</xsl:text> <xsl:if test="(@long-table = ('yes', 'y', 'true', 't', '1')) and @caption"> <xsl:text>\caption{</xsl:text> <xsl:value-of select="@caption" /> <xsl:text>} \\</xsl:text> </xsl:if> <xsl:apply-templates select="tabular-header" /> <xsl:apply-templates select="tabular-body" /> <xsl:apply-templates select="tabular-footer" /> <xsl:text>\end{</xsl:text> <xsl:value-of select=" if (@long-table = ('yes', 'y', 'true', 't', '1')) then 'longtable' else 'tabular'" /> <xsl:text>}</xsl:text> <xsl:if test="@scale"><xsl:text>}</xsl:text></xsl:if> <xsl:if test="@rotate"><xsl:text>}</xsl:text></xsl:if> <xsl:if test="@align"> <xsl:text>\end{</xsl:text> <xsl:choose> <xsl:when test="@align = ('left', 'right')"> <xsl:text>flush</xsl:text> <xsl:value-of select="@align" /> </xsl:when> <xsl:when test="@align = ('center', 'centre')"> <xsl:text>center</xsl:text> </xsl:when> </xsl:choose> <xsl:text>}</xsl:text> </xsl:if> <!-- spacing --> <xsl:call-template name="newline-internal" /> <xsl:call-template name="newline-internal" /> </common> <common formats="/html/xhtml/"> <table> <xsl:attribute name="border"> <xsl:value-of select="@border" /> <xsl:if test="not(@border)">0</xsl:if> </xsl:attribute> <xsl:attribute name="cellspacing">0</xsl:attribute> <xsl:attribute name="style"> <xsl:text>border-collapse: collapse; </xsl:text> <xsl:choose> <xsl:when test="@align = ('center', 'centre')"> <xsl:text>margin-left:auto; margin-right: auto; </xsl:text> </xsl:when> <xsl:when test="@align eq 'right'"> <xsl:text>margin-left:auto; </xsl:text> </xsl:when> <xsl:otherwise /> </xsl:choose> </xsl:attribute> <!-- Note different ordering of tabular components: HTML requires THEAD and TFOOT to precede TBODY. --> <xsl:apply-templates select="tabular-header" /> <xsl:apply-templates select="tabular-footer" /> <xsl:apply-templates select="tabular-body" /> </table> </common> </template> <!-- Specify column formatting, mainly for LaTeX, although HTML does get <td> ALIGN values from here. @align: The alignment of this particular column. 'left' [default] 'center' | 'centre' 'right' @left-border: Set to '|' to include a column separator to the left of this column. @right-border: Set to '|' to include a column separator to the right of this column. Careful: including a right-border on a cell and a left-border on the next cell will produce '||', not '|'. BUT, when doing multi-column or multi-row cells, always include both borders if required, because \multicolumn overrides the default border specification. --> <template name="aligned-tabular-column" match="tabular-columns/column[@align]"> <common formats="/latex/xelatex/"> <xsl:value-of select="@left-border" /> <xsl:value-of select="substring(@align, 1, 1)" /> <xsl:value-of select="@right-border" /> </common> </template> <template name="unaligned-tabular-column" match="tabular-columns/column[not(@align)]"> <common formats="/latex/xelatex/"> <xsl:value-of select="@left-border" /> <xsl:text>l</xsl:text> <xsl:value-of select="@right-border" /> </common> </template> <!-- Tabular header. --> <template name="tabular-header" match="tabular-header"> <common formats="/latex/xelatex/"><xsl:apply-templates /></common> <common formats="/html/xhtml/"> <thead> <xsl:apply-templates /> </thead> </common> </template> <!-- Tabular footer. --> <template name="tabular-footer" match="tabular-footer"> <common formats="/latex/xelatex/"><xsl:apply-templates /></common> <common formats="/html/xhtml/"> <tfoot> <xsl:apply-templates /> </tfoot> </common> </template> <!-- Tabular main body. --> <template name="tabular-body" match="tabular-body"> <common formats="/latex/xelatex/"><xsl:apply-templates /></common> <common formats="/html/xhtml/"> <tbody> <xsl:apply-templates /> </tbody> </common> </template> <!-- A single row of a tabular. @page-break: Inhibit page breaks after this row (LaTeX only). --> <template name="row" match="row"> <common formats="/latex/xelatex/"> <xsl:apply-templates /> <xsl:text> \\</xsl:text> <xsl:if test="@page-break = ('no', 'n', 'false', 'f', '0')"><xsl:text>*</xsl:text></xsl:if> <xsl:text> </xsl:text> </common> <common formats="/html/xhtml/"> <tr> <xsl:if test="@valign"> <xsl:attribute name="valign"><xsl:value-of select="@valign" /></xsl:attribute> </xsl:if> <xsl:apply-templates /> </tr> </common> </template> <!-- This template handles the following cases: The last row of a tabular in (Xe)LaTeX shouldn't have a \\ at the end, /unless/ you want a horizontal rule (\hline) under the last row (Lamport, p. 62). This template handles the following cases: Case 1: The last row of a tabular-body, without a row-rule following it, and no tabular-footer. Case 2: The last row of a tabular-footer, without a row-rule following it. --> <template name="last-row-body" match="tabular-body/row[( position() = last() ) and not( following-sibling::row-rule ) and not( ancestor::tabular/tabular-footer )]|tabular-footer/row[position() = last() and not( following-sibling::row-rule )]"> <common formats="/latex/xelatex/"> <xsl:apply-templates /> <xsl:text> </xsl:text> </common> <common formats="/html/xhtml/"> <xsl:call-template name="row" /> </common> </template> <!-- Horizontal rules (LaTeX only). @columns: The column range to draw the rule across. Specify as you would for a \cline in LaTeX, e.g., '3-5'. If omitted, the rule is drawn across all columns. @weight: The weight of the rule. Note that double weight isn't available for partial rules in LaTeX, because repeated \cline macros simply draw over the top of each other. 'single' [default] 'double' = a double rule --> <template name="row-rule-full" match="row-rule[not(@columns)]"> <common formats="/latex/xelatex/"> <xsl:text>\hline</xsl:text> <xsl:if test="@weight eq 'double'"><xsl:text>\hline</xsl:text></xsl:if> <xsl:text> </xsl:text> </common> <common formats="/html/xhtml/"> <tr> <td> <xsl:attribute name="style"> <xsl:text>border-bottom: 1px solid black; </xsl:text> <!-- This is a bit of a hack to get a double border, as some browsers don't support the "double" border style yet. It looks slightly ugly, but works. --> <xsl:if test="@weight eq 'double'"> <xsl:text>border-top: 1px solid black; </xsl:text> </xsl:if> </xsl:attribute> <xsl:attribute name="colspan"> <xsl:value-of select="count(ancestor::tabular/tabular-columns/column)" /> </xsl:attribute> </td> </tr> </common> </template> <template name="row-rule-partial" match="row-rule[@columns]"> <common formats="/latex/xelatex/"> <!-- Tokenise the column specifications for later reference. --> <xsl:variable name="column-specs" select="tokenize(@columns, ',')" /> <xsl:for-each select="$column-specs"> <xsl:text>\cline{</xsl:text> <xsl:value-of select="." /> <!-- Normalise the value to a range if necessary. --> <xsl:if test="not(contains(., '-'))"> <xsl:text>-</xsl:text> <xsl:value-of select="." /> </xsl:if> <xsl:text>}</xsl:text> </xsl:for-each> </common> <common formats="/html/xhtml/"> <!-- Tokenise the column specifications for later reference. --> <xsl:variable name="column-specs" select="tokenize(@columns, '[-,]')" /> <!-- We need to store the value of @weight, because the context will be changed by the for-each loop below. Default to "single" in any case. --> <xsl:variable name="weight"> <xsl:value-of select="@weight" /> <xsl:if test="not(@weight)"> <xsl:text>single</xsl:text> </xsl:if> </xsl:variable> <tr> <!-- Loop through all of the columns in the table, testing to see whether the column index exists in $column-specs. If so, add a border to the cell. Note that this loop changes the current context! --> <xsl:for-each select="1 to count(ancestor::tabular/tabular-columns/column)"> <td> <xsl:if test="exists(index-of($column-specs, . cast as xs:string))"> <xsl:attribute name="style"> <xsl:text>border-bottom: 1px solid black; </xsl:text> <xsl:if test="$weight eq 'double'"> <xsl:text>border-top: 1px solid black; </xsl:text> </xsl:if> </xsl:attribute> </xsl:if> </td> </xsl:for-each> </tr> </common> </template> <!-- Multi-row cells (LaTeX only, as this is pretty trivial to achieve in HTML). @rows: The number of rows this cell spans. @header: Is this a header cell? [yes, NO] --> <!-- Hmm, the multi-row stuff is somewhat broken in LaTeX, oops. Need to insert missing columns (as was done in the calendar XSL) when a multi-row cell is encountered. Also need to sort out \hlines in the presence of multi-row cells and also what happens to vertical cell borders :(. This probably needs reworking. --> <template name="multirow-cell" match="cell" mode="latex-multi-row"> <common formats="/latex/xelatex/"> <xsl:text>\multirow{</xsl:text> <xsl:value-of select="@rows" /> <xsl:text>}{*}{</xsl:text> <xsl:if test="@header = ('yes', 'y', 'true', 't', '1')"><xsl:text>\textbf{</xsl:text></xsl:if> <!-- check for embedded line breaks, if so, embed another tabular inside this one --> <xsl:if test="count(child::br) ne 0"> <xsl:text>\begin{tabular}{@{}</xsl:text> <xsl:choose> <xsl:when test="@align"> <xsl:value-of select="substring(@align, 1, 1)" /> </xsl:when> <xsl:otherwise> <xsl:text>l</xsl:text> </xsl:otherwise> </xsl:choose> <xsl:text>@{}}</xsl:text> </xsl:if> <xsl:apply-templates /> <xsl:if test="count(child::br) ne 0"> <xsl:text>\end{tabular}</xsl:text> <xsl:call-template name="newline-internal" /> </xsl:if> <xsl:if test="@header = ('yes', 'y', 'true', 't', '1')"><xsl:text>}</xsl:text></xsl:if> <xsl:text>}</xsl:text> </common> </template> <!-- Multi-column cells (LaTeX only, as this is pretty trivial to achieve in HTML). $num-columns: The number of columns this cell spans. @header: Is this a header cell? [yes, NO] --> <template name="multicolumn-cell" match="cell" mode="latex-multi-column"> <common formats="/latex/xelatex/"> <!-- TODO: Not quite sure why the number of columns is a parameter rather than just using the @columns attribute? Something to do with defaults perhaps? --> <xsl:param name="num-columns">1</xsl:param> <xsl:text>\multicolumn{</xsl:text> <xsl:value-of select="$num-columns" /> <xsl:text>}{</xsl:text> <xsl:value-of select="@left-border" /> <xsl:choose> <xsl:when test="@align"> <xsl:value-of select="substring(@align, 1, 1)" /> </xsl:when> <xsl:otherwise> <xsl:text>l</xsl:text> </xsl:otherwise> </xsl:choose> <xsl:value-of select="@right-border" /> <xsl:text>}{</xsl:text> <xsl:choose> <xsl:when test="@rows"> <xsl:apply-templates select="." mode="multi-row" /> </xsl:when> <xsl:otherwise> <xsl:if test="@header = ('yes', 'y', 'true', 't', '1')"><xsl:text>\textbf{</xsl:text></xsl:if> <!-- check for embedded line breaks, if so, embed another tabular inside this one --> <xsl:if test="count(child::br) ne 0"> <xsl:text>\begin{tabular}{@{}</xsl:text> <xsl:choose> <xsl:when test="@align"> <xsl:value-of select="substring(@align, 1, 1)" /> </xsl:when> <xsl:otherwise> <xsl:text>l</xsl:text> </xsl:otherwise> </xsl:choose> <xsl:text>@{}}</xsl:text> </xsl:if> <xsl:apply-templates /> <xsl:if test="count(child::br) ne 0"> <xsl:text>\end{tabular}</xsl:text> <xsl:call-template name="newline-internal" /> </xsl:if> <xsl:if test="@header = ('yes', 'y', 'true', 't', '1')"><xsl:text>}</xsl:text></xsl:if> </xsl:otherwise> </xsl:choose> <xsl:text>}</xsl:text> </common> </template> <!-- Top-level template for generating cells. @columns: The number of columns this cell spans. @rows: The number of rows this cell spans. @align: The alignment of this cell. [LEFT, center, right] @header: Is this a header cell? [yes, NO] --> <template match="cell"> <common> <!-- position() doesn't seem to work very well in this context. --> <xsl:variable name="column-no"><xsl:number /></xsl:variable> </common> <!-- Doing this sensibly for LaTeX is actually pretty ugly, because different attribute combinations produce different code :(. This is the sort of algorithm that can only really be clearly described by a flow chart :). --> <common formats="/latex/xelatex/"> <xsl:choose> <xsl:when test="@columns"> <xsl:apply-templates select="." mode="latex-multi-column"> <xsl:with-param name="num-columns" select="@columns" /> </xsl:apply-templates> </xsl:when> <xsl:when test="@align"> <xsl:apply-templates select="." mode="latex-multi-column" /> </xsl:when> <xsl:when test="@rows"> <xsl:apply-templates select="." mode="latex-multi-row" /> </xsl:when> <xsl:otherwise> <xsl:if test="@header = ('yes', 'y', 'true', 't', '1')"><xsl:text>\textbf{</xsl:text></xsl:if> <!-- check for embedded line breaks, if so, embed another tabular inside this one --> <xsl:if test="count(child::br) ne 0"> <xsl:text>\begin{tabular}{@{}</xsl:text> <xsl:choose> <xsl:when test="@align"> <xsl:value-of select="substring(@align, 1, 1)" /> </xsl:when> <xsl:otherwise> <xsl:text>l</xsl:text> </xsl:otherwise> </xsl:choose> <xsl:text>@{}}</xsl:text> </xsl:if> <xsl:apply-templates /> <xsl:if test="count(child::br) ne 0"> <xsl:text>\end{tabular}</xsl:text> <xsl:call-template name="newline-internal" /> </xsl:if> <xsl:if test="@header = ('yes', 'y', 'true', 't', '1')"><xsl:text>}</xsl:text></xsl:if> </xsl:otherwise> </xsl:choose> <xsl:if test="$column-no != last()"> <xsl:call-template name="tabular-column-separator" /> </xsl:if> </common> <!-- It's much easier in HTML, because a <td> is a <td> is a <td>, regardless of the attributes supplied. --> <common formats="/html/xhtml/"> <!-- Hmm, how to generate either a TD or TH as required, including attributes, without repeating code? Aha, the answer is attribute value templates! --> <xsl:variable name="celltype"> <xsl:choose> <xsl:when test="@header = ('yes', 'y', 'true', 't', '1')">th</xsl:when> <xsl:otherwise>td</xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:element name="{$celltype}"> <xsl:attribute name="align"> <xsl:value-of select="@align" /> <xsl:if test="not(@align)"> <xsl:value-of select="ancestor::tabular/tabular-columns/column[position() = $column-no]/@align" /> <xsl:if test="not(ancestor::tabular/tabular-columns/column[position() = $column-no]/@align)"> <xsl:text>left</xsl:text> </xsl:if> </xsl:if> </xsl:attribute> <xsl:attribute name="valign"> <xsl:value-of select="@valign" /> <xsl:if test="not(@valign)"><xsl:text>middle</xsl:text></xsl:if> </xsl:attribute> <xsl:attribute name="colspan"> <xsl:value-of select="@columns" /> <xsl:if test="not(@columns)"><xsl:text>1</xsl:text></xsl:if> </xsl:attribute> <xsl:attribute name="rowspan"> <xsl:value-of select="@rows" /> <xsl:if test="not(@rows)"><xsl:text>1</xsl:text></xsl:if> </xsl:attribute> <xsl:apply-templates /> </xsl:element> </common> </template> </stylesheet>
<?xml version="1.0" encoding="utf-8"?> <!-- Tabular structures (LaTeX {tabular}, HTML <table>). Note that this is distinct from "tables" in general, which correspond to the {table} environment in LaTeX (i.e., floating). --> <stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- Tabular structures (LaTeX {tabular}, HTML <table>). @align: The alignment of the table as a whole. 'left' [default] 'center' | 'centre' 'right' @valign (LaTeX only): Vertical alignment of the tabular within the paragraph. 'top' 'center' | 'centre' [default] 'bottom' @border (HTML only): Width of cell border for HTML tables. @scale (LaTeX only): Scaling factor for the tabular. @rotate (LaTeX only): Rotation angle of tabular in degrees anti-clockwise. --> <template name="tabular" match="tabular"> <common formats="/latex/xelatex/"> <!-- spacing --> <xsl:call-template name="newline-internal" /> <xsl:call-template name="newline-internal" /> <!-- Overall tabular alignment. --> <xsl:if test="@align"> <xsl:text>\begin{</xsl:text> <xsl:choose> <xsl:when test="@align = ('left', 'right')"> <xsl:text>flush</xsl:text><xsl:value-of select="@align" /> </xsl:when> <xsl:when test="@align = ('center', 'centre')"> <xsl:text>center</xsl:text> </xsl:when> </xsl:choose> <xsl:text>}</xsl:text> </xsl:if> <!-- tabular rotation --> <xsl:if test="@rotate"> <xsl:text>\rotatebox{</xsl:text> <xsl:value-of select="@rotate" /> <xsl:text>}{</xsl:text> </xsl:if> <!-- tabular scaling --> <xsl:if test="@scale"> <xsl:text>\scalebox{</xsl:text> <xsl:value-of select="@scale" /> <xsl:text>}{</xsl:text> </xsl:if> <xsl:text>\begin{tabular}</xsl:text> <!-- vertical alignment --> <xsl:if test="@valign = ('top', 'bottom')"> <xsl:text>[</xsl:text> <xsl:value-of select="substring(@valign, 1, 1)" /> <xsl:text>]</xsl:text> </xsl:if> <xsl:text>{</xsl:text> <xsl:apply-templates select="tabular-columns" /> <xsl:text>}</xsl:text> <xsl:apply-templates select="tabular-header" /> <xsl:apply-templates select="tabular-body" /> <xsl:apply-templates select="tabular-footer" /> <xsl:text>\end{tabular}</xsl:text> <xsl:if test="@scale"><xsl:text>}</xsl:text></xsl:if> <xsl:if test="@rotate"><xsl:text>}</xsl:text></xsl:if> <xsl:if test="@align"> <xsl:text>\end{</xsl:text> <xsl:choose> <xsl:when test="@align = ('left', 'right')"> <xsl:text>flush</xsl:text> <xsl:value-of select="@align" /> </xsl:when> <xsl:when test="@align = ('center', 'centre')"> <xsl:text>center</xsl:text> </xsl:when> </xsl:choose> <xsl:text>}</xsl:text> </xsl:if> <!-- spacing --> <xsl:call-template name="newline-internal" /> <xsl:call-template name="newline-internal" /> </common> <common formats="/html/xhtml/"> <table> <xsl:attribute name="border"> <xsl:value-of select="@border" /> <xsl:if test="not(@border)">0</xsl:if> </xsl:attribute> <xsl:attribute name="cellspacing">0</xsl:attribute> <xsl:attribute name="style"> <xsl:text>border-collapse: collapse; </xsl:text> <xsl:choose> <xsl:when test="@align = ('center', 'centre')"> <xsl:text>margin-left:auto; margin-right: auto; </xsl:text> </xsl:when> <xsl:when test="@align eq 'right'"> <xsl:text>margin-left:auto; </xsl:text> </xsl:when> <xsl:otherwise /> </xsl:choose> </xsl:attribute> <!-- Note different ordering of tabular components: HTML requires THEAD and TFOOT to precede TBODY. --> <xsl:apply-templates select="tabular-header" /> <xsl:apply-templates select="tabular-footer" /> <xsl:apply-templates select="tabular-body" /> </table> </common> </template> <!-- Specify column formatting, mainly for LaTeX, although HTML does get <td> ALIGN values from here. @align: The alignment of this particular column. 'left' [default] 'center' | 'centre' 'right' @left-border: Set to '|' to include a column separator to the left of this column. @right-border: Set to '|' to include a column separator to the right of this column. Careful: including a right-border on a cell and a left-border on the next cell will produce '||', not '|'. BUT, when doing multi-column or multi-row cells, always include both borders if required, because \multicolumn overrides the default border specification. --> <template name="aligned-tabular-column" match="tabular-columns/column[@align]"> <common formats="/latex/xelatex/"> <xsl:value-of select="@left-border" /> <xsl:value-of select="substring(@align, 1, 1)" /> <xsl:value-of select="@right-border" /> </common> </template> <template name="unaligned-tabular-column" match="tabular-columns/column[not(@align)]"> <common formats="/latex/xelatex/"> <xsl:value-of select="@left-border" /> <xsl:text>l</xsl:text> <xsl:value-of select="@right-border" /> </common> </template> <!-- Tabular header. --> <template name="tabular-header" match="tabular-header"> <common formats="/latex/xelatex/"><xsl:apply-templates /></common> <common formats="/html/xhtml/"> <thead> <xsl:apply-templates /> </thead> </common> </template> <!-- Tabular footer. --> <template name="tabular-footer" match="tabular-footer"> <common formats="/latex/xelatex/"><xsl:apply-templates /></common> <common formats="/html/xhtml/"> <tfoot> <xsl:apply-templates /> </tfoot> </common> </template> <!-- Tabular main body. --> <template name="tabular-body" match="tabular-body"> <common formats="/latex/xelatex/"><xsl:apply-templates /></common> <common formats="/html/xhtml/"> <tbody> <xsl:apply-templates /> </tbody> </common> </template> <!-- A single row of a tabular. @no-page-break: Inhibit page breaks after this row (LaTeX only). --> <template name="row" match="row"> <common formats="/latex/xelatex/"> <xsl:apply-templates /> <xsl:text> \\</xsl:text> <xsl:if test="@no-page-break = ('yes', 'y', 'true', 't', '1')"><xsl:text>*</xsl:text></xsl:if> <xsl:text> </xsl:text> </common> <common formats="/html/xhtml/"> <tr> <xsl:if test="@valign"> <xsl:attribute name="valign"><xsl:value-of select="@valign" /></xsl:attribute> </xsl:if> <xsl:apply-templates /> </tr> </common> </template> <!-- This template handles the following cases: The last row of a tabular in (Xe)LaTeX shouldn't have a \\ at the end, /unless/ you want a horizontal rule (\hline) under the last row (Lamport, p. 62). This template handles the following cases: Case 1: The last row of a tabular-body, without a row-rule following it, and no tabular-footer. Case 2: The last row of a tabular-footer, without a row-rule following it. --> <template name="last-row-body" match="tabular-body/row[( position() = last() ) and not( following-sibling::row-rule ) and not( ancestor::tabular/tabular-footer )]|tabular-footer/row[position() = last() and not( following-sibling::row-rule )]"> <common formats="/latex/xelatex/"> <xsl:apply-templates /> <xsl:text> </xsl:text> </common> <common formats="/html/xhtml/"> <xsl:call-template name="row" /> </common> </template> <!-- Horizontal rules (LaTeX only). @columns: The column range to draw the rule across. Specify as you would for a \cline in LaTeX, e.g., '3-5'. If omitted, the rule is drawn across all columns. @weight: The weight of the rule. Note that double weight isn't available for partial rules in LaTeX, because repeated \cline macros simply draw over the top of each other. 'single' [default] 'double' = a double rule --> <template name="row-rule-full" match="row-rule[not(@columns)]"> <common formats="/latex/xelatex/"> <xsl:text>\hline</xsl:text> <xsl:if test="@weight eq 'double'"><xsl:text>\hline</xsl:text></xsl:if> <xsl:text> </xsl:text> </common> <common formats="/html/xhtml/"> <tr> <td> <xsl:attribute name="style"> <xsl:text>border-bottom: 1px solid black; </xsl:text> <!-- This is a bit of a hack to get a double border, as some browsers don't support the "double" border style yet. It looks slightly ugly, but works. --> <xsl:if test="@weight eq 'double'"> <xsl:text>border-top: 1px solid black; </xsl:text> </xsl:if> </xsl:attribute> <xsl:attribute name="colspan"> <xsl:value-of select="count(ancestor::tabular/tabular-columns/column)" /> </xsl:attribute> </td> </tr> </common> </template> <template name="row-rule-partial" match="row-rule[@columns]"> <common formats="/latex/xelatex/"> <!-- Tokenise the column specifications for later reference. --> <xsl:variable name="column-specs" select="tokenize(@columns, ',')" /> <xsl:for-each select="$column-specs"> <xsl:text>\cline{</xsl:text> <xsl:value-of select="." /> <!-- Normalise the value to a range if necessary. --> <xsl:if test="not(contains(., '-'))"> <xsl:text>-</xsl:text> <xsl:value-of select="." /> </xsl:if> <xsl:text>}</xsl:text> </xsl:for-each> </common> <common formats="/html/xhtml/"> <!-- Tokenise the column specifications for later reference. --> <xsl:variable name="column-specs" select="tokenize(@columns, '[-,]')" /> <!-- We need to store the value of @weight, because the context will be changed by the for-each loop below. Default to "single" in any case. --> <xsl:variable name="weight"> <xsl:value-of select="@weight" /> <xsl:if test="not(@weight)"> <xsl:text>single</xsl:text> </xsl:if> </xsl:variable> <tr> <!-- Loop through all of the columns in the table, testing to see whether the column index exists in $column-specs. If so, add a border to the cell. Note that this loop changes the current context! --> <xsl:for-each select="1 to count(ancestor::tabular/tabular-columns/column)"> <td> <xsl:if test="exists(index-of($column-specs, . cast as xs:string))"> <xsl:attribute name="style"> <xsl:text>border-bottom: 1px solid black; </xsl:text> <xsl:if test="$weight eq 'double'"> <xsl:text>border-top: 1px solid black; </xsl:text> </xsl:if> </xsl:attribute> </xsl:if> </td> </xsl:for-each> </tr> </common> </template> <!-- Multi-row cells (LaTeX only, as this is pretty trivial to achieve in HTML). @rows: The number of rows this cell spans. @header: Is this a header cell? [yes, NO] --> <!-- Hmm, the multi-row stuff is somewhat broken in LaTeX, oops. Need to insert missing columns (as was done in the calendar XSL) when a multi-row cell is encountered. Also need to sort out \hlines in the presence of multi-row cells and also what happens to vertical cell borders :(. This probably needs reworking. --> <template name="multirow-cell" match="cell" mode="latex-multi-row"> <common formats="/latex/xelatex/"> <xsl:text>\multirow{</xsl:text> <xsl:value-of select="@rows" /> <xsl:text>}{*}{</xsl:text> <xsl:if test="@header = ('yes', 'y', 'true', 't', '1')"><xsl:text>\textbf{</xsl:text></xsl:if> <!-- check for embedded line breaks, if so, embed another tabular inside this one --> <xsl:if test="count(child::br) ne 0"> <xsl:text>\begin{tabular}{@{}</xsl:text> <xsl:choose> <xsl:when test="@align"> <xsl:value-of select="substring(@align, 1, 1)" /> </xsl:when> <xsl:otherwise> <xsl:text>l</xsl:text> </xsl:otherwise> </xsl:choose> <xsl:text>@{}}</xsl:text> </xsl:if> <xsl:apply-templates /> <xsl:if test="count(child::br) ne 0"> <xsl:text>\end{tabular}</xsl:text> <xsl:call-template name="newline-internal" /> </xsl:if> <xsl:if test="@header = ('yes', 'y', 'true', 't', '1')"><xsl:text>}</xsl:text></xsl:if> <xsl:text>}</xsl:text> </common> </template> <!-- Multi-column cells (LaTeX only, as this is pretty trivial to achieve in HTML). $num-columns: The number of columns this cell spans. @header: Is this a header cell? [yes, NO] --> <template name="multicolumn-cell" match="cell" mode="latex-multi-column"> <common formats="/latex/xelatex/"> <!-- TODO: Not quite sure why the number of columns is a parameter rather than just using the @columns attribute? Something to do with defaults perhaps? --> <xsl:param name="num-columns">1</xsl:param> <xsl:text>\multicolumn{</xsl:text> <xsl:value-of select="$num-columns" /> <xsl:text>}{</xsl:text> <xsl:value-of select="@left-border" /> <xsl:choose> <xsl:when test="@align"> <xsl:value-of select="substring(@align, 1, 1)" /> </xsl:when> <xsl:otherwise> <xsl:text>l</xsl:text> </xsl:otherwise> </xsl:choose> <xsl:value-of select="@right-border" /> <xsl:text>}{</xsl:text> <xsl:choose> <xsl:when test="@rows"> <xsl:apply-templates select="." mode="multi-row" /> </xsl:when> <xsl:otherwise> <xsl:if test="@header = ('yes', 'y', 'true', 't', '1')"><xsl:text>\textbf{</xsl:text></xsl:if> <!-- check for embedded line breaks, if so, embed another tabular inside this one --> <xsl:if test="count(child::br) ne 0"> <xsl:text>\begin{tabular}{@{}</xsl:text> <xsl:choose> <xsl:when test="@align"> <xsl:value-of select="substring(@align, 1, 1)" /> </xsl:when> <xsl:otherwise> <xsl:text>l</xsl:text> </xsl:otherwise> </xsl:choose> <xsl:text>@{}}</xsl:text> </xsl:if> <xsl:apply-templates /> <xsl:if test="count(child::br) ne 0"> <xsl:text>\end{tabular}</xsl:text> <xsl:call-template name="newline-internal" /> </xsl:if> <xsl:if test="@header = ('yes', 'y', 'true', 't', '1')"><xsl:text>}</xsl:text></xsl:if> </xsl:otherwise> </xsl:choose> <xsl:text>}</xsl:text> </common> </template> <!-- Top-level template for generating cells. @columns: The number of columns this cell spans. @rows: The number of rows this cell spans. @align: The alignment of this cell. [LEFT, center, right] @header: Is this a header cell? [yes, NO] --> <template match="cell"> <common> <!-- position() doesn't seem to work very well in this context. --> <xsl:variable name="column-no"><xsl:number /></xsl:variable> </common> <!-- Doing this sensibly for LaTeX is actually pretty ugly, because different attribute combinations produce different code :(. This is the sort of algorithm that can only really be clearly described by a flow chart :). --> <common formats="/latex/xelatex/"> <xsl:choose> <xsl:when test="@columns"> <xsl:apply-templates select="." mode="latex-multi-column"> <xsl:with-param name="num-columns" select="@columns" /> </xsl:apply-templates> </xsl:when> <xsl:when test="@align"> <xsl:apply-templates select="." mode="latex-multi-column" /> </xsl:when> <xsl:when test="@rows"> <xsl:apply-templates select="." mode="latex-multi-row" /> </xsl:when> <xsl:otherwise> <xsl:if test="@header = ('yes', 'y', 'true', 't', '1')"><xsl:text>\textbf{</xsl:text></xsl:if> <!-- check for embedded line breaks, if so, embed another tabular inside this one --> <xsl:if test="count(child::br) ne 0"> <xsl:text>\begin{tabular}{@{}</xsl:text> <xsl:choose> <xsl:when test="@align"> <xsl:value-of select="substring(@align, 1, 1)" /> </xsl:when> <xsl:otherwise> <xsl:text>l</xsl:text> </xsl:otherwise> </xsl:choose> <xsl:text>@{}}</xsl:text> </xsl:if> <xsl:apply-templates /> <xsl:if test="count(child::br) ne 0"> <xsl:text>\end{tabular}</xsl:text> <xsl:call-template name="newline-internal" /> </xsl:if> <xsl:if test="@header = ('yes', 'y', 'true', 't', '1')"><xsl:text>}</xsl:text></xsl:if> </xsl:otherwise> </xsl:choose> <xsl:if test="$column-no != last()"> <xsl:call-template name="tabular-column-separator" /> </xsl:if> </common> <!-- It's much easier in HTML, because a <td> is a <td> is a <td>, regardless of the attributes supplied. --> <common formats="/html/xhtml/"> <!-- Hmm, how to generate either a TD or TH as required, including attributes, without repeating code? Aha, the answer is attribute value templates! --> <xsl:variable name="celltype"> <xsl:choose> <xsl:when test="@header = ('yes', 'y', 'true', 't', '1')">th</xsl:when> <xsl:otherwise>td</xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:element name="{$celltype}"> <xsl:attribute name="align"> <xsl:value-of select="@align" /> <xsl:if test="not(@align)"> <xsl:value-of select="ancestor::tabular/tabular-columns/column[position() = $column-no]/@align" /> <xsl:if test="not(ancestor::tabular/tabular-columns/column[position() = $column-no]/@align)"> <xsl:text>left</xsl:text> </xsl:if> </xsl:if> </xsl:attribute> <xsl:attribute name="valign"> <xsl:value-of select="@valign" /> <xsl:if test="not(@valign)"><xsl:text>middle</xsl:text></xsl:if> </xsl:attribute> <xsl:attribute name="colspan"> <xsl:value-of select="@columns" /> <xsl:if test="not(@columns)"><xsl:text>1</xsl:text></xsl:if> </xsl:attribute> <xsl:attribute name="rowspan"> <xsl:value-of select="@rows" /> <xsl:if test="not(@rows)"><xsl:text>1</xsl:text></xsl:if> </xsl:attribute> <xsl:apply-templates /> </xsl:element> </common> </template> </stylesheet>
Ignore Space
Show notes
View
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:xs="http://www.w3.org/2001/XMLSchema" xmlns:infosci="http://info-nts-12.otago.ac.nz/infosci"> <!-- 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="xml" encoding="utf-8" cdata-section-elements="html" /> <!-- What target format are we generating a styesheet for? Possible values: html, xhtml, latex (includes pdflatex), xelatex. --> <xsl:param name="target-format"><xsl:text>html</xsl:text></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> <!-- *** TEMPLATES *** --> <xsl:template match="/"> <xsl-out:stylesheet version="2.0"> <xsl-out:strip-space elements="*" /> <xsl-out:param name="subject-code"><xsl:text>INFO</xsl:text></xsl-out:param> <xsl-out:param name="paper-number" /> <xsl-out:param name="paper-year" select="year-from-date( current-date() )"/> <xsl-out:param name="period-code" /> <xsl-out:param name="showanswers"><xsl:text>no</xsl:text></xsl-out:param> <!-- This is normally the path to the current document directory. --> <xsl-out:param name="base-path"><xsl:text>.</xsl:text></xsl-out:param> <!-- This is normally the path to the root directory of the paper tree in the filesystem. --> <xsl-out:param name="paper-include-path"><xsl:text>.</xsl:text></xsl-out:param> <!-- This is normally the file paper_init.tex in the root of the paper tree. --> <xsl-out:param name="latex-initialisation-file"><xsl:text>paper_init</xsl:text></xsl-out:param> <!-- Full period string corresponding to the supplied period code. --> <xsl-out:variable name="period-string" select="infosci:expand-period-code( $period-code )" /> <!-- The date and time when the document was last built. --> <xsl-out:variable name="date-built" select="current-dateTime()" /> <!-- Get the name of the document being processed. --> <xsl-out:variable name="document-name" select="reverse( tokenize( base-uri(), '/' ) )[1]" /> <!-- Include the generated Oracle documentation code. --> <xsl-out:include href="oracle-docs.xsl" /> <!-- Boilerplate (Xe)LaTeX code for loading hyperref. If the package is already loaded (by the document class), attempting to load it again will cause an "option clash" error. To avoid this, check first whether it's already loaded. We apply the required settings afterwards regardless. --> <xsl-out:variable name="latex-hyperref-boilerplate"> <xsl-out:text> % Avoid option clash if document class already loaded it. \makeatletter \@ifpackageloaded{hyperref}{}{\usepackage{hyperref}} \makeatother % Safer to specify the hyperref options directly rather than relying on % the default hyperref.cfg, as XeLaTeX seems to ignore it :(. \hypersetup{pdfpagemode=UseNone,colorlinks,urlcolor=blue,citecolor=blue,% linkcolor=blue,breaklinks} </xsl-out:text> </xsl-out:variable> <!-- 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="$target-format = ('latex', 'html')"> <xsl:text>iso-8859-1</xsl:text> </xsl:when> <xsl:when test="$target-format = ('xelatex', 'xhtml')"> <xsl:text>utf-8</xsl:text> </xsl:when> <xsl:otherwise> <xsl:message terminate="yes"> <xsl:text>Sorry, unknown target format: </xsl:text><xsl:value-of select="$target-format" /> </xsl:message> </xsl:otherwise> </xsl:choose> </xsl:variable> <!-- First, output the document preamble according to target format. This is generally different for each target 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="$target-format eq '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="$target-format eq '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 document, 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="$target-format eq '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"><xsl:text>yes</xsl:text></xsl-out:param> <xsl-out:template name="latex-preamble"> <xsl-out:text> \usepackage{mathpazo} % mathpple is deprecated \usepackage[T1]{fontenc} \usepackage{textcomp} </xsl-out:text> <xsl-out:apply-templates select="environment/latex-packages" /> <xsl-out:value-of select="$latex-hyperref-boilerplate" /> <xsl-out:text> \renewcommand{\ttdefault}{blg} </xsl-out:text> </xsl-out:template> </xsl:when> <xsl:when test="$target-format eq '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"><xsl:text>yes</xsl:text></xsl-out:param> <xsl-out:template name="latex-preamble"> <xsl-out:text> \usepackage[no-math]{fontspec} \usepackage{mathspec} \usepackage{xunicode} \usepackage{xltxtra} \usepackage{textcomp} % ??? </xsl-out:text> <xsl-out:apply-templates select="environment/latex-packages" /> <xsl-out:value-of select="$latex-hyperref-boilerplate" /> <xsl-out:text> \defaultfontfeatures{Mapping=tex-text} \setmainfont{Minion Pro} \setsansfont[Scale=MatchUppercase,BoldFont={Open Sans}]{Open Sans Light} \setmonofont[Scale=MatchLowercase]{Letter Gothic 12 Pitch} \setmathsfont(Latin,Digits){TeX Gyre Pagella} % Hack to prevent digits in hyperlinks from being set in the main font instead of the mono font. % From http://tex.stackexchange.com/questions/99770/problem-with-digits-in-urls-when-using-mathspec-and-hyperref % Note: doesn't matter if this is executed multiple times. \makeatletter \DeclareMathSymbol{0}{\mathalpha}{\eu@DigitsArabic@symfont}{`0} \DeclareMathSymbol{1}{\mathalpha}{\eu@DigitsArabic@symfont}{`1} \DeclareMathSymbol{2}{\mathalpha}{\eu@DigitsArabic@symfont}{`2} \DeclareMathSymbol{3}{\mathalpha}{\eu@DigitsArabic@symfont}{`3} \DeclareMathSymbol{4}{\mathalpha}{\eu@DigitsArabic@symfont}{`4} \DeclareMathSymbol{5}{\mathalpha}{\eu@DigitsArabic@symfont}{`5} \DeclareMathSymbol{6}{\mathalpha}{\eu@DigitsArabic@symfont}{`6} \DeclareMathSymbol{7}{\mathalpha}{\eu@DigitsArabic@symfont}{`7} \DeclareMathSymbol{8}{\mathalpha}{\eu@DigitsArabic@symfont}{`8} \DeclareMathSymbol{9}{\mathalpha}{\eu@DigitsArabic@symfont}{`9} \makeatother </xsl-out:text> </xsl-out:template> </xsl:when> <!-- No need for an otherwise, as weird target 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 target format. This is generally the same across similar target formats. --> <xsl:choose> <xsl:when test="$target-format = ('html', 'xhtml')"> <!-- *** (X)HTML Output *** --> <!-- Default to PNG images for web dispay. --> <xsl-out:param name="image-format"><xsl:text>png</xsl:text></xsl-out:param> <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>https://blackboard.otago.ac.nz/bbcswebdav/courses/</xsl-out:text> <xsl-out:value-of select="$subject-code" /> <xsl-out:value-of select="$paper-number" /> <xsl-out:text>_</xsl-out:text> <xsl-out:value-of select="$period-code" /> <xsl-out:text>DNI_</xsl-out:text> <xsl-out:value-of select="$paper-year" /> <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> <xsl:text>text/html;charset=</xsl:text> <xsl:value-of select="$text-encoding" /> </xsl-out:text> </xsl-out:attribute> </xsl-out:element> <title> <xsl-out:choose> <xsl-out:when test="@class eq 'calendar'"> <xsl-out:value-of select="$subject-code" /> <xsl-out:value-of select="$paper-number" /> <xsl-out:text> Teaching Calendar, </xsl-out:text> <xsl-out:value-of select="$period-string" /> <xsl-out:text>, </xsl-out:text> <xsl-out:value-of select="$paper-year" /> </xsl-out:when> <xsl-out:otherwise> <xsl-out:apply-templates select="title" mode="preamble" /> </xsl-out:otherwise> </xsl-out:choose> </title> </head> <body> <xsl-out:choose> <xsl-out:when test="@class eq 'calendar'" /> <xsl-out:otherwise> <xsl-out:apply-templates select="title" mode="title" /> <xsl-out:apply-templates select="date" mode="title" /> <xsl-out:apply-templates select="due-date" mode="title" /> </xsl-out:otherwise> </xsl-out:choose> <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> <xsl-out:call-template name="build-date-internal"> <xsl-out:with-param name="format">long</xsl-out:with-param> <xsl-out:with-param name="style">footer</xsl-out:with-param> </xsl-out:call-template> </body> </html> </xsl-out:template> </xsl:when> <xsl:when test="$target-format = ('latex', 'xelatex')"> <!-- Set to pdf if using PDFLaTeX, otherwise eps. --> <xsl-out:param name="image-format"><xsl:text>pdf</xsl:text></xsl-out:param> <!-- Generate macro to encode the document class name. Note that if the document class loads a package that the boilerplate in this template also attempts to load, it may cause an "option clash" error. If so, the loading of that package will need to be made conditional in the boilerplate (using \@ifpackageloaded). So far this applies to the following packages: * geometry * hyperref Other packages that *might* cause similar problems (guessing here): * listings --> <xsl-out:template name="setup-document-class"> <xsl-out:text> \def\DocumentClass{</xsl-out:text> <xsl-out:value-of select="@latex-document-class" /> <xsl-out:if test="not( @latex-document-class )"> <xsl-out:text>article</xsl-out:text> </xsl-out:if> <xsl-out:text>} </xsl-out:text> </xsl-out:template> <!-- Generate macro to specify document class options. --> <xsl-out:template name="setup-class-options"> <xsl-out:text> \def\LaTeXOptions{</xsl-out:text> <xsl-out:value-of select="string-join(( if (@latex-font-size) then @latex-font-size else '12pt', if (@latex-paper-size) then @latex-paper-size else 'a4paper', @latex-class-options), ',')" /> <xsl-out:text>} </xsl-out:text> </xsl-out:template> <!-- *** (Xe)LaTeX Source Output *** --> <xsl-out:template match="/document"> <xsl-out:choose> <!-- standalone = "yes" means generate an entire valid (Xe)LaTeX source document. --> <xsl-out:when test="$standalone eq 'yes'"> <xsl-out:text> % THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT! </xsl-out:text> <xsl-out:call-template name="setup-class-options" /> <xsl-out:call-template name="setup-document-class" /> <xsl-out:text> \PassOptionsToClass{\LaTeXOptions}{\DocumentClass} \documentclass{\DocumentClass} % Set up paper variables, if applicable. \makeatletter \@ifpackageloaded{lecturecommon}{\input{</xsl-out:text><xsl-out:value-of select="$paper-include-path" /><xsl-out:text>/</xsl-out:text><xsl-out:value-of select="$latex-initialisation-file" /><xsl-out:text>}} \makeatother % Avoid option clash if document class already loaded it. \makeatletter \@ifpackageloaded{geometry}{}{\usepackage[margin=1in]{geometry}} \makeatother \usepackage{multirow} \usepackage{longtable} \usepackage{graphicx} \usepackage{verbatim} % needed for \verbatiminput \usepackage{relalg} % needed for join operators \usepackage{pifont} \usepackage[mode=text]{siunitx} % number and SI unit formatting ([mode=text] needed to make it use the correct % maths typeface under Unicode/fontspec, otherwise it uses Computer Modern. Works % fine in non-Unicode regardless.) \usepackage{listings} % nicely formatted code listings \usepackage[normalem]{ulem} % fancy underlining, strikeout, etc. \usepackage{boxedminipage} \usepackage{parskip} % Space-separated rather than indented paragraphs. \usepackage{rotating} % Rotate stuff. \usepackage{microtype} % For better typesetting in general. \makeatletter \@ifpackageloaded{amsmath}{}{\usepackage{amsmath}} \makeatother </xsl-out:text> <xsl-out:call-template name="latex-preamble" /> <xsl-out:apply-templates select="environment/latex-commands" /> <xsl-out:text> \newenvironment{answer}{\par\vspace{0.5em}\itshape}{\normalfont\vspace{1.5em}} % Listings setup. We preload the most commonly used languages to speed things % up. Other languages will still work, just not quite as quickly. \lstloadlanguages{Oracle} \lstset{basicstyle=\ttfamily,basewidth=0.5em,escapeinside={(@}{@)}, showspaces=false,showstringspaces=false} </xsl-out:text> <xsl-out:choose> <xsl-out:when test="@latex-document-class eq 'lectureassignment'"> <xsl-out:text>\SetAssignmentNumber{</xsl-out:text> <xsl-out:value-of select="@sequence-number" /> <xsl-out:text>}</xsl-out:text> <xsl-out:call-template name="newline-internal" /> </xsl-out:when> <xsl-out:when test="@latex-document-class eq 'lectureworksheet'"> <xsl-out:text>\SetWeekNumber{</xsl-out:text> <xsl-out:value-of select="@sequence-number" /> <xsl-out:text>}</xsl-out:text> <xsl-out:call-template name="newline-internal" /> </xsl-out:when> <xsl-out:otherwise /> </xsl-out:choose> <xsl-out:apply-templates select="title" mode="preamble" /> <xsl-out:call-template name="newline-internal" /> <xsl-out:apply-templates select="author" mode="preamble" /> <xsl-out:call-template name="newline-internal" /> <xsl-out:apply-templates select="date|due-date" mode="preamble" /> <xsl-out:call-template name="newline-internal" /> <xsl-out:text> \begin{document} </xsl-out:text> <xsl-out:if test="not(@suppress-latex-title) or not(@suppress-latex-title = ('yes', 'y', 'true', 't', '1'))"> <xsl-out:text> \maketitle </xsl-out:text> </xsl-out:if> <!-- Note that the generate-latex-toc attribute doesn't override anything that the document class does. If the document class generates a table of contents anyway, the value of the attribute is irrelevant. --> <xsl-out:if test="@generate-latex-toc eq 'yes'"> <xsl-out:text> \tableofcontents </xsl-out:text> </xsl-out:if> <xsl-out:text> </xsl-out:text> <xsl-out:apply-templates /> <!-- If you're having problems with the build date appearing in weird or annoying locations (usually because of floating items like tables and figures), set document/@auto-latex-build-date to "no". You can then use the build-date element to insert the build date wherever you like, if necessary. This really only applies to LaTeX documents. The behaviour of HTML documents is much more predictable because they don't have elements with "minds of their own", so the build date is guaranteed to always appear at the very end. --> <xsl-out:if test="not(@auto-latex-build-date) or not(@auto-latex-build-date = ('no', 'n', 'false', 'f', '0'))"> <xsl-out:call-template name="build-date-internal"> <xsl-out:with-param name="format">long</xsl-out:with-param> <xsl-out:with-param name="style">footer</xsl-out:with-param> </xsl-out:call-template> </xsl-out:if> <xsl-out:text>\end{document}</xsl-out:text> </xsl-out:when> <!-- standalone = "no" means generate a (Xe)LaTeX source fragment. --> <xsl-out:otherwise> <xsl-out:apply-templates select="title" mode="chapter" /> <xsl-out:apply-templates select="*[not(self::title)]" /> <xsl-out:if test="not(@auto-latex-build-date) or not(@auto-latex-build-date = ('no', 'n', 'false', 'f', '0'))"> <xsl-out:call-template name="build-date-internal"> <xsl-out:with-param name="format">long</xsl-out:with-param> <xsl-out:with-param name="style">footer</xsl-out:with-param> </xsl-out:call-template> </xsl-out:if> </xsl-out:otherwise> </xsl-out:choose> </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> <xsl:apply-templates /> </xsl-out:stylesheet> </xsl:template> <!-- Copy across templates according to the target format. If there's no common code for a particular format, an empty template is generated. --> <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 target formats. Any code not specific to a particular target format will therefore always appear FIRST in the resulting template. --> <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('/', $target-format, '/'))]/node()" /> <xsl:copy-of select="*[name(.) = $target-format]/node()" /> </xsl-out:template> </xsl:template> <!-- Dealing with functions is slightly more complex than templates, as functions aren't allowed to be empty. We therefore have to completely ignore function definitions that have no code for the target format. The second, more specific template will match in preference to the empty one. --> <xsl:template match="function" /> <xsl:template match="function[common[contains( @formats, concat( '/', $target-format, '/' ) )]]|function[common[not( @formats )]]"> <xsl-out:function> <!-- 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 target formats. Any code not specific to a particular target format will therefore always appear FIRST in the resulting template. --> <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( '/', $target-format, '/' ) )]/node()" /> <xsl:copy-of select="*[name( . )=$target-format]/node()" /> </xsl-out:function> </xsl:template> <!-- Include templates from a stylesheet sub-module. This enables us to modularise the master stylesheet. --> <xsl:template match="include"> <xsl:apply-templates select="document( @href )/stylesheet/*" /> </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> </xsl:stylesheet>
<?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:xs="http://www.w3.org/2001/XMLSchema" xmlns:infosci="http://info-nts-12.otago.ac.nz/infosci"> <!-- 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="xml" encoding="utf-8" cdata-section-elements="html" /> <!-- What target format are we generating a styesheet for? Possible values: html, xhtml, latex (includes pdflatex), xelatex. --> <xsl:param name="target-format"><xsl:text>html</xsl:text></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> <!-- *** TEMPLATES *** --> <xsl:template match="/"> <xsl-out:stylesheet version="2.0"> <xsl-out:strip-space elements="*" /> <xsl-out:param name="subject-code"><xsl:text>INFO</xsl:text></xsl-out:param> <xsl-out:param name="paper-number" /> <xsl-out:param name="paper-year" select="year-from-date( current-date() )"/> <xsl-out:param name="period-code" /> <xsl-out:param name="showanswers"><xsl:text>no</xsl:text></xsl-out:param> <!-- This is normally the path to the current document directory. --> <xsl-out:param name="base-path"><xsl:text>.</xsl:text></xsl-out:param> <!-- This is normally the path to the root directory of the paper tree in the filesystem. --> <xsl-out:param name="paper-include-path"><xsl:text>.</xsl:text></xsl-out:param> <!-- This is normally the file paper_init.tex in the root of the paper tree. --> <xsl-out:param name="latex-initialisation-file"><xsl:text>paper_init</xsl:text></xsl-out:param> <!-- Full period string corresponding to the supplied period code. --> <xsl-out:variable name="period-string" select="infosci:expand-period-code( $period-code )" /> <!-- The date and time when the document was last built. --> <xsl-out:variable name="date-built" select="current-dateTime()" /> <!-- Get the name of the document being processed. --> <xsl-out:variable name="document-name" select="reverse( tokenize( base-uri(), '/' ) )[1]" /> <!-- Include the generated Oracle documentation code. --> <xsl-out:include href="oracle-docs.xsl" /> <!-- Boilerplate (Xe)LaTeX code for loading hyperref. If the package is already loaded (by the document class), attempting to load it again will cause an "option clash" error. To avoid this, check first whether it's already loaded. We apply the required settings afterwards regardless. --> <xsl-out:variable name="latex-hyperref-boilerplate"> <xsl-out:text> % Avoid option clash if document class already loaded it. \makeatletter \@ifpackageloaded{hyperref}{}{\usepackage{hyperref}} \makeatother % Safer to specify the hyperref options directly rather than relying on % the default hyperref.cfg, as XeLaTeX seems to ignore it :(. \hypersetup{pdfpagemode=UseNone,colorlinks,urlcolor=blue,citecolor=blue,% linkcolor=blue,breaklinks} </xsl-out:text> </xsl-out:variable> <!-- 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="$target-format = ('latex', 'html')"> <xsl:text>iso-8859-1</xsl:text> </xsl:when> <xsl:when test="$target-format = ('xelatex', 'xhtml')"> <xsl:text>utf-8</xsl:text> </xsl:when> <xsl:otherwise> <xsl:message terminate="yes"> <xsl:text>Sorry, unknown target format: </xsl:text><xsl:value-of select="$target-format" /> </xsl:message> </xsl:otherwise> </xsl:choose> </xsl:variable> <!-- First, output the document preamble according to target format. This is generally different for each target 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="$target-format eq '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="$target-format eq '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 document, 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="$target-format eq '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"><xsl:text>yes</xsl:text></xsl-out:param> <xsl-out:template name="latex-preamble"> <xsl-out:text> \usepackage{mathpazo} % mathpple is deprecated \usepackage[T1]{fontenc} \usepackage{textcomp} </xsl-out:text> <xsl-out:apply-templates select="environment/latex-packages" /> <xsl-out:value-of select="$latex-hyperref-boilerplate" /> <xsl-out:text> \renewcommand{\ttdefault}{blg} </xsl-out:text> </xsl-out:template> </xsl:when> <xsl:when test="$target-format eq '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"><xsl:text>yes</xsl:text></xsl-out:param> <xsl-out:template name="latex-preamble"> <xsl-out:text> \usepackage[no-math]{fontspec} \usepackage{mathspec} \usepackage{xunicode} \usepackage{xltxtra} \usepackage{textcomp} % ??? </xsl-out:text> <xsl-out:apply-templates select="environment/latex-packages" /> <xsl-out:value-of select="$latex-hyperref-boilerplate" /> <xsl-out:text> \defaultfontfeatures{Mapping=tex-text} \setmainfont{Minion Pro} \setsansfont[Scale=MatchUppercase,BoldFont={Open Sans}]{Open Sans Light} \setmonofont[Scale=MatchLowercase]{Letter Gothic 12 Pitch} \setmathsfont(Latin,Digits){TeX Gyre Pagella} % Hack to prevent digits in hyperlinks from being set in the main font instead of the mono font. % From http://tex.stackexchange.com/questions/99770/problem-with-digits-in-urls-when-using-mathspec-and-hyperref % Note: doesn't matter if this is executed multiple times. \makeatletter \DeclareMathSymbol{0}{\mathalpha}{\eu@DigitsArabic@symfont}{`0} \DeclareMathSymbol{1}{\mathalpha}{\eu@DigitsArabic@symfont}{`1} \DeclareMathSymbol{2}{\mathalpha}{\eu@DigitsArabic@symfont}{`2} \DeclareMathSymbol{3}{\mathalpha}{\eu@DigitsArabic@symfont}{`3} \DeclareMathSymbol{4}{\mathalpha}{\eu@DigitsArabic@symfont}{`4} \DeclareMathSymbol{5}{\mathalpha}{\eu@DigitsArabic@symfont}{`5} \DeclareMathSymbol{6}{\mathalpha}{\eu@DigitsArabic@symfont}{`6} \DeclareMathSymbol{7}{\mathalpha}{\eu@DigitsArabic@symfont}{`7} \DeclareMathSymbol{8}{\mathalpha}{\eu@DigitsArabic@symfont}{`8} \DeclareMathSymbol{9}{\mathalpha}{\eu@DigitsArabic@symfont}{`9} \makeatother </xsl-out:text> </xsl-out:template> </xsl:when> <!-- No need for an otherwise, as weird target 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 target format. This is generally the same across similar target formats. --> <xsl:choose> <xsl:when test="$target-format = ('html', 'xhtml')"> <!-- *** (X)HTML Output *** --> <!-- Default to PNG images for web dispay. --> <xsl-out:param name="image-format"><xsl:text>png</xsl:text></xsl-out:param> <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>https://blackboard.otago.ac.nz/bbcswebdav/courses/</xsl-out:text> <xsl-out:value-of select="$subject-code" /> <xsl-out:value-of select="$paper-number" /> <xsl-out:text>_</xsl-out:text> <xsl-out:value-of select="$period-code" /> <xsl-out:text>DNI_</xsl-out:text> <xsl-out:value-of select="$paper-year" /> <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> <xsl:text>text/html;charset=</xsl:text> <xsl:value-of select="$text-encoding" /> </xsl-out:text> </xsl-out:attribute> </xsl-out:element> <title> <xsl-out:choose> <xsl-out:when test="@class eq 'calendar'"> <xsl-out:value-of select="$subject-code" /> <xsl-out:value-of select="$paper-number" /> <xsl-out:text> Teaching Calendar, </xsl-out:text> <xsl-out:value-of select="$period-string" /> <xsl-out:text>, </xsl-out:text> <xsl-out:value-of select="$paper-year" /> </xsl-out:when> <xsl-out:otherwise> <xsl-out:apply-templates select="title" mode="preamble" /> </xsl-out:otherwise> </xsl-out:choose> </title> </head> <body> <xsl-out:choose> <xsl-out:when test="@class eq 'calendar'" /> <xsl-out:otherwise> <xsl-out:apply-templates select="title" mode="title" /> <xsl-out:apply-templates select="date" mode="title" /> <xsl-out:apply-templates select="due-date" mode="title" /> </xsl-out:otherwise> </xsl-out:choose> <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> <xsl-out:call-template name="build-date-internal"> <xsl-out:with-param name="format">long</xsl-out:with-param> <xsl-out:with-param name="style">footer</xsl-out:with-param> </xsl-out:call-template> </body> </html> </xsl-out:template> </xsl:when> <xsl:when test="$target-format = ('latex', 'xelatex')"> <!-- Set to pdf if using PDFLaTeX, otherwise eps. --> <xsl-out:param name="image-format"><xsl:text>pdf</xsl:text></xsl-out:param> <!-- Generate macro to encode the document class name. Note that if the document class loads a package that the boilerplate in this template also attempts to load, it may cause an "option clash" error. If so, the loading of that package will need to be made conditional in the boilerplate (using \@ifpackageloaded). So far this applies to the following packages: * geometry * hyperref Other packages that *might* cause similar problems (guessing here): * listings --> <xsl-out:template name="setup-document-class"> <xsl-out:text> \def\DocumentClass{</xsl-out:text> <xsl-out:value-of select="@latex-document-class" /> <xsl-out:if test="not( @latex-document-class )"> <xsl-out:text>article</xsl-out:text> </xsl-out:if> <xsl-out:text>} </xsl-out:text> </xsl-out:template> <!-- Generate macro to specify document class options. --> <xsl-out:template name="setup-class-options"> <xsl-out:text> \def\LaTeXOptions{</xsl-out:text> <xsl-out:value-of select="string-join(( if (@latex-font-size) then @latex-font-size else '12pt', if (@latex-paper-size) then @latex-paper-size else 'a4paper', @latex-class-options), ',')" /> <xsl-out:text>} </xsl-out:text> </xsl-out:template> <!-- *** (Xe)LaTeX Source Output *** --> <xsl-out:template match="/document"> <xsl-out:choose> <!-- standalone = "yes" means generate an entire valid (Xe)LaTeX source document. --> <xsl-out:when test="$standalone eq 'yes'"> <xsl-out:text> % THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT! </xsl-out:text> <xsl-out:call-template name="setup-class-options" /> <xsl-out:call-template name="setup-document-class" /> <xsl-out:text> \PassOptionsToClass{\LaTeXOptions}{\DocumentClass} \documentclass{\DocumentClass} % Set up paper variables, if applicable. \makeatletter \@ifpackageloaded{lecturecommon}{\input{</xsl-out:text><xsl-out:value-of select="$paper-include-path" /><xsl-out:text>/</xsl-out:text><xsl-out:value-of select="$latex-initialisation-file" /><xsl-out:text>}} \makeatother % Avoid option clash if document class already loaded it. \makeatletter \@ifpackageloaded{geometry}{}{\usepackage[margin=1in]{geometry}} \makeatother \usepackage{multirow} \usepackage{graphicx} \usepackage{verbatim} % needed for \verbatiminput \usepackage{relalg} % needed for join operators \usepackage{pifont} \usepackage[mode=text]{siunitx} % number and SI unit formatting ([mode=text] needed to make it use the correct % maths typeface under Unicode/fontspec, otherwise it uses Computer Modern. Works % fine in non-Unicode regardless.) \usepackage{listings} % nicely formatted code listings \usepackage[normalem]{ulem} % fancy underlining, strikeout, etc. \usepackage{boxedminipage} \usepackage{parskip} % Space-separated rather than indented paragraphs. \usepackage{rotating} % Rotate stuff. \usepackage{microtype} % For better typesetting in general. \makeatletter \@ifpackageloaded{amsmath}{}{\usepackage{amsmath}} \makeatother </xsl-out:text> <xsl-out:call-template name="latex-preamble" /> <xsl-out:apply-templates select="environment/latex-commands" /> <xsl-out:text> \newenvironment{answer}{\par\vspace{0.5em}\itshape}{\normalfont\vspace{1.5em}} % Listings setup. We preload the most commonly used languages to speed things % up. Other languages will still work, just not quite as quickly. \lstloadlanguages{Oracle} \lstset{basicstyle=\ttfamily,basewidth=0.5em,escapeinside={(@}{@)}, showspaces=false,showstringspaces=false} </xsl-out:text> <xsl-out:choose> <xsl-out:when test="@latex-document-class eq 'lectureassignment'"> <xsl-out:text>\SetAssignmentNumber{</xsl-out:text> <xsl-out:value-of select="@sequence-number" /> <xsl-out:text>}</xsl-out:text> <xsl-out:call-template name="newline-internal" /> </xsl-out:when> <xsl-out:when test="@latex-document-class eq 'lectureworksheet'"> <xsl-out:text>\SetWeekNumber{</xsl-out:text> <xsl-out:value-of select="@sequence-number" /> <xsl-out:text>}</xsl-out:text> <xsl-out:call-template name="newline-internal" /> </xsl-out:when> <xsl-out:otherwise /> </xsl-out:choose> <xsl-out:apply-templates select="title" mode="preamble" /> <xsl-out:call-template name="newline-internal" /> <xsl-out:apply-templates select="author" mode="preamble" /> <xsl-out:call-template name="newline-internal" /> <xsl-out:apply-templates select="date|due-date" mode="preamble" /> <xsl-out:call-template name="newline-internal" /> <xsl-out:text> \begin{document} </xsl-out:text> <xsl-out:if test="not(@suppress-latex-title) or not(@suppress-latex-title = ('yes', 'y', 'true', 't', '1'))"> <xsl-out:text> \maketitle </xsl-out:text> </xsl-out:if> <!-- Note that the generate-latex-toc attribute doesn't override anything that the document class does. If the document class generates a table of contents anyway, the value of the attribute is irrelevant. --> <xsl-out:if test="@generate-latex-toc eq 'yes'"> <xsl-out:text> \tableofcontents </xsl-out:text> </xsl-out:if> <xsl-out:text> </xsl-out:text> <xsl-out:apply-templates /> <!-- If you're having problems with the build date appearing in weird or annoying locations (usually because of floating items like tables and figures), set document/@auto-latex-build-date to "no". You can then use the build-date element to insert the build date wherever you like, if necessary. This really only applies to LaTeX documents. The behaviour of HTML documents is much more predictable because they don't have elements with "minds of their own", so the build date is guaranteed to always appear at the very end. --> <xsl-out:if test="not(@auto-latex-build-date) or not(@auto-latex-build-date = ('no', 'n', 'false', 'f', '0'))"> <xsl-out:call-template name="build-date-internal"> <xsl-out:with-param name="format">long</xsl-out:with-param> <xsl-out:with-param name="style">footer</xsl-out:with-param> </xsl-out:call-template> </xsl-out:if> <xsl-out:text>\end{document}</xsl-out:text> </xsl-out:when> <!-- standalone = "no" means generate a (Xe)LaTeX source fragment. --> <xsl-out:otherwise> <xsl-out:apply-templates select="title" mode="chapter" /> <xsl-out:apply-templates select="*[not(self::title)]" /> <xsl-out:if test="not(@auto-latex-build-date) or not(@auto-latex-build-date = ('no', 'n', 'false', 'f', '0'))"> <xsl-out:call-template name="build-date-internal"> <xsl-out:with-param name="format">long</xsl-out:with-param> <xsl-out:with-param name="style">footer</xsl-out:with-param> </xsl-out:call-template> </xsl-out:if> </xsl-out:otherwise> </xsl-out:choose> </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> <xsl:apply-templates /> </xsl-out:stylesheet> </xsl:template> <!-- Copy across templates according to the target format. If there's no common code for a particular format, an empty template is generated. --> <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 target formats. Any code not specific to a particular target format will therefore always appear FIRST in the resulting template. --> <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('/', $target-format, '/'))]/node()" /> <xsl:copy-of select="*[name(.) = $target-format]/node()" /> </xsl-out:template> </xsl:template> <!-- Dealing with functions is slightly more complex than templates, as functions aren't allowed to be empty. We therefore have to completely ignore function definitions that have no code for the target format. The second, more specific template will match in preference to the empty one. --> <xsl:template match="function" /> <xsl:template match="function[common[contains( @formats, concat( '/', $target-format, '/' ) )]]|function[common[not( @formats )]]"> <xsl-out:function> <!-- 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 target formats. Any code not specific to a particular target format will therefore always appear FIRST in the resulting template. --> <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( '/', $target-format, '/' ) )]/node()" /> <xsl:copy-of select="*[name( . )=$target-format]/node()" /> </xsl-out:function> </xsl:template> <!-- Include templates from a stylesheet sub-module. This enables us to modularise the master stylesheet. --> <xsl:template match="include"> <xsl:apply-templates select="document( @href )/stylesheet/*" /> </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> </xsl:stylesheet>
Show line notes below