pages2normalise.xsl 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. <xsl:stylesheet version="1.0"
  2. xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  3. xmlns:sfa="http://developer.apple.com/namespaces/sfa"
  4. xmlns:sf="http://developer.apple.com/namespaces/sf"
  5. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  6. xmlns:appsl="http://developer.apple.com/namespaces/sl"
  7. xmlns:dbk='http://docbook.org/ns/docbook'
  8. xmlns:rnd='http://docbook.org/ns/docbook/roundtrip'
  9. exclude-result-prefixes='sfa sf xsi appsl'>
  10. <xsl:output method="xml" indent='yes'/>
  11. <!-- ********************************************************************
  12. $Id: pages2normalise.xsl 7637 2008-01-09 20:48:30Z balls $
  13. ********************************************************************
  14. This file is part of the XSL DocBook Stylesheet distribution.
  15. See ../README or http://nwalsh.com/docbook/xsl/ for copyright
  16. and other information.
  17. ******************************************************************** -->
  18. <xsl:strip-space elements='*'/>
  19. <xsl:preserve-space elements='sf:span'/>
  20. <xsl:key name='styles'
  21. match='sf:paragraphstyle[not(ancestor::appsl:section-prototypes)] |
  22. sf:characterstyle[not(ancestor::appsl:section-prototypes)] |
  23. sf:table-style'
  24. use='@sf:ident|@sfa:ID'/>
  25. <xsl:key name='ids'
  26. match='*'
  27. use='@sfa:ID'/>
  28. <xsl:template match='appsl:document'>
  29. <dbk:article>
  30. <!-- TODO: headers and footers -->
  31. <xsl:apply-templates select='sf:text-storage'/>
  32. </dbk:article>
  33. </xsl:template>
  34. <xsl:template match='sf:p'>
  35. <xsl:choose>
  36. <xsl:when test='sf:attachment-ref and
  37. count(*) = count(sf:attachment-ref|sf:br|sf:selection-start|sf:selection-end)'>
  38. <xsl:apply-templates/>
  39. </xsl:when>
  40. <xsl:otherwise>
  41. <dbk:para>
  42. <xsl:variable name='style-name'>
  43. <xsl:call-template name='rnd:find-style'/>
  44. </xsl:variable>
  45. <xsl:if test='$style-name != "" and
  46. $style-name != "para"'>
  47. <xsl:attribute name='rnd:style'>
  48. <xsl:value-of select='$style-name'/>
  49. </xsl:attribute>
  50. </xsl:if>
  51. <xsl:apply-templates/>
  52. </dbk:para>
  53. </xsl:otherwise>
  54. </xsl:choose>
  55. </xsl:template>
  56. <xsl:template match='sf:span'>
  57. <xsl:variable name='style-name'
  58. select='key("styles", @sf:style)/self::sf:characterstyle/@sf:name'/>
  59. <xsl:variable name='char-style'>
  60. <xsl:call-template name='rnd:find-style'>
  61. <xsl:with-param name='char-style-name' select='$style-name'/>
  62. </xsl:call-template>
  63. </xsl:variable>
  64. <xsl:choose>
  65. <xsl:when test='$style-name = "attribute-name"'>
  66. <xsl:if test='not(preceding-sibling::node()[not(self::text()) or (self::text() and normalize-space() != "")])'>
  67. <xsl:attribute name='{.}'>
  68. <xsl:apply-templates select='following-sibling::*[1][self::sf:span]'
  69. mode='attribute'/>
  70. </xsl:attribute>
  71. </xsl:if>
  72. </xsl:when>
  73. <xsl:when test='$style-name = "attribute-value"'/>
  74. <xsl:when test='$style-name = ""'>
  75. <xsl:apply-templates/>
  76. </xsl:when>
  77. <xsl:when test='$char-style = "superscript" or
  78. $char-style = "subscript"'>
  79. <xsl:element name='{$char-style}'
  80. namespace='http://docbook.org/ns/docbook'>
  81. <xsl:apply-templates/>
  82. </xsl:element>
  83. </xsl:when>
  84. <xsl:otherwise>
  85. <dbk:emphasis>
  86. <xsl:choose>
  87. <xsl:when test='$char-style = "emphasis-bold" or
  88. $char-style = "emphasis-strong"'>
  89. <xsl:attribute name='role'>bold</xsl:attribute>
  90. </xsl:when>
  91. <xsl:when test='$char-style != "" and
  92. $char-style != "emphasis"'>
  93. <xsl:attribute name='rnd:style'>
  94. <xsl:value-of select='$char-style'/>
  95. </xsl:attribute>
  96. </xsl:when>
  97. </xsl:choose>
  98. <xsl:apply-templates/>
  99. </dbk:emphasis>
  100. </xsl:otherwise>
  101. </xsl:choose>
  102. </xsl:template>
  103. <xsl:template match='*' mode='attribute'>
  104. <xsl:variable name='style-name'
  105. select='key("styles", @sf:style)/self::sf:characterstyle/@sf:name'/>
  106. <xsl:if test='$style-name = "attribute-value"'>
  107. <xsl:apply-templates/>
  108. </xsl:if>
  109. </xsl:template>
  110. <xsl:template match='sf:br'/>
  111. <xsl:template match='sf:lnbr|sf:crbr'>
  112. <xsl:text>&#xa;</xsl:text>
  113. </xsl:template>
  114. <xsl:template match='sf:tab'>
  115. <xsl:text> </xsl:text>
  116. </xsl:template>
  117. <xsl:template match='sf:link'>
  118. <dbk:ulink url='{@href}'>
  119. <xsl:apply-templates/>
  120. </dbk:ulink>
  121. </xsl:template>
  122. <xsl:template match='sf:attachment-ref'>
  123. <xsl:if test='@sf:kind = "tabular-attachment"'>
  124. <xsl:apply-templates select='key("ids", @sfa:IDREF)'/>
  125. </xsl:if>
  126. </xsl:template>
  127. <xsl:template match='sf:attachment[@sf:kind = "tabular-attachment"]'>
  128. <xsl:variable name='model'
  129. select='key("ids", sf:tabular-info/sf:tabular-model-ref/@sfa:IDREF)'/>
  130. <xsl:variable name='num-cols' select='$model/sf:grid/@sf:numcols'/>
  131. <xsl:variable name='num-rows' select='$model/sf:grid/@sf:numrows'/>
  132. <xsl:variable name='border.top'
  133. select='count($model/sf:grid/sf:horizontal-gridline-styles/*) = 0 or
  134. not($model/sf:grid/sf:horizontal-gridline-styles/sf:style-run[@sf:gridline-index = "0"])'/>
  135. <xsl:variable name='border.bottom'
  136. select='count($model/sf:grid/sf:horizontal-gridline-styles/*) = 0 or
  137. not($model/sf:grid/sf:horizontal-gridline-styles/sf:style-run[@sf:gridline-index = $num-rows - 1])'/>
  138. <xsl:variable name='border.left'
  139. select='count($model/sf:grid/sf:vertical-gridline-styles/*) = 0 or
  140. not($model/sf:grid/sf:vertical-gridline-styles/sf:style-run[@sf:gridline-index = "0"])'/>
  141. <xsl:variable name='border.right'
  142. select='count($model/sf:grid/sf:vertical-gridline-styles/*) = 0 or
  143. not($model/sf:grid/sf:vertical-gridline-styles/sf:style-run[@sf:gridline-index = $num-cols])'/>
  144. <xsl:choose>
  145. <xsl:when test='not($num-rows) or $num-rows = ""'>
  146. <xsl:message> cannot determine number of rows in table</xsl:message>
  147. <xsl:comment> cannot determine number of rows in table </xsl:comment>
  148. </xsl:when>
  149. <xsl:when test='not($num-cols) or $num-cols = ""'>
  150. <xsl:message> cannot determine number of columns in table</xsl:message>
  151. <xsl:comment> cannot determine number of columns in table </xsl:comment>
  152. </xsl:when>
  153. <xsl:otherwise>
  154. <dbk:informaltable>
  155. <xsl:choose>
  156. <xsl:when test='$border.top and $border.bottom and
  157. $border.left and $border.right'>
  158. <xsl:attribute name='frame'>all</xsl:attribute>
  159. </xsl:when>
  160. <xsl:when test='$border.top and $border.bottom'>
  161. <xsl:attribute name='frame'>topbot</xsl:attribute>
  162. </xsl:when>
  163. <xsl:when test='$border.left and $border.right'>
  164. <xsl:attribute name='frame'>sides</xsl:attribute>
  165. </xsl:when>
  166. <xsl:when test='$border.top'>
  167. <xsl:attribute name='frame'>top</xsl:attribute>
  168. </xsl:when>
  169. <xsl:when test='$border.bottom'>
  170. <xsl:attribute name='frame'>bottom</xsl:attribute>
  171. </xsl:when>
  172. </xsl:choose>
  173. <dbk:tgroup cols='{$num-cols}'>
  174. <xsl:apply-templates select='$model/sf:grid/sf:columns/sf:grid-column'
  175. mode='rnd:colspec'/>
  176. <xsl:if test='$model/@sf:num-header-rows != 0'>
  177. <dbk:thead>
  178. <xsl:call-template name='rnd:make-table-rows'>
  179. <xsl:with-param name='nodes'
  180. select='$model/sf:grid/sf:datasource/sf:text-cell[@sf:row &lt; $model/@sf:num-header-rows]'/>
  181. <xsl:with-param name='num-rows'
  182. select='$model/@sf:num-header-rows'/>
  183. </xsl:call-template>
  184. </dbk:thead>
  185. </xsl:if>
  186. <dbk:tbody>
  187. <xsl:call-template name='rnd:make-table-rows'>
  188. <xsl:with-param name='nodes'
  189. select='$model/sf:grid/sf:datasource/sf:text-cell[@sf:row >= $model/@sf:num-header-rows and
  190. @sf:row &lt; $num-rows - $model/@sf:num-footer-rows]'/>
  191. <xsl:with-param name='num-rows' select='$num-rows - $model/@sf:num-header-rows - $model/@sf:num-footer-rows'/>
  192. <xsl:with-param name='row' select='$model/@sf:num-header-rows'/>
  193. </xsl:call-template>
  194. </dbk:tbody>
  195. <xsl:if test='$model/@sf:num-footer-rows != 0'>
  196. <dbk:tfoot>
  197. <xsl:call-template name='rnd:make-table-rows'>
  198. <xsl:with-param name='nodes'
  199. select='$model/sf:grid/sf:datasource/sf:text-cell[@sf:row &gt;= $num-rows - $model/@sf:num-footer-rows]'/>
  200. <xsl:with-param name='num-rows'
  201. select='$model/@sf:num-footer-rows'/>
  202. <xsl:with-param name='row'
  203. select='$num-rows - $model/@sf:num-footer-rows'/>
  204. </xsl:call-template>
  205. </dbk:tfoot>
  206. </xsl:if>
  207. </dbk:tgroup>
  208. </dbk:informaltable>
  209. </xsl:otherwise>
  210. </xsl:choose>
  211. </xsl:template>
  212. <xsl:template match='sf:grid-column' mode='rnd:colspec'>
  213. <dbk:colspec colwidth='{@sf:width}'
  214. colname='column-{count(preceding-sibling::sf:grid-column) + 1}'/>
  215. </xsl:template>
  216. <xsl:template name='rnd:make-table-rows'>
  217. <xsl:param name='num-rows' select='0'/>
  218. <xsl:param name='nodes' select='/..'/>
  219. <xsl:param name='row' select='0'/>
  220. <xsl:choose>
  221. <xsl:when test='not($nodes) and $num-rows != 0'>
  222. <xsl:message>WARNING: insufficient table cells</xsl:message>
  223. <xsl:comment> WARNING: insufficient table cells (num-rows <xsl:value-of select='$num-rows'/>, row <xsl:value-of select='$row'/>) </xsl:comment>
  224. </xsl:when>
  225. <xsl:when test='$nodes and $num-rows = 0'>
  226. <xsl:message>WARNING: excess table cells</xsl:message>
  227. <xsl:comment> WARNING: excess table cells (num-rows <xsl:value-of select='$num-rows'/>, row <xsl:value-of select='$row'/>) </xsl:comment>
  228. </xsl:when>
  229. <xsl:when test='not($nodes)'/>
  230. <xsl:when test='$num-rows = 0'/>
  231. <xsl:otherwise>
  232. <dbk:row>
  233. <xsl:apply-templates select='$nodes[@sf:row = $row]'/>
  234. </dbk:row>
  235. <xsl:call-template name='rnd:make-table-rows'>
  236. <xsl:with-param name='num-rows'
  237. select='$num-rows - 1'/>
  238. <xsl:with-param name='row'
  239. select='$row + 1'/>
  240. <xsl:with-param name='nodes'
  241. select='$nodes[@sf:row != $row]'/>
  242. </xsl:call-template>
  243. </xsl:otherwise>
  244. </xsl:choose>
  245. </xsl:template>
  246. <xsl:template match='sf:text-cell'>
  247. <dbk:entry>
  248. <!-- Does this cell have no bottom border? -->
  249. <xsl:variable name='horiz'
  250. select='ancestor::sf:grid/sf:horizontal-gridline-styles'/>
  251. <xsl:if test='not($horiz/*) or
  252. not($horiz/sf:style-run[@sf:gridline-index = current()/@sf:row + 1]/sf:vector-style-ref[@sf:start-index &lt;= current()/@sf:col and @sf:stop-index >= current()/@sf:col])'>
  253. <xsl:attribute name='rowsep'>1</xsl:attribute>
  254. </xsl:if>
  255. <!-- Does this cell have no right border? -->
  256. <xsl:variable name='vert'
  257. select='ancestor::sf:grid/sf:vertical-gridline-styles'/>
  258. <xsl:if test='not($vert/*) or
  259. not($vert/sf:style-run[@sf:gridline-index = current()/@sf:col + 1]/sf:vector-style-ref[@sf:start-index &lt;= current()/@sf:row and @sf:stop-index >= current()/@sf:row])'>
  260. <xsl:attribute name='colsep'>1</xsl:attribute>
  261. </xsl:if>
  262. <xsl:choose>
  263. <xsl:when test='sf:cell-text/@sfa:string'>
  264. <dbk:para>
  265. <xsl:apply-templates select='sf:cell-text/@sfa:string'/>
  266. </dbk:para>
  267. </xsl:when>
  268. <xsl:otherwise>
  269. <xsl:apply-templates select='sf:cell-text/sf:cell-storage/sf:text-body/*'/>
  270. </xsl:otherwise>
  271. </xsl:choose>
  272. </dbk:entry>
  273. </xsl:template>
  274. <xsl:template match='sf:tableAttachmentTable |
  275. sf:tableModelCells'>
  276. <xsl:apply-templates/>
  277. </xsl:template>
  278. <xsl:template match='sf:tableModelPartitionSource |
  279. sf:tableModelStyle-ref |
  280. sf:tableModelVectors |
  281. sf:tableCellArrayCellsByColumn |
  282. sf:tableModelTableID'/>
  283. <xsl:template match='sf:text-storage |
  284. sf:text-body |
  285. sf:section |
  286. sf:layout'>
  287. <xsl:apply-templates/>
  288. </xsl:template>
  289. <xsl:template match='sf:stylesheet|sf:stylesheet-ref |
  290. sf:container-hint |
  291. sf:page-start|sf:br |
  292. sf:selection-start|sf:selection-end |
  293. sf:insertion-point |
  294. sf:ghost-text |
  295. sf:attachments'/>
  296. <xsl:template match='*'>
  297. <xsl:message>element "<xsl:value-of select='name()'/>" not handled</xsl:message>
  298. </xsl:template>
  299. <xsl:template name='rnd:find-style'>
  300. <xsl:param name='ident' select='@sf:style'/>
  301. <xsl:param name='para-style-name'
  302. select='key("styles", $ident)/self::sf:paragraphstyle/@sf:name'/>
  303. <xsl:param name='char-style-name'
  304. select='key("styles", $ident)/self::sf:characterstyle/@sf:name'/>
  305. <xsl:choose>
  306. <xsl:when test='$ident = "paragraph-style-default"'/>
  307. <xsl:when test='$para-style-name != ""'>
  308. <xsl:value-of select='$para-style-name'/>
  309. </xsl:when>
  310. <xsl:when test='key("styles", $ident)/self::sf:characterstyle/sf:property-map/sf:superscript/sf:number/@sfa:number = "1"'>superscript</xsl:when>
  311. <xsl:when test='key("styles", $ident)/self::sf:characterstyle/sf:property-map/sf:subscript/sf:number/@sfa:number = "1"'>subscript</xsl:when>
  312. <xsl:when test='$char-style-name != "" or
  313. key("styles", $ident)/self::sf:characterstyle/sf:property-map/*'>
  314. <xsl:value-of select='$char-style-name'/>
  315. </xsl:when>
  316. </xsl:choose>
  317. </xsl:template>
  318. </xsl:stylesheet>