Newer
Older
XML / modules / lists.xml
  1. <?xml version="1.0" encoding="utf-8"?>
  2.  
  3. <!--
  4. Environments (in the LaTeX terminology) for enumerated, ordered, and numbered lists. Note the lack of orthgonality that means that elements other than <item> inside lists are ignored.
  5. TODO: Use just xsl:apply-templates and instead of using modes, check what the parent is inside the item template?
  6. -->
  7.  
  8. <stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  9.  
  10.  
  11. <!-- Unordered lists -->
  12. <template name="itemised-list" match="itemised-list|itemize|unordered-list|bulleted-list|bullet-list|bullet-points|UL|ul">
  13. <common formats="/latex/xelatex/">
  14. <xsl:call-template name="newline-internal" />
  15. <xsl:text>\begin{itemize}</xsl:text>
  16. <xsl:call-template name="newline-internal" />
  17. <xsl:apply-templates select="item" mode="normal" />
  18. <xsl:call-template name="newline-internal" />
  19. <xsl:text>\end{itemize}</xsl:text>
  20. <xsl:call-template name="newline-internal" />
  21. </common>
  22. <common formats="/html/xhtml/">
  23. <ul>
  24. <xsl:apply-templates select="item" mode="normal" />
  25. </ul>
  26. </common>
  27. </template>
  28.  
  29. <!--
  30. Ordered lists.
  31. @start: The starting number for the list. [default 1]
  32. -->
  33. <template name="enumerated-list" match="enumerated-list|enumerate|ordered-list|numbered-list|question-list|OL|ol">
  34. <common formats="/latex/xelatex/">
  35. <xsl:call-template name="newline-internal" />
  36. <xsl:text>\begin{enumerate}</xsl:text>
  37. <xsl:call-template name="newline-internal" />
  38. <xsl:if test='@start'>
  39. <!--
  40. Set the appropriate enum counter according to the depth. Use the format attribute of xsl:number to output it in Roman numerals. Depth must be at least 1 (enumi) and at most 4 (enumiv).
  41. -->
  42. <xsl:text>\setcounter{enum</xsl:text>
  43. <xsl:number value="min( ( 1 + count( ancestor::enumerated-list|ancestor::enumerate|ancestor::ordered-list|ancestor::numbered-list|ancestor::question-list|ancestor::OL|ancestor::ol ), 4 ) )" format="i" />
  44. <xsl:text>}{</xsl:text>
  45. <!-- Remember that LaTeX adds 1 to the counter before using it. -->
  46. <xsl:value-of select="@start - 1" />
  47. <xsl:text>}</xsl:text>
  48. </xsl:if>
  49. <xsl:apply-templates select="item" mode="enumerated-list" />
  50. <xsl:call-template name="newline-internal" />
  51. <xsl:text>\end{enumerate}</xsl:text>
  52. <xsl:call-template name="newline-internal" />
  53. </common>
  54. <common formats="/html/xhtml/">
  55. <ol>
  56. <xsl:if test="@start">
  57. <!--
  58. Note that we're using the START attribute of OL, which is actually deprecated in HTML 4 and XHTML. However, the alternative (using CSS styling) is useless, as it doesn't permit different number formatting for different levels of list (e.g., 1., a., ii., etc.). The only standards-compliant solution to this is to forgo HTML list elements completely and do it all ourselves. Ugh, no thanks!
  59. -->
  60. <xsl:attribute name="start">
  61. <xsl:value-of select="@start" />
  62. </xsl:attribute>
  63. </xsl:if>
  64. <xsl:apply-templates select="item" mode="enumerated-list" />
  65. </ol>
  66. </common>
  67. </template>
  68. <!-- Definition or description lists. -->
  69. <template name="definition-list" match="definition-list|description-list|DL|dl">
  70. <common formats="/latex/xelatex/">
  71. <xsl:call-template name="newline-internal" />
  72. <xsl:text>\begin{description}</xsl:text>
  73. <xsl:call-template name="newline-internal" />
  74. <xsl:apply-templates select="item" mode="definition-list" />
  75. <xsl:call-template name="newline-internal" />
  76. <xsl:text>\end{description}</xsl:text>
  77. <xsl:call-template name="newline-internal" />
  78. </common>
  79. <common formats="/html/xhtml/">
  80. <!--
  81. <dl>s in HTML tend to come out with the spacing a bit wrong (or maybe it's just my browser?). Anyway, they don't appear to be displayed correctly. A more portable solution is to use plain <p>s with CSS margins to control the hanging indent. The tricky part is dealing with embedded <paragraph>s inside the <description-list>. The clever details are handled in the "definition-item" template.
  82. -->
  83. <xsl:apply-templates select="item" mode="definition-list" />
  84. </common>
  85. </template>
  86.  
  87.  
  88. <!-- List items for non-definition lists. -->
  89. <template name="list-item" match="item" mode="normal">
  90. <common formats="/latex/xelatex/">
  91. <xsl:text>\item </xsl:text>
  92. <xsl:apply-templates />
  93. <xsl:call-template name="newline-internal" />
  94. </common>
  95. <common formats="/html/xhtml/">
  96. <xsl:choose>
  97. <!--
  98. Check whether there are actual paragraphs or things that should be treated like paragraphs inside the item (there are rather a lot of these!). If so, let them worry about inserting the <p> tags.
  99. -->
  100. <xsl:when test="count(paragraph|para|p|question|answer|code-block|itemised-list|itemize|unordered-list|bulleted-list|bullet-list|bullet-points|UL|ul|enumerated-list|enumerate|ordered-list|numbered-list|question-list|OL|ol|definition-list|description-list|DL|dl) != 0">
  101. <li><xsl:apply-templates /></li>
  102. </xsl:when>
  103. <!--
  104. Otherwise, insert <p> tags surrounding the item content so that the item spacing looks OK.
  105. -->
  106. <xsl:otherwise>
  107. <li><p><xsl:apply-templates /></p></li>
  108. </xsl:otherwise>
  109. </xsl:choose>
  110. </common>
  111. </template>
  112. <!--
  113. Provide the ability to set the numbering of specific items in enumerated lists. Results could be unpredictable if this is applied to an itemised list!
  114. @value: the number to use for the next list item. [default 1]
  115. -->
  116. <template name="enumerated-item-value" match="item[@value]" mode="enumerated-list">
  117. <common formats="/latex/xelatex/">
  118. <!-- Set the appropriate enum counter. -->
  119. <xsl:text>\setcounter{enum</xsl:text>
  120. <xsl:number value="min( ( count( ancestor::enumerated-list|ancestor::enumerate|ancestor::ordered-list|ancestor::numbered-list|ancestor::question-list|ancestor::OL|ancestor::ol ), 4 ) )" format="i" />
  121. <xsl:text>}{</xsl:text>
  122. <!-- Remember that LaTeX adds 1 to the counter before using it. -->
  123. <xsl:value-of select="@value - 1" />
  124. <xsl:text>}</xsl:text>
  125. <xsl:call-template name="newline-internal" />
  126. <xsl:apply-templates select="." mode="normal" />
  127. </common>
  128. <!--
  129. Unfortunately this can't just be a wrapper around the "normal" item template because of the nesting of attributes inside the element.
  130. -->
  131. <common formats="/html/xhtml/">
  132. <xsl:choose>
  133. <!--
  134. Check whether there are actual paragraphs or things that should be treated like paragraphs inside the item (there are rather a lot of these!). If so, let them worry about inserting the <p> tags.
  135. -->
  136. <xsl:when test="count(paragraph|para|p|question|answer|code-block|itemised-list|itemize|unordered-list|bulleted-list|bullet-list|bullet-points|UL|ul|enumerated-list|enumerate|ordered-list|numbered-list|question-list|OL|ol|definition-list|description-list|DL|dl) != 0">
  137. <li>
  138. <xsl:attribute name="value" select="@value" />
  139. <xsl:apply-templates />
  140. </li>
  141. </xsl:when>
  142. <!--
  143. Otherwise, insert <p> tags surrounding the item content
  144. so that the item spacing looks OK.
  145. -->
  146. <xsl:otherwise>
  147. <li>
  148. <xsl:attribute name="value" select="@value" />
  149. <p><xsl:apply-templates /></p>
  150. </li>
  151. </xsl:otherwise>
  152. </xsl:choose>
  153. </common>
  154. </template>
  155. <!-- Normally numbered enumerated item. -->
  156. <template name="enumerated-item" match="item[not( @value )]" mode="enumerated-list">
  157. <common>
  158. <xsl:apply-templates select="." mode="normal" />
  159. </common>
  160. </template>
  161.  
  162. <!-- List items for definition lists. -->
  163. <template name="definition-item" match="item" mode="definition-list">
  164. <common formats="/latex/xelatex/">
  165. <xsl:text>\item[</xsl:text>
  166. <xsl:apply-templates select="keyword|term|topic|DT|dt" />
  167. <xsl:text>] </xsl:text>
  168. <xsl:apply-templates select="definition|description|discourse|DD|dd" />
  169. <xsl:call-template name="newline-internal" />
  170. </common>
  171. <common formats="/html/xhtml/">
  172. <!--
  173. We have to be a little clever here, because we're transforming potentially multiple embedded elements (embedded <paragraph>s in particular) into one or more <p> tags in the HTML. We need to ensure that:
  174. (a) we don't end up with nested <p> tags,
  175. (b) all paragraphs are correctly indented, and
  176. (c) if the first thing following the <definition> is a <paragraph> or text node, it gets positioned correctly relative to the <keyword>.
  177.  
  178. We know that the <keyword> won't have embedded <paragraph>s (it doesn't really make sense, not that we actually check :). The only thing we therefore need to check for is <paragraph> elements inside the <definition> element.
  179. -->
  180. <xsl:choose>
  181. <!--
  182. If the first sub-node of the <definition> is NOT a <p> node, then the whole thing should be just simple text and contain only basic formatting elements, if anything (i.e., no lists!). We therefore just wrap the <keyword> and <definition> within a <p> with a hanging indent and finish. Note the use of child::node()[1|2], because we don't necessarily know what variants of <keyword> and <definition> have actually been used, but we know that they will (should!) always be the first and second children of the <item> respectively.
  183. This probably is the most common case, so test for it first.
  184. -->
  185. <xsl:when test="not( child::node()[2]/child::node()[1][self::p] or child::node()[2]/child::node()[1][self::paragraph] )">
  186. <p class="definition1">
  187. <xsl:apply-templates select="child::node()[1]" />
  188. <xsl:text> </xsl:text>
  189. <xsl:apply-templates select="child::node()[2]" />
  190. </p>
  191. </xsl:when>
  192. <!--
  193. If the first sub-node of the <definition> IS a <p> or <paragraph>, then we need to skip over the processing of this element to avoid nested <p>s in the output. Any remaining sub-nodes are processed normally, except that we pass in the HTMLStyle parameter to ensure that any remaining paragraph elements are correctly indented. I would have used modes for this, but it killed embedded <itemize>s, because there isn't an <itemize> template with the appropriate mode (nor is there a need for one). Grr.
  194. -->
  195. <xsl:otherwise>
  196. <p class="definition1">
  197. <xsl:apply-templates select="child::node()[1]" />
  198. <xsl:text> </xsl:text>
  199. <xsl:apply-templates select="child::node()[2]/child::node()[1]/node()" />
  200. </p>
  201. <xsl:apply-templates select="child::node()[2]/*[position() > 1]">
  202. <xsl:with-param name="HTMLStyle">definition2</xsl:with-param>
  203. </xsl:apply-templates>
  204. </xsl:otherwise>
  205. </xsl:choose>
  206. </common>
  207. </template>
  208. <!--
  209. Need to provide some context here as, e.g., <term> is also a standalone element.
  210. -->
  211. <template name="keyword" match="item/keyword|item/term|item/topic|item/DT|item/dt">
  212. <common formats="/latex/xelatex/">
  213. <xsl:apply-templates />
  214. </common>
  215. <common formats="/html/xhtml/">
  216. <strong><xsl:apply-templates /></strong>
  217. </common>
  218. </template>
  219. <!--
  220. Need to provide some context here as, e.g., <description> is also used within <image>.
  221. -->
  222. <template name="definition" match="item/definition|item/description|item/discourse|item/DD|item/dd">
  223. <common>
  224. <xsl:apply-templates />
  225. </common>
  226. </template>
  227.  
  228.  
  229. </stylesheet>