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