1<?xml version="1.0" encoding="UTF-8"?>
2<!--***********************************************************
3 *
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements.  See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership.  The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License.  You may obtain a copy of the License at
11 *
12 *   http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied.  See the License for the
18 * specific language governing permissions and limitations
19 * under the License.
20 *
21 ***********************************************************-->
22
23
24<xsl:stylesheet version="1.0"
25	xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
26	xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0"
27	xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0"
28	xmlns:dc="http://purl.org/dc/elements/1.1/"
29	xmlns:dom="http://www.w3.org/2001/xml-events"
30	xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0"
31	xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0"
32	xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0"
33	xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0"
34	xmlns:math="http://www.w3.org/1998/Math/MathML"
35	xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0"
36	xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0"
37	xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0"
38	xmlns:ooo="http://openoffice.org/2004/office"
39	xmlns:oooc="http://openoffice.org/2004/calc"
40	xmlns:ooow="http://openoffice.org/2004/writer"
41	xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0"
42	xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0"
43	xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0"
44	xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0"
45	xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0"
46	xmlns:xlink="http://www.w3.org/1999/xlink"
47	xmlns:xt="http://www.jclark.com/xt"
48	xmlns:common="http://exslt.org/common"
49	xmlns:xalan="http://xml.apache.org/xalan"
50	xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:c="urn:schemas-microsoft-com:office:component:spreadsheet" xmlns:html="http://www.w3.org/TR/REC-html40" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:x2="http://schemas.microsoft.com/office/excel/2003/xml" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
51	exclude-result-prefixes="chart config dc dom dr3d draw fo form math meta number office ooo oooc ooow script style svg table text xlink xt common xalan">
52
53
54	<!-- ************** -->
55	<!-- *** Table  *** -->
56	<!-- ************** -->
57
58	<!-- check existence of default cell style -->
59	<xsl:variable name="firstDefaultCellStyle" select="descendant::table:table-column/@table:default-cell-style-name" />
60
61
62	<xsl:template match="table:table" name="table:table">
63		<xsl:element name="Table">
64			<xsl:apply-templates select="@table:style-name" />
65
66			<!-- find all columns in the table -->
67			<xsl:variable name="columnNodes" select="descendant::table:table-column" />
68			<!-- calculate the overall column amount -->
69			<xsl:variable name="maxColumnNo">
70				<xsl:choose>
71					<xsl:when test="$columnNodes/@table:number-columns-repeated">
72						<xsl:value-of select="count($columnNodes)
73											+ number(sum($columnNodes/@table:number-columns-repeated))
74											- count($columnNodes/@table:number-columns-repeated)" />
75					</xsl:when>
76					<xsl:otherwise>
77						<xsl:value-of select="count($columnNodes)"/>
78					</xsl:otherwise>
79				</xsl:choose>
80			</xsl:variable>
81			<!-- create columns -->
82			<xsl:apply-templates select="$columnNodes[1]">
83				<xsl:with-param name="columnNodes"  select="$columnNodes" />
84				<xsl:with-param name="maxColumnNo"  select="$maxColumnNo" />
85			</xsl:apply-templates>
86
87			<!-- create rows -->
88			<xsl:choose>
89				<xsl:when test="not($columnNodes/@table:number-columns-repeated)">
90					<xsl:call-template name="optimized-row-handling">
91						<xsl:with-param name="rowNodes"  		select="descendant::table:table-row" />
92						<xsl:with-param name="columnNodes"      select="$columnNodes" />
93					</xsl:call-template>
94				</xsl:when>
95				<xsl:otherwise>
96					<!-- To be able to match from a cell to the corresponding column to match @table:default-cell-style-name,
97						the repeated columns are being resolved by copying them in a helper variable -->
98					<xsl:variable name="columnNodes-RTF">
99						<xsl:for-each select="$columnNodes">
100							<xsl:call-template name="adding-column-styles-entries" />
101						</xsl:for-each>
102					</xsl:variable>
103					<xsl:choose>
104						<xsl:when test="function-available('xalan:nodeset')">
105							<xsl:call-template name="optimized-row-handling">
106								<xsl:with-param name="rowNodes"  		select="descendant::table:table-row" />
107								<xsl:with-param name="columnNodes"      select="xalan:nodeset($columnNodes-RTF)" />
108							</xsl:call-template>
109						</xsl:when>
110						<xsl:when test="function-available('common:node-set')">
111							<xsl:call-template name="optimized-row-handling">
112								<xsl:with-param name="rowNodes"  		select="descendant::table:table-row" />
113								<xsl:with-param name="columnNodes"      select="common:node-set($columnNodes-RTF)" />
114							</xsl:call-template>
115						</xsl:when>
116						<xsl:when test="function-available('xt:node-set')">
117							<xsl:call-template name="optimized-row-handling">
118								<xsl:with-param name="rowNodes"  		select="descendant::table:table-row" />
119								<xsl:with-param name="columnNodes"      select="xt:node-set($columnNodes-RTF)" />
120							</xsl:call-template>
121						</xsl:when>
122					</xsl:choose>
123				</xsl:otherwise>
124			</xsl:choose>
125		</xsl:element>
126	</xsl:template>
127
128
129	<!-- **************** -->
130	<!-- *** Columns  *** -->
131	<!-- **************** -->
132
133	<xsl:template match="table:table-column">
134		<xsl:param name="columnNodes"  />
135		<xsl:param name="currentColumnNumber" select="1" />
136		<xsl:param name="setIndex" select="false()" />
137		<xsl:param name="maxColumnNo" />
138
139		<xsl:element name="Column">
140			<xsl:if test="@table:visibility = 'collapse' or @table:visibility = 'filter'">
141				<xsl:attribute name="ss:Hidden">1</xsl:attribute>
142			</xsl:if>
143
144			<xsl:if test="@table:number-columns-repeated">
145				<xsl:attribute name="ss:Span">
146					<xsl:value-of select="@table:number-columns-repeated - 1" />
147				</xsl:attribute>
148			</xsl:if>
149
150		   <xsl:if test="$setIndex">
151				<xsl:attribute name="ss:Index">
152					<xsl:value-of select="$currentColumnNumber" />
153				</xsl:attribute>
154			</xsl:if>
155
156			<xsl:choose>
157				<xsl:when test="@style:use-optimal-column-width = 'true'">
158					<xsl:attribute name="ss:AutoFitWidth">1</xsl:attribute>
159				</xsl:when>
160				<xsl:otherwise>
161					<xsl:variable name="width" select="key('styles', @table:style-name)/style:table-column-properties/@style:column-width" />
162					<xsl:if test="$width">
163						<xsl:attribute name="ss:Width">
164							<!-- using the absolute width in point -->
165							<xsl:call-template name="convert2pt">
166								<xsl:with-param name="value" select="$width" />
167							</xsl:call-template>
168						</xsl:attribute>
169					</xsl:if>
170				</xsl:otherwise>
171			</xsl:choose>
172
173			<xsl:if test="@table:number-columns-repeated">
174				<xsl:attribute name="ss:Span">
175					<xsl:value-of select="@table:number-columns-repeated - 1" />
176				</xsl:attribute>
177			</xsl:if>
178		</xsl:element>
179
180		<xsl:variable name="columnNumber">
181			<xsl:choose>
182				<xsl:when test="@table:number-columns-repeated">
183					<xsl:value-of select="$currentColumnNumber + @table:number-columns-repeated"/>
184				</xsl:when>
185				<xsl:otherwise>
186					<xsl:value-of select="$currentColumnNumber"/>
187			   </xsl:otherwise>
188		   </xsl:choose>
189	   </xsl:variable>
190		<xsl:if test="$columnNumber &lt; $maxColumnNo">
191			<xsl:variable name="nextColumnNodes" select="$columnNodes[position() != 1]" />
192			<xsl:choose>
193				<xsl:when test="@table:number-columns-repeated">
194					<xsl:apply-templates select="$nextColumnNodes[1]">
195						<xsl:with-param name="columnNodes"   		select="$nextColumnNodes" />
196						<xsl:with-param name="currentColumnNumber"  select="$columnNumber" />
197						<xsl:with-param name="maxColumnNo"   		select="$maxColumnNo" />
198						<xsl:with-param name="setIndex"      		select="true()" />
199					</xsl:apply-templates>
200				</xsl:when>
201				<xsl:otherwise>
202					<xsl:apply-templates select="$nextColumnNodes[1]">
203						<xsl:with-param name="columnNodes"   		select="$nextColumnNodes" />
204						<xsl:with-param name="currentColumnNumber"  select="$columnNumber + 1" />
205						<xsl:with-param name="maxColumnNo"   		select="$maxColumnNo" />
206					</xsl:apply-templates>
207				</xsl:otherwise>
208			</xsl:choose>
209		</xsl:if>
210	</xsl:template>
211
212	<!-- current node is a table:table-column -->
213	<xsl:template name="adding-column-styles-entries">
214		<xsl:choose>
215			<xsl:when test="not(@table:number-columns-repeated and @table:number-columns-repeated > 1)">
216				<!-- writes an entry of a column in the columns-variable -->
217				<xsl:copy-of select="." />
218			</xsl:when>
219			<xsl:otherwise>
220				<!-- repeated colums will be written explicit several times in the variable-->
221				<xsl:call-template name="repeat-adding-table-column">
222					<xsl:with-param name="numberColumnsRepeated"  select="@table:number-columns-repeated" />
223				</xsl:call-template>
224			</xsl:otherwise>
225		</xsl:choose>
226	 </xsl:template>
227
228
229	<!-- current node is a table:table-column -->
230	<!-- dublicates column elements in case of column-repeated attribute  -->
231	<xsl:template name="repeat-adding-table-column">
232		<xsl:param name="table:table-column" />
233		<xsl:param name="numberColumnsRepeated" />
234
235		<xsl:choose>
236			<xsl:when test="$numberColumnsRepeated > 1">
237				<!-- writes an entry of a column in the columns-variable -->
238				<xsl:copy-of select="." />
239				<!-- repeat calling this method until all elements written out -->
240				<xsl:call-template name="repeat-adding-table-column">
241					<xsl:with-param name="numberColumnsRepeated"    select="$numberColumnsRepeated - 1" />
242				</xsl:call-template>
243			</xsl:when>
244			<xsl:otherwise>
245				<!-- writes an entry of a column in the columns-variable -->
246				<xsl:copy-of select="." />
247			</xsl:otherwise>
248		</xsl:choose>
249	</xsl:template>
250
251
252	<!-- ************* -->
253	<!-- *** Rows  *** -->
254	<!-- ************* -->
255
256
257	<!-- Recursions are much faster when the stack size is small 	-->
258	<xsl:template name="optimized-row-handling">
259		<xsl:param name="rowNodes" />
260		<xsl:param name="columnNodes"  />
261		<xsl:param name="offset" select="0"/>
262		<xsl:param name="threshold" select="10"/>
263
264		<xsl:variable name="rowCount" select="count($rowNodes)"/>
265		<xsl:choose>
266			<xsl:when test="$rowCount &lt;= $threshold">
267				<xsl:apply-templates select="$rowNodes[1]">
268					<xsl:with-param name="rowNodes" select="$rowNodes" />
269					<xsl:with-param name="offset" select="$offset" />
270					<xsl:with-param name="columnNodes" select="$columnNodes" />
271				</xsl:apply-templates>
272			</xsl:when>
273			<xsl:otherwise>
274				<xsl:variable name="rowCountHalf" select="floor($rowCount div 2)"/>
275				<xsl:variable name="rowNodesSetA" select="$rowNodes[position() &lt;= $rowCountHalf]"/>
276				<xsl:variable name="rowNodesSetB" select="$rowNodes[position() &gt; $rowCountHalf]"/>
277				<!-- to keep track of the rownumber, the repeteated rows have to kept into accounts -->
278				<xsl:variable name="rowsCreatedByRepetition">
279				<xsl:choose>
280					<xsl:when test="$rowNodesSetA/@table:number-rows-repeated">
281						<xsl:value-of select="number(sum($rowNodesSetA/@table:number-rows-repeated))
282											- count($rowNodesSetA/@table:number-rows-repeated)" />
283					</xsl:when>
284					<xsl:otherwise>0</xsl:otherwise>
285					</xsl:choose>
286				</xsl:variable>
287				<xsl:choose>
288					<xsl:when test="$rowCountHalf &gt; $threshold">
289						<xsl:call-template name="optimized-row-handling">
290							<xsl:with-param name="rowNodes" select="$rowNodesSetA"/>
291							<xsl:with-param name="offset" select="$offset" />
292							<xsl:with-param name="columnNodes" select="$columnNodes" />
293						</xsl:call-template>
294						<xsl:call-template name="optimized-row-handling">
295							<xsl:with-param name="rowNodes" select="$rowNodesSetB"/>
296							<xsl:with-param name="offset" select="$offset + $rowCountHalf + $rowsCreatedByRepetition" />
297							<xsl:with-param name="columnNodes" select="$columnNodes" />
298						</xsl:call-template>
299					</xsl:when>
300					<xsl:otherwise>
301						<xsl:apply-templates select="$rowNodesSetA[1]">
302							<xsl:with-param name="rowNodes" select="$rowNodesSetA"/>
303							<xsl:with-param name="offset" select="$offset" />
304							<xsl:with-param name="columnNodes" select="$columnNodes" />
305						</xsl:apply-templates>
306						<xsl:apply-templates select="$rowNodesSetB[1]">
307							<xsl:with-param name="rowNodes" select="$rowNodesSetB" />
308							<xsl:with-param name="offset" select="$offset + $rowCountHalf + $rowsCreatedByRepetition" />
309							<xsl:with-param name="columnNodes" select="$columnNodes" />
310						</xsl:apply-templates>
311					</xsl:otherwise>
312				</xsl:choose>
313			</xsl:otherwise>
314		</xsl:choose>
315	</xsl:template>
316
317	<!--
318		Rows as "table:table-row" might be grouped in
319		"table:table-header-rows" or "table:table-row-group"
320		This row-tree will be traversed providing each Row with it's
321		calculatedRowPosition and earlierRowNumber.
322		By this repeated empty rows might be neglected in the spreadsheetml output,
323		as the following row will notice the 'gap' and provide @ss:Index,
324		which results in filling up the gap by a row without style and content.
325
326		In Excel created rows by ss:Index are 'default' rows.
327	-->
328	<xsl:template match="table:table-row">
329		<xsl:param name="earlierRowNumber" select="0" />
330		<xsl:param name="offset" />
331		<xsl:param name="calculatedRowPosition" select="$offset + 1" />
332		<xsl:param name="rowNodes" />
333		<xsl:param name="columnNodes"  />
334
335		<xsl:choose>
336			<xsl:when test="@table:number-rows-repeated &gt; 1">
337				<xsl:call-template name="write-table-row">
338					<xsl:with-param name="earlierRowNumber"  select="$earlierRowNumber" />
339					<xsl:with-param name="calculatedRowPosition"  select="$calculatedRowPosition" />
340					<xsl:with-param name="columnNodes" select="$columnNodes" />
341				</xsl:call-template>
342				<xsl:if test="@table:number-rows-repeated &gt; 2 and (table:table-cell/@office:value-type or $firstDefaultCellStyle != '')">
343					<!-- In case a cell is being repeated, the cell will be created
344					in a variabel, which is as many times given out, as being repeated -->
345					<xsl:variable name="tableRow">
346						<xsl:call-template name="write-table-row">
347							<xsl:with-param name="columnNodes" select="$columnNodes" />
348						</xsl:call-template>
349					</xsl:variable>
350					<xsl:call-template name="optimized-row-repeating">
351						<xsl:with-param name="tableRow"     select="$tableRow" />
352						<xsl:with-param name="repetition"   select="@table:number-rows-repeated - 1" />
353						<xsl:with-param name="columnNodes" select="$columnNodes" />
354				   </xsl:call-template>
355			   </xsl:if>
356			</xsl:when>
357			<xsl:otherwise>
358				<xsl:call-template name="write-table-row">
359					<xsl:with-param name="earlierRowNumber"  select="$earlierRowNumber" />
360					<xsl:with-param name="calculatedRowPosition"  select="$calculatedRowPosition" />
361					<xsl:with-param name="columnNodes" select="$columnNodes" />
362				</xsl:call-template>
363			</xsl:otherwise>
364		</xsl:choose>
365
366		<xsl:variable name="nextRowNodes" select="$rowNodes[position()!=1]" />
367		<xsl:choose>
368			<xsl:when test="@table:number-rows-repeated &gt; 1">
369				<xsl:apply-templates select="$nextRowNodes[1]">
370					<xsl:with-param name="earlierRowNumber"  select="$calculatedRowPosition" />
371					<xsl:with-param name="calculatedRowPosition"  select="$calculatedRowPosition + @table:number-rows-repeated" />
372					<xsl:with-param name="rowNodes" select="$nextRowNodes" />
373					<xsl:with-param name="columnNodes" select="$columnNodes" />
374			   </xsl:apply-templates>
375			</xsl:when>
376			<xsl:otherwise>
377				<xsl:apply-templates select="$nextRowNodes[1]">
378					<xsl:with-param name="earlierRowNumber"  select="$calculatedRowPosition" />
379					<xsl:with-param name="calculatedRowPosition"  select="$calculatedRowPosition + 1" />
380					<xsl:with-param name="rowNodes" select="$nextRowNodes" />
381					<xsl:with-param name="columnNodes" select="$columnNodes" />
382				</xsl:apply-templates>
383			</xsl:otherwise>
384		</xsl:choose>
385	</xsl:template>
386
387	<xsl:template name="write-table-row">
388		<xsl:param name="earlierRowNumber" select="0" />
389		<xsl:param name="calculatedRowPosition" select="1" />
390		<xsl:param name="columnNodes"  />
391
392		<xsl:element name="Row">
393			<xsl:if test="@table:visibility = 'collapse' or @table:visibility = 'filter'">
394				<xsl:attribute name="ss:Hidden">1</xsl:attribute>
395			</xsl:if>
396			<xsl:if test="not($earlierRowNumber + 1 = $calculatedRowPosition)">
397				<xsl:attribute name="ss:Index"><xsl:value-of select="$calculatedRowPosition" /></xsl:attribute>
398			</xsl:if>
399
400			<!-- writing the style of the row -->
401			<xsl:apply-templates select="@table:style-name" mode="table-row" />
402
403			<xsl:variable name="rowProperties" select="key('styles', @table:style-name)/*" />
404			<xsl:if test="$rowProperties/@style:use-optimal-row-height = 'false'">
405				<!-- default is '1', therefore write only '0' -->
406				<xsl:attribute name="ss:AutoFitHeight">0</xsl:attribute>
407			</xsl:if>
408
409			<xsl:variable name="height" select="$rowProperties/@style:row-height" />
410			<xsl:if test="$height">
411				<xsl:attribute name="ss:Height">
412					<!-- using the absolute height in point -->
413					<xsl:call-template name="convert2pt">
414						<xsl:with-param name="value" select="$height" />
415					</xsl:call-template>
416				</xsl:attribute>
417			</xsl:if>
418			<xsl:apply-templates select="table:table-cell[1]">
419				<xsl:with-param name="calculatedRowPosition"  select="$calculatedRowPosition" />
420				<xsl:with-param name="cellNodes"  select="table:table-cell" />
421				<xsl:with-param name="columnNodes" select="$columnNodes" />
422			</xsl:apply-templates>
423		</xsl:element>
424	</xsl:template>
425
426
427	<!-- Recursions are much faster when the stack size is small 	-->
428	<xsl:template name="optimized-row-repeating">
429		<xsl:param name="tableRow" />
430		<xsl:param name="repetition" />
431		<!-- resource optimation: instead of '1' it will be '1000' and the column is not full -->
432		<xsl:param name="thresholdmax" select="512"/>
433		<xsl:param name="thresholdmin" select="256"/>
434
435		<xsl:choose>
436			<xsl:when test="$repetition &lt;= $thresholdmax">
437				<xsl:copy-of select="$tableRow" />
438				<xsl:if test="$repetition &lt;= $thresholdmin">
439					<xsl:call-template name="optimized-row-repeating">
440						<xsl:with-param name="repetition" select="$repetition - 1"/>
441						<xsl:with-param name="tableRow" select="$tableRow" />
442					</xsl:call-template>
443				</xsl:if>
444			</xsl:when>
445			<xsl:otherwise>
446				<xsl:if test="$repetition mod 2 = 1">
447					<xsl:copy-of select="$tableRow" />
448				</xsl:if>
449				<xsl:variable name="repetitionHalf" select="floor($repetition div 2)"/>
450				<xsl:call-template name="optimized-row-repeating">
451					<xsl:with-param name="repetition" select="$repetitionHalf"/>
452					<xsl:with-param name="tableRow" select="$tableRow" />
453				</xsl:call-template>
454				<xsl:call-template name="optimized-row-repeating">
455					<xsl:with-param name="repetition" select="$repetitionHalf"/>
456					<xsl:with-param name="tableRow" select="$tableRow" />
457				</xsl:call-template>
458			</xsl:otherwise>
459		</xsl:choose>
460	</xsl:template>
461
462
463
464	<!-- ************** -->
465	<!-- *** Cells  *** -->
466	<!-- ************** -->
467
468	<!-- Table cells are able to be repeated by attribute in StarOffice,
469		 but not in Excel. If more cells are repeated -->
470	<xsl:template name="table:table-cell" match="table:table-cell">
471		<xsl:param name="calculatedCellPosition" select="1" /><!-- the later table position of the current cell  -->
472		<xsl:param name="calculatedRowPosition" /><!-- the later table position of the current row  -->
473		<xsl:param name="setIndex" select="false()" /> <!-- if not '0' @ss:Index used for neglecting repeteated empty cells -->
474		<xsl:param name="repetition" select="@table:number-columns-repeated" /> <!-- used for explicit writen out cells -->
475		<xsl:param name="repetitionCellPosition" select="$calculatedCellPosition" /><!-- during repetition formula needs exact cell positioning -->
476		<xsl:param name="nextMatchedCellPosition"><!-- the later table position of the next cell  -->
477		<xsl:choose>
478			<xsl:when test="not(@table:number-columns-repeated) and not(@table:number-columns-spanned)">
479				<xsl:value-of select="$calculatedCellPosition + 1" />
480			</xsl:when>
481			<xsl:when test="not(@table:number-columns-spanned)">
482				<xsl:value-of select="$calculatedCellPosition + @table:number-columns-repeated" />
483			</xsl:when>
484			<xsl:when test="not(@table:number-columns-repeated)">
485				<xsl:value-of select="$calculatedCellPosition + @table:number-columns-spanned" />
486			</xsl:when>
487			<xsl:otherwise>
488				<xsl:value-of select="$calculatedCellPosition + @table:number-columns-spanned * @table:number-columns-repeated" />
489			</xsl:otherwise>
490		</xsl:choose>
491		</xsl:param>
492		<xsl:param name="cellNodes" /><!-- cells to be handled  -->
493		<xsl:param name="columnNodes" />
494
495		<xsl:choose>
496			<!-- in case a repetition took place -->
497			<xsl:when test="$repetition &gt; 0">
498				<xsl:choose>
499					<!-- In case of no cell content (text, subelements, attribute, except repeated style) the ss:Index could be used -->
500					<xsl:when test="not(text()) and not(*) and not(@*[name() != 'table:number-columns-repeated'])">
501						<xsl:choose>
502							<xsl:when test="count($cellNodes) = 1">
503								<xsl:call-template name="create-table-cell">
504									<xsl:with-param name="setIndex" select="true()" />
505									<xsl:with-param name="calculatedCellPosition" select="$nextMatchedCellPosition - 1" />
506									<xsl:with-param name="calculatedRowPosition"  select="$calculatedRowPosition" />
507									<xsl:with-param name="columnNodes"  		  select="$columnNodes" />
508								</xsl:call-template>
509							</xsl:when>
510							<xsl:otherwise>
511								<xsl:apply-templates select="$cellNodes[2]">
512									<xsl:with-param name="calculatedCellPosition" select="$nextMatchedCellPosition" />
513									<xsl:with-param name="calculatedRowPosition"  select="$calculatedRowPosition" />
514									<xsl:with-param name="setIndex" select="true()" />
515									<xsl:with-param name="cellNodes" select="$cellNodes[position() != 1]" />
516									<xsl:with-param name="columnNodes"  		  select="$columnNodes" />
517								</xsl:apply-templates>
518							</xsl:otherwise>
519						</xsl:choose>
520					</xsl:when>
521					<!-- Fastest cell repetition by creating cell once and copying, works not for
522							a) cells with formula (need of actual cell postition)
523							b) cells, which start with ss:Index (as ss:Index is not allowed to be repeated) -->
524					<xsl:when test="not(@table:formula) and not($setIndex)">
525						<!-- In case a non-empty cell is being repeated, the cell will be created
526							in a variabel, which is as many times given out, as being repeated -->
527						<xsl:variable name="tableCell">
528							<xsl:call-template name="create-table-cell">
529								<xsl:with-param name="setIndex" select="false()" /><!-- copied cells may not have indices -->
530								<xsl:with-param name="columnNodes" select="$columnNodes" />
531							</xsl:call-template>
532						</xsl:variable>
533						<xsl:call-template name="repeat-copy-table-cell">
534							<xsl:with-param name="tableCell"   select="$tableCell" />
535							<xsl:with-param name="repetition"  select="$repetition" />
536							<xsl:with-param name="columnNodes" select="$columnNodes" />
537					   </xsl:call-template>
538						<xsl:apply-templates select="$cellNodes[2]">
539							<xsl:with-param name="calculatedCellPosition" select="$nextMatchedCellPosition" />
540							<xsl:with-param name="calculatedRowPosition"  select="$calculatedRowPosition" />
541							<xsl:with-param name="cellNodes" select="$cellNodes[position() != 1]" />
542							<xsl:with-param name="columnNodes" select="$columnNodes" />
543						</xsl:apply-templates>
544					</xsl:when>
545					<!-- explicit writing (instead of copying) of cell for the cases mentioned above -->
546					<xsl:otherwise>
547						<xsl:call-template name="create-table-cell">
548							<xsl:with-param name="setIndex" select="$setIndex" /><!-- a possible Index will be created -->
549							<xsl:with-param name="calculatedCellPosition" select="$repetitionCellPosition" />
550							<xsl:with-param name="calculatedRowPosition" select="$calculatedRowPosition" />
551							<xsl:with-param name="columnNodes" select="$columnNodes" />
552						</xsl:call-template>
553						<xsl:choose>
554							<!-- as long there is a repetition (higher '1') stay on the same cell node  -->
555							<xsl:when test="$repetition &gt; 1">
556								<xsl:call-template name="table:table-cell">
557									<xsl:with-param name="calculatedCellPosition" select="$nextMatchedCellPosition" />
558									<xsl:with-param name="calculatedRowPosition" select="$calculatedRowPosition" />
559									<xsl:with-param name="repetitionCellPosition">
560										<xsl:choose>
561											<xsl:when test="@table:number-columns-spanned">
562												<xsl:value-of select="$repetitionCellPosition + @table:number-columns-spanned" />
563											</xsl:when>
564											<xsl:otherwise>
565												<xsl:value-of select="$repetitionCellPosition + 1"/>
566											</xsl:otherwise>
567										</xsl:choose>
568									</xsl:with-param>
569									<xsl:with-param name="nextMatchedCellPosition" select="$nextMatchedCellPosition" />
570									<xsl:with-param name="repetition" select="$repetition - 1" />
571									<xsl:with-param name="cellNodes" select="$cellNodes" />
572									<xsl:with-param name="columnNodes" select="$columnNodes" />
573								</xsl:call-template>
574							</xsl:when>
575							<xsl:otherwise>
576								<xsl:apply-templates select="$cellNodes[2]">
577									<xsl:with-param name="calculatedCellPosition" select="$nextMatchedCellPosition" />
578									<xsl:with-param name="calculatedRowPosition"  select="$calculatedRowPosition" />
579									<xsl:with-param name="cellNodes" select="$cellNodes[position() != 1]" />
580									<xsl:with-param name="columnNodes" select="$columnNodes" />
581								</xsl:apply-templates>
582							</xsl:otherwise>
583						</xsl:choose>
584					</xsl:otherwise>
585				</xsl:choose>
586			</xsl:when>
587			<xsl:otherwise>
588				<!-- in case no repetition took place -->
589				<xsl:choose>
590					<!-- neglect en empty cells by using ss:Index Attribut  -->
591					<xsl:when test="not(text()) and not(*) and not(@*)">
592						<xsl:choose>
593							<!-- if it is the last cell, write this cell -->
594							<xsl:when test="count($cellNodes) = 1">
595								<xsl:call-template name="create-table-cell">
596									<xsl:with-param name="setIndex" select="true()" />
597									<xsl:with-param name="calculatedCellPosition" select="$nextMatchedCellPosition - 1" />
598									<xsl:with-param name="calculatedRowPosition"  select="$calculatedRowPosition" />
599									<xsl:with-param name="columnNodes" select="$columnNodes" />
600								</xsl:call-template>
601							</xsl:when>
602							<xsl:otherwise>
603								<xsl:apply-templates select="$cellNodes[2]">
604									<xsl:with-param name="setIndex" select="true()" />
605									<xsl:with-param name="calculatedCellPosition" select="$nextMatchedCellPosition" />
606									<xsl:with-param name="calculatedRowPosition"  select="$calculatedRowPosition" />
607									<xsl:with-param name="cellNodes" select="$cellNodes[position() != 1]" />
608									<xsl:with-param name="columnNodes" select="$columnNodes" />
609								</xsl:apply-templates>
610							</xsl:otherwise>
611						</xsl:choose>
612					</xsl:when>
613					<xsl:otherwise>
614						<!-- create cell and use/unset the ss:Index -->
615						<xsl:call-template name="create-table-cell">
616							<xsl:with-param name="setIndex" select="$setIndex" />
617							<xsl:with-param name="calculatedCellPosition" select="$calculatedCellPosition" />
618							<xsl:with-param name="calculatedRowPosition"  select="$calculatedRowPosition" />
619							<xsl:with-param name="columnNodes" select="$columnNodes" />
620						</xsl:call-template>
621						<xsl:apply-templates select="$cellNodes[2]">
622							<xsl:with-param name="calculatedCellPosition" select="$nextMatchedCellPosition" />
623							<xsl:with-param name="calculatedRowPosition"  select="$calculatedRowPosition" />
624							<xsl:with-param name="cellNodes" select="$cellNodes[position() != 1]" />
625							<xsl:with-param name="columnNodes" select="$columnNodes" />
626						</xsl:apply-templates>
627					</xsl:otherwise>
628				</xsl:choose>
629			</xsl:otherwise>
630		</xsl:choose>
631	</xsl:template>
632
633	<!-- Copies the variable 'tableCell' to the output as often as 'repetition' -->
634	<xsl:template name="repeat-copy-table-cell">
635		<xsl:param name="tableCell" />
636		<xsl:param name="repetition" />
637
638		<xsl:if test="$repetition &gt; 0">
639			<xsl:copy-of select="$tableCell"/>
640			<xsl:call-template name="repeat-copy-table-cell">
641				<xsl:with-param name="tableCell"   select="$tableCell" />
642				<xsl:with-param name="repetition"  select="$repetition - 1" />
643			</xsl:call-template>
644		</xsl:if>
645	</xsl:template>
646
647	<xsl:template name="create-table-cell">
648		<xsl:param name="setIndex" select="false()" />
649		<xsl:param name="calculatedCellPosition" />
650		<xsl:param name="calculatedRowPosition" />
651		<xsl:param name="columnNodes"  />
652
653		<xsl:element name="Cell" namespace="urn:schemas-microsoft-com:office:spreadsheet">
654			<xsl:if test="$setIndex">
655				<xsl:attribute name="ss:Index">
656					<xsl:value-of select="$calculatedCellPosition"/>
657				</xsl:attribute>
658			</xsl:if>
659			<xsl:if test="@table:number-columns-spanned &gt; 1">
660				<xsl:attribute name="ss:MergeAcross">
661					<xsl:value-of select="@table:number-columns-spanned - 1" />
662				</xsl:attribute>
663			</xsl:if>
664			<xsl:if test="@table:number-rows-spanned &gt; 1">
665				<xsl:attribute name="ss:MergeDown">
666					<xsl:value-of select="@table:number-rows-spanned - 1" />
667				</xsl:attribute>
668			</xsl:if>
669			<xsl:variable name="link" select="descendant::text:a/@xlink:href" />
670			<xsl:if test="$link">
671				<xsl:attribute name="ss:HRef">
672					<xsl:value-of select="$link" />
673				</xsl:attribute>
674			</xsl:if>
675			<xsl:choose>
676				<xsl:when test="@table:style-name">
677					<xsl:apply-templates select="@table:style-name" />
678				</xsl:when>
679				<xsl:otherwise>
680					<xsl:if test="$firstDefaultCellStyle != ''">
681						<xsl:variable name="defaultCellStyle" select="$columnNodes/table:table-column[position() = $calculatedCellPosition]/@table:default-cell-style-name" />
682						<xsl:if test="$defaultCellStyle">
683							<xsl:if test="not($defaultCellStyle = 'Default')">
684									<xsl:attribute name="ss:StyleID"><xsl:value-of select="$defaultCellStyle"/></xsl:attribute>
685							</xsl:if>
686						</xsl:if>
687					</xsl:if>
688				</xsl:otherwise>
689			</xsl:choose>
690			<xsl:apply-templates select="@table:formula">
691				<xsl:with-param name="calculatedCellPosition" select="$calculatedCellPosition" />
692				<xsl:with-param name="calculatedRowPosition"  select="$calculatedRowPosition" />
693			</xsl:apply-templates>
694			<xsl:choose>
695				<xsl:when test="*">
696				<!-- in case it is not an empty cell
697
698				  As the sequence of comment and data is opposite in Excel and Calc no match work here, in both comments exist only once
699				  Possible Table Content of interest: text:h|text:p|text:list  -->
700					<xsl:if test="text:h | text:p | text:list">
701						<xsl:variable name="valueType">
702							<xsl:choose>
703								<xsl:when test="@office:value-type">
704									<xsl:value-of select="@office:value-type" />
705								</xsl:when>
706								<xsl:otherwise>string</xsl:otherwise>
707							</xsl:choose>
708						</xsl:variable>
709						<xsl:call-template name="ss:Data">
710							<xsl:with-param name="valueType" select="$valueType" />
711							<xsl:with-param name="cellStyleName" select="@table:style-name" />
712						</xsl:call-template>
713					</xsl:if>
714
715					<xsl:if test="office:annotation">
716						<xsl:element name="Comment">
717							<xsl:if test="office:annotation/@office:author">
718								<xsl:attribute name="ss:Author"><xsl:value-of select="office:annotation/@office:author" /></xsl:attribute>
719							</xsl:if>
720							<xsl:if test="office:annotation/@office:display = 'true'">
721								<xsl:attribute name="ss:ShowAlways">1</xsl:attribute>
722							</xsl:if>
723							<!-- ss:Data is oblicatory, but not the same as the ss:Cell ss:Data child, as it has no attributes  -->
724							<ss:Data xmlns="http://www.w3.org/TR/REC-html40">
725								<xsl:for-each select="office:annotation/text:p">
726									<xsl:choose>
727										<xsl:when test="*">
728											<!-- paragraph style have to be neglected due to Excel error,
729												which does not allow shadowing their HTML attributes -->
730											<xsl:for-each select="*">
731												<xsl:call-template name="style-and-contents" />
732											</xsl:for-each>
733										</xsl:when>
734										<xsl:when test="@text:style-name">
735											<xsl:call-template name="style-and-contents" />
736										</xsl:when>
737										<xsl:otherwise>
738											<!-- if no style is set, BOLD is set as default -->
739											<B>
740												<xsl:call-template name="style-and-contents" />
741											</B>
742										</xsl:otherwise>
743									</xsl:choose>
744								</xsl:for-each>
745							</ss:Data>
746						</xsl:element>
747					</xsl:if>
748				</xsl:when>
749			</xsl:choose>
750		</xsl:element>
751	</xsl:template>
752
753	<!-- comments are handled separately in the cell -->
754	<xsl:template match="office:annotation" />
755	<xsl:template match="dc:date" />
756
757	<xsl:template name="ss:Data">
758		<!-- the default value is 'String' in the office -->
759		<xsl:param name="valueType" select="'string'" />
760		<xsl:param name="cellStyleName" />
761
762		<xsl:choose>
763			<xsl:when test="descendant::*/@text:style-name">
764				<xsl:choose>
765					<xsl:when test="$valueType = 'string'">
766						<ss:Data ss:Type="String" xmlns="http://www.w3.org/TR/REC-html40">
767							<xsl:apply-templates>
768								<xsl:with-param name="cellStyleName" select="$cellStyleName" />
769							</xsl:apply-templates>
770						</ss:Data>
771					</xsl:when>
772					<xsl:when test="$valueType = 'boolean'">
773						<ss:Data ss:Type="Boolean" xmlns="http://www.w3.org/TR/REC-html40">
774							<xsl:apply-templates>
775								<xsl:with-param name="cellStyleName" select="$cellStyleName" />
776							</xsl:apply-templates>
777						</ss:Data>
778					</xsl:when>
779					<xsl:when test="$valueType = 'date'">
780						<ss:Data ss:Type="DateTime" xmlns="http://www.w3.org/TR/REC-html40">
781							<xsl:apply-templates>
782								<xsl:with-param name="cellStyleName" select="$cellStyleName" />
783							</xsl:apply-templates>
784						</ss:Data>
785					</xsl:when>
786					<!-- float, time, percentage, currency (no 'Error' setting) -->
787					<xsl:otherwise>
788						<ss:Data ss:Type="Number" xmlns="http://www.w3.org/TR/REC-html40">
789							<xsl:apply-templates>
790								<xsl:with-param name="cellStyleName" select="$cellStyleName" />
791							</xsl:apply-templates>
792						</ss:Data>
793					</xsl:otherwise>
794				</xsl:choose>
795			</xsl:when>
796			<xsl:otherwise>
797				<xsl:element name="Data">
798					<xsl:call-template name="ss:Type">
799						<xsl:with-param name="valueType" select="$valueType" />
800					</xsl:call-template>
801				</xsl:element>
802			</xsl:otherwise>
803		</xsl:choose>
804	</xsl:template>
805
806
807	<xsl:template name="ss:Type">
808		<xsl:param name="valueType" select="'string'" />
809
810		<xsl:choose>
811			<xsl:when test="$valueType = 'string'">
812				<xsl:attribute name="ss:Type">String</xsl:attribute>
813				<xsl:apply-templates select="*"/>
814			</xsl:when>
815			<xsl:when test="$valueType = 'boolean'">
816				<xsl:attribute name="ss:Type">Boolean</xsl:attribute>
817				<xsl:choose>
818					<xsl:when test="@office:boolean-value = 'true'">1</xsl:when>
819					<xsl:otherwise>0</xsl:otherwise>
820				</xsl:choose>
821			</xsl:when>
822			<xsl:when test="$valueType = 'date' or $valueType = 'time'">
823				<!-- issue in Excel: can not have an empty 'DateTime' cell -->
824				<xsl:attribute name="ss:Type">DateTime</xsl:attribute>
825				<!-- Gathering information of two StarOffice date/time attributes
826				Excel always needs both informations in one attribute -->
827				<xsl:choose>
828					<xsl:when test="@office:date-value">
829					<!-- office:date-value may contain time (after 'T')-->
830						<xsl:choose>
831							<xsl:when test="contains(@office:date-value, 'T')">
832								<!-- in case time is also part of the date -->
833								<xsl:value-of select="substring-before(@office:date-value, 'T')" />
834								<xsl:text>T</xsl:text>
835								<xsl:value-of select="substring-after(@office:date-value,'T')" />
836							   <xsl:if test="not(contains(@office:date-value,'.'))">
837									<xsl:text>.</xsl:text>
838								</xsl:if>
839								<xsl:text>000</xsl:text>
840							</xsl:when>
841							<xsl:when test="@office:time-value">
842							<!-- conatains date and time (time will be evaluated later -->
843								<xsl:value-of select="@office:date-value" />
844								<xsl:text>T</xsl:text>
845								<xsl:choose>
846									<xsl:when test="@table:formula or contains(@office:time-value,',')">
847										<!-- customized number types not implemented yet -->
848										<xsl:text>00:00:00.000</xsl:text>
849									</xsl:when>
850									<xsl:otherwise>
851										<xsl:value-of select="translate(substring-after(@office:time-value,'PT'),'HMS','::.')" />
852										<xsl:if test="not(contains(@office:time-value,'S'))">
853											<xsl:text>.</xsl:text>
854										</xsl:if>
855										<xsl:text>000</xsl:text>
856									</xsl:otherwise>
857								</xsl:choose>
858							</xsl:when>
859							<xsl:otherwise>
860								<xsl:value-of select="@office:date-value" />
861								<xsl:text>T00:00:00.000</xsl:text>
862							</xsl:otherwise>
863						</xsl:choose>
864					</xsl:when>
865					<xsl:otherwise>
866						<xsl:if test="@office:time-value">
867							<xsl:text>1899-12-31T</xsl:text>
868							<xsl:choose>
869								<xsl:when test="@table:formula or contains(@office:time-value,',')">
870									<!-- customized number types not implemented yet -->
871									<xsl:text>00:00:00.000</xsl:text>
872								</xsl:when>
873								<xsl:otherwise>
874									<xsl:value-of select="translate(substring-after(@office:time-value,'PT'),'HMS','::.')" />
875								   <xsl:if test="not(contains(@office:time-value,'S'))">
876										<xsl:text>.</xsl:text>
877									</xsl:if>
878									<xsl:text>000</xsl:text>
879								</xsl:otherwise>
880							</xsl:choose>
881						</xsl:if>
882					</xsl:otherwise>
883				</xsl:choose>
884			</xsl:when>
885			<!-- float, percentage, currency (no 'Error' setting) -->
886			<xsl:otherwise>
887				<xsl:attribute name="ss:Type">Number</xsl:attribute>
888				<xsl:value-of select="@office:value" />
889			</xsl:otherwise>
890		</xsl:choose>
891	</xsl:template>
892
893
894	<!-- ******************** -->
895	<!-- *** Common Rules *** -->
896	<!-- ******************** -->
897
898	<xsl:template match="*">
899		<xsl:param name="cellStyleName" />
900
901<!-- 	LineBreak in Cell -->
902		<xsl:if test="preceding-sibling::text:p[1]"><xsl:text>&#10;</xsl:text></xsl:if>
903		<xsl:call-template name="style-and-contents">
904			<xsl:with-param name="cellStyleName" select="$cellStyleName" />
905		</xsl:call-template>
906	</xsl:template>
907
908	<!-- disabling draw:frames -->
909	<xsl:template match="draw:frame" />
910
911	<xsl:template match="text:s">
912		<xsl:call-template name="write-breakable-whitespace">
913			<xsl:with-param name="whitespaces" select="@text:c" />
914		</xsl:call-template>
915	</xsl:template>
916
917	<!--write the number of 'whitespaces' -->
918	<xsl:template name="write-breakable-whitespace">
919		<xsl:param name="whitespaces" />
920
921		<xsl:text> </xsl:text>
922		<xsl:if test="$whitespaces >= 1">
923			<xsl:call-template name="write-breakable-whitespace">
924				<xsl:with-param name="whitespaces" select="$whitespaces - 1" />
925			</xsl:call-template>
926		</xsl:if>
927	</xsl:template>
928
929	<!-- allowing all matched text nodes -->
930	<xsl:template match="text()"><xsl:value-of select="." /></xsl:template>
931
932</xsl:stylesheet>
933
934