simpletable.xsl 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!--
  3. This file is part of the DITA Open Toolkit project.
  4. Copyright 2016 Jarno Elovirta
  5. See the accompanying LICENSE file for applicable license.
  6. -->
  7. <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  8. xmlns:xs="http://www.w3.org/2001/XMLSchema"
  9. xmlns:dita2html="http://dita-ot.sourceforge.net/ns/200801/dita2html"
  10. xmlns:ditamsg="http://dita-ot.sourceforge.net/ns/200704/ditamsg"
  11. xmlns:dita-ot="http://dita-ot.sourceforge.net/ns/201007/dita-ot"
  12. xmlns:table="http://dita-ot.sourceforge.net/ns/201007/dita-ot/table"
  13. xmlns:simpletable="http://dita-ot.sourceforge.net/ns/201007/dita-ot/simpletable"
  14. version="2.0"
  15. exclude-result-prefixes="xs dita2html ditamsg dita-ot table simpletable">
  16. <xsl:template match="*[contains(@class, ' topic/simpletable ')]" mode="generate-table-summary-attribute">
  17. <!-- Override this to use a local convention for setting table's @summary attribute,
  18. until OASIS provides a standard mechanism for setting. -->
  19. </xsl:template>
  20. <xsl:template name="dita2html:simpletable-cols">
  21. <xsl:variable name="col-count" as="xs:integer">
  22. <xsl:apply-templates select="." mode="dita2html:get-max-entry-count"/>
  23. </xsl:variable>
  24. <xsl:variable name="col-widths" as="xs:double*">
  25. <xsl:variable name="widths" select="tokenize(normalize-space(translate(@relcolwidth, '*', '')), '\s+')" as="xs:string*"/>
  26. <xsl:for-each select="$widths">
  27. <xsl:choose>
  28. <xsl:when test=". castable as xs:double">
  29. <xsl:sequence select="xs:double(.)"/>
  30. </xsl:when>
  31. <xsl:otherwise>
  32. <xsl:sequence select="xs:double(1)"/>
  33. </xsl:otherwise>
  34. </xsl:choose>
  35. </xsl:for-each>
  36. <xsl:for-each select="1 to ($col-count - count($widths))">
  37. <xsl:sequence select="xs:double(1)"/>
  38. </xsl:for-each>
  39. </xsl:variable>
  40. <xsl:variable name="col-widths-sum" select="sum($col-widths)"/>
  41. <colgroup>
  42. <xsl:for-each select="$col-widths">
  43. <col style="width:{(. div $col-widths-sum) * 100}%"/>
  44. </xsl:for-each>
  45. </colgroup>
  46. </xsl:template>
  47. <xsl:template match="*[contains(@class, ' topic/simpletable ')]" mode="dita2html:get-max-entry-count" as="xs:integer">
  48. <xsl:variable name="counts" as="xs:integer*">
  49. <xsl:for-each select="*[contains(@class, ' topic/sthead ')] |
  50. *[contains(@class, ' topic/strow ')]">
  51. <xsl:sequence select="count(*[contains(@class, ' topic/stentry ')])"/>
  52. </xsl:for-each>
  53. </xsl:variable>
  54. <xsl:sequence select="max($counts)"/>
  55. </xsl:template>
  56. <!-- Output the ID for a simpletable entry, when it is specified. If no ID is specified,
  57. and this is a header row, generate an ID. The entry is considered a header entry
  58. when the it is inside <sthead>, or when it is in the column specified in the keycol
  59. attribute on <simpletable>
  60. NOTE: It references simpletable with parent::*/parent::* in order to avoid problems
  61. with nested simpletables. -->
  62. <!-- Deprecated in 3.0 in favor of HTML5 @scope attribute. -->
  63. <xsl:template name="output-stentry-id">
  64. <!-- Find the position in this row -->
  65. <xsl:variable name="thiscolnum"><xsl:number level="single" count="*[contains(@class, ' topic/stentry ')]"/></xsl:variable>
  66. <xsl:choose>
  67. <xsl:when test="@id"> <!-- If ID is specified, always use it -->
  68. <xsl:attribute name="id" select="dita-ot:generate-html-id(.)"/>
  69. </xsl:when>
  70. <!-- If no ID is specified, and this is a header cell, generate an ID -->
  71. <xsl:when test="parent::*[contains(@class, ' topic/sthead ')] or
  72. (parent::*/parent::*/@keycol and number(parent::*/parent::*/@keycol) = number($thiscolnum))">
  73. <xsl:attribute name="id" select="generate-id(.)"/>
  74. </xsl:when>
  75. </xsl:choose>
  76. </xsl:template>
  77. <!-- Output the headers attribute for screen readers. If specified, it should match both
  78. of the following:
  79. * the <stentry> with the same position in the sthead
  80. * the <stentry> that is in the key column (specified in @keycol on simpletable)
  81. Note: This function is not called within sthead, so sthead never gets headers.
  82. NOTE: I reference simpletable with parent::*/parent::* in order to avoid problems
  83. with nested simpletables. -->
  84. <!-- Deprecated in 3.0 in favor of HTML5 @scope attribute -->
  85. <xsl:template name="set.stentry.headers">
  86. <xsl:variable name="keycol" select="parent::*/parent::*/@keycol"/>
  87. <xsl:if test="$keycol | parent::*/parent::*/*[contains(@class, ' topic/sthead ')]">
  88. <xsl:variable name="thiscolnum"><xsl:number level="single" count="*[contains(@class, ' topic/stentry ')]"/></xsl:variable>
  89. <!-- If there is a keycol, and this is not the key column, get the ID for the keycol -->
  90. <xsl:variable name="keycolhead">
  91. <xsl:if test="$keycol and $thiscolnum != number($keycol)">
  92. <xsl:variable name="col" select="../*[number($keycol)]"/>
  93. <xsl:choose>
  94. <xsl:when test="$col/@id">
  95. <xsl:value-of select="$col/@id"/>
  96. </xsl:when>
  97. <xsl:otherwise>
  98. <xsl:value-of select="generate-id($col)"/>
  99. </xsl:otherwise>
  100. </xsl:choose>
  101. </xsl:if>
  102. </xsl:variable>
  103. <!-- If there is a header, get the ID from the head cell in this column.
  104. Go up to simpletable, into the row, to the entry at column $thiscolnum -->
  105. <xsl:variable name="header">
  106. <xsl:if test="parent::*/parent::*/*[contains(@class, ' topic/sthead ')]/*[contains(@class, ' topic/stentry ')][number($thiscolnum)]">
  107. <xsl:value-of select="dita-ot:generate-html-id(parent::*/parent::*/*[contains(@class, ' topic/sthead ')]/*[contains(@class, ' topic/stentry ')][number($thiscolnum)])"/>
  108. </xsl:if>
  109. </xsl:variable>
  110. <!-- If there is a keycol header or an sthead header, create the attribute -->
  111. <xsl:if test="string-length($header) > 0 or string-length($keycolhead) > 0">
  112. <xsl:attribute name="headers">
  113. <xsl:value-of select="$header"/>
  114. <xsl:if test="string-length($header) > 0 and string-length($keycolhead) > 0"><xsl:text> </xsl:text></xsl:if>
  115. <xsl:value-of select="$keycolhead"/>
  116. </xsl:attribute>
  117. </xsl:if>
  118. </xsl:if>
  119. </xsl:template>
  120. <!-- For simple table headers: <TH> Set align="right" when in a BIDI area -->
  121. <xsl:template name="th-align">
  122. <xsl:variable name="biditest" as="xs:boolean">
  123. <xsl:call-template name="bidi-area"/>
  124. </xsl:variable>
  125. <xsl:text>text-align:</xsl:text>
  126. <xsl:value-of select="if ($biditest) then 'right' else 'left'"/>
  127. <xsl:text>;</xsl:text>
  128. </xsl:template>
  129. <xsl:template name="stentry-templates">
  130. <xsl:choose>
  131. <xsl:when test="not(*|text()|processing-instruction()) and @specentry">
  132. <xsl:value-of select="@specentry"/>
  133. </xsl:when>
  134. <xsl:when test="not(*|text()|processing-instruction())">
  135. <xsl:text>&#160;</xsl:text> <!-- nbsp -->
  136. </xsl:when>
  137. <xsl:otherwise>
  138. <xsl:apply-templates/>
  139. </xsl:otherwise>
  140. </xsl:choose>
  141. </xsl:template>
  142. <xsl:function name="simpletable:generate-headers" as="xs:string">
  143. <xsl:param name="el" as="element()"/>
  144. <xsl:param name="suffix" as="xs:string"/>
  145. <xsl:sequence select="string-join((generate-id($el), $suffix), '-')"/>
  146. </xsl:function>
  147. <xsl:template match="*[contains(@class,' topic/simpletable ')]
  148. [empty(*[contains(@class,' topic/strow ')]/*[contains(@class,' topic/stentry ')])]" priority="10"/>
  149. <xsl:template match="*[contains(@class,' topic/strow ') or contains(@class,' topic/sthead ')][empty(*[contains(@class,' topic/stentry ')])]" priority="10"/>
  150. <xsl:template match="*[contains(@class, ' topic/simpletable ')]" name="topic.simpletable">
  151. <xsl:apply-templates select="*[contains(@class, ' ditaot-d/ditaval-startprop ')]" mode="out-of-line"/>
  152. <xsl:call-template name="spec-title"/>
  153. <table>
  154. <xsl:apply-templates select="." mode="table:common"/>
  155. <xsl:call-template name="dita2html:simpletable-cols"/>
  156. <xsl:apply-templates select="*[contains(@class, ' topic/sthead ')]"/>
  157. <xsl:apply-templates select="." mode="generate-table-header"/>
  158. <tbody>
  159. <xsl:apply-templates select="*[contains(@class, ' topic/strow ')]"/>
  160. </tbody>
  161. </table>
  162. <xsl:apply-templates select="*[contains(@class, ' ditaot-d/ditaval-endprop ')]" mode="out-of-line"/>
  163. </xsl:template>
  164. <xsl:template match="*[contains(@class, ' topic/simpletable ')]" mode="css-class">
  165. <xsl:apply-templates select="@frame, @expanse, @scale" mode="#current"/>
  166. </xsl:template>
  167. <xsl:template match="*[contains(@class, ' topic/strow ')]" name="topic.strow">
  168. <tr>
  169. <xsl:apply-templates select="." mode="table:common"/>
  170. <xsl:apply-templates/>
  171. </tr>
  172. </xsl:template>
  173. <xsl:template match="*[contains(@class, ' topic/sthead ')]" name="topic.sthead">
  174. <thead>
  175. <tr>
  176. <xsl:apply-templates select="." mode="table:common"/>
  177. <xsl:apply-templates/>
  178. </tr>
  179. </thead>
  180. </xsl:template>
  181. <xsl:template match="*[simpletable:is-head-entry(.)]">
  182. <th>
  183. <xsl:apply-templates select="." mode="simpletable:entry"/>
  184. </th>
  185. </xsl:template>
  186. <xsl:template match="*[simpletable:is-body-entry(.)][simpletable:is-keycol-entry(.)]">
  187. <th scope="row">
  188. <xsl:apply-templates select="." mode="simpletable:entry"/>
  189. </th>
  190. </xsl:template>
  191. <xsl:template match="*[simpletable:is-body-entry(.)][not(simpletable:is-keycol-entry(.))]" name="topic.stentry">
  192. <td>
  193. <xsl:apply-templates select="." mode="simpletable:entry"/>
  194. </td>
  195. </xsl:template>
  196. <xsl:template match="*[contains(@class, ' topic/stentry ')]" mode="simpletable:entry">
  197. <xsl:apply-templates select="." mode="table:common"/>
  198. <xsl:apply-templates select="." mode="headers"/>
  199. <xsl:choose>
  200. <xsl:when test="*|text()|processing-instruction()">
  201. <xsl:apply-templates/>
  202. </xsl:when>
  203. <xsl:when test="@specentry">
  204. <xsl:apply-templates select="@specentry"/>
  205. </xsl:when>
  206. </xsl:choose>
  207. </xsl:template>
  208. <xsl:template match="*[simpletable:is-head-entry(.)]" mode="headers">
  209. <xsl:attribute name="scope" select="'col'"/>
  210. </xsl:template>
  211. <xsl:template match="*[simpletable:is-body-entry(.)]" mode="headers">
  212. <xsl:if test="simpletable:is-keycol-entry(.)">
  213. <xsl:attribute name="scope" select="'row'"/>
  214. </xsl:if>
  215. </xsl:template>
  216. <xsl:template match="*[contains(@class, ' topic/simpletable ')]" mode="generate-table-header" priority="10">
  217. <xsl:variable name="gen" as="element(gen)">
  218. <!--
  219. Generated header needs to be wrapped in gen element to allow correct
  220. language detection.
  221. -->
  222. <gen>
  223. <xsl:copy-of select="ancestor-or-self::*[@xml:lang][1]/@xml:lang"/>
  224. <xsl:next-match/>
  225. </gen>
  226. </xsl:variable>
  227. <xsl:apply-templates select="$gen/*"/>
  228. </xsl:template>
  229. </xsl:stylesheet>