diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
commit | ed5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch) | |
tree | 7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /filter/source/xslt/odf2xhtml/export | |
parent | Initial commit. (diff) | |
download | libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.tar.xz libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.zip |
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'filter/source/xslt/odf2xhtml/export')
12 files changed, 6980 insertions, 0 deletions
diff --git a/filter/source/xslt/odf2xhtml/export/common/body.xsl b/filter/source/xslt/odf2xhtml/export/common/body.xsl new file mode 100644 index 000000000..bcad3abd9 --- /dev/null +++ b/filter/source/xslt/odf2xhtml/export/common/body.xsl @@ -0,0 +1,428 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + --> +<!-- + For further documentation and updates visit http://xml.openoffice.org/odf2xhtml +--> +<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:java="http://xml.apache.org/xslt/java" xmlns:urlencoder="http://www.jclark.com/xt/java/java.net.URLEncoder" exclude-result-prefixes="chart config dc dom dr3d draw fo form math meta number office ooo oooc ooow script style svg table text xforms xlink xsd xsi java urlencoder"> + + + <xsl:include href="table_of_content.xsl"/> + + + <!-- ****************** --> + <!-- *** Whitespace *** --> + <!-- ****************** --> + + <xsl:template match="text:s"> + <xsl:call-template name="write-breakable-whitespace"> + <xsl:with-param name="whitespaces" select="@text:c"/> + </xsl:call-template> + </xsl:template> + + + <!--write the number of 'whitespaces' --> + <xsl:template name="write-breakable-whitespace"> + <xsl:param name="whitespaces"/> + + <!--write two space chars as the normal white space character will be stripped + and the other is able to break --> + <xsl:text> </xsl:text> + <xsl:if test="$whitespaces >= 2"> + <xsl:call-template name="write-breakable-whitespace-2"> + <xsl:with-param name="whitespaces" select="$whitespaces - 1"/> + </xsl:call-template> + </xsl:if> + </xsl:template> + + + <!--write the number of 'whitespaces' --> + <xsl:template name="write-breakable-whitespace-2"> + <xsl:param name="whitespaces"/> + <!--write two space chars as the normal white space character will be stripped + and the other is able to break --> + <xsl:text> </xsl:text> + <xsl:if test="$whitespaces >= 2"> + <xsl:call-template name="write-breakable-whitespace"> + <xsl:with-param name="whitespaces" select="$whitespaces - 1"/> + </xsl:call-template> + </xsl:if> + </xsl:template> + + <!-- currentSolution: 8 non-breakable-spaces instead of a TAB is an approximation. + Sometimes less spaces than 8 might be needed and the output might be more difficult to read--> + <xsl:template match="text:tab"> + <xsl:param name="globalData"/> + + <xsl:call-template name="write-breakable-whitespace"> + <xsl:with-param name="whitespaces" select="8"/> + </xsl:call-template> + </xsl:template> + + + + <!-- *************** --> + <!-- *** Textbox *** --> + <!-- *************** --> + + <!-- ID / NAME of text-box --> + <xsl:template match="@draw:name"> + <xsl:attribute name="id"> + <xsl:choose> + <xsl:when test="number(substring(.,1,1))"> + <!-- Heuristic: If the first character is a number a 'a_' will be set + as prefix, as id have to be of type NMTOKEN --> + <xsl:value-of select="concat('a_',translate(., '
&<>.,;: %()[]/\+', '___________________________'))"/> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="translate(., '
&<>.,;: %()[]/\+', '___________________________')"/> + </xsl:otherwise> + </xsl:choose> + </xsl:attribute> + </xsl:template> + + + <xsl:template match="text:line-break"> + <xsl:param name="listIndent"/> + + <xsl:element namespace="{$namespace}" name="br"/> + + <!-- line breaks in lists need an indent similar to the list label --> + <xsl:if test="$listIndent"> + <xsl:element namespace="{$namespace}" name="span"> + <!-- some locales use , instead of . so replace it --> + <xsl:attribute name="style">margin-left:<xsl:value-of select="translate($listIndent, ',', '.')"/>cm</xsl:attribute> + </xsl:element> + </xsl:if> + </xsl:template> + + + <!-- currently there have to be an explicit call of the style attribute nodes, maybe the attributes nodes have no priority only order relevant--> + <xsl:template name="apply-styles-and-content"> + <xsl:param name="globalData"/> + <xsl:param name="footnotePrefix" /> + <xsl:apply-templates select="@*"> + <xsl:with-param name="globalData" select="$globalData"/> + </xsl:apply-templates> + <!-- the footnote symbol is the prefix for a footnote in the footer --> + <xsl:copy-of select="$footnotePrefix"/> + <xsl:apply-templates select="node()"> + <xsl:with-param name="globalData" select="$globalData"/> + </xsl:apply-templates> + </xsl:template> + + + <!-- ******************* --> + <!-- *** References *** --> + <!-- ******************* --> + + <xsl:template match="text:reference-ref | text:sequence-ref | text:bookmark-ref"> + <xsl:param name="globalData"/> + <xsl:if test="*|text()"> + <xsl:element namespace="{$namespace}" name="a"> + <xsl:attribute name="href"> + <xsl:text>#</xsl:text> + <xsl:choose> + <xsl:when test="number(substring(@text:ref-name,1,1))"> + <!-- Heuristic: If the first character is a number a 'a_' will be set + as prefix, as id have to be of type NMTOKEN --> + <xsl:value-of select="concat('a_',translate(@text:ref-name, '
&<>.,;: %()[]/\+', '___________________________'))"/> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="translate(@text:ref-name, '
&<>.,;: %()[]/\+', '___________________________')"/> + </xsl:otherwise> + </xsl:choose> + </xsl:attribute> + + <xsl:apply-templates select="@* | node()"> + <xsl:with-param name="globalData" select="$globalData"/> + </xsl:apply-templates> + + </xsl:element> + </xsl:if> + </xsl:template> + + <xsl:template match="@text:name"> + <xsl:attribute name="id"> + <xsl:choose> + <xsl:when test="number(substring(.,1,1))"> + <!-- Heuristic: If the first character is a number a 'a_' will be set + as prefix, as id have to be of type NMTOKEN --> + <xsl:value-of select="concat('a_',translate(., '
&<>.,;: %()[]/\+', '___________________________'))"/> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="translate(., '
&<>.,;: %()[]/\+', '___________________________')"/> + </xsl:otherwise> + </xsl:choose> + </xsl:attribute> + </xsl:template> + + <xsl:template match="text:sequence"> + <xsl:param name="globalData"/> + + <xsl:element namespace="{$namespace}" name="a"> + <xsl:apply-templates select="@*" /> + <xsl:attribute name="id"> + <xsl:choose> + <xsl:when test="number(substring(@text:ref-name,1,1))"> + <!-- Heuristic: If the first character is a number a 'a_' will be set + as prefix, as id have to be of type NMTOKEN --> + <xsl:value-of select="concat('a_',translate(@text:ref-name, '
&<>.,;: %()[]/\+', '___________________________'))"/> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="translate(@text:ref-name, '
&<>.,;: %()[]/\+', '___________________________')"/> + </xsl:otherwise> + </xsl:choose> + </xsl:attribute> + </xsl:element> + + <xsl:apply-templates> + <xsl:with-param name="globalData" select="$globalData"/> + </xsl:apply-templates> + </xsl:template> + + <xsl:template match="text:reference-mark"> + <xsl:param name="globalData"/> + + <xsl:element namespace="{$namespace}" name="a"> + <xsl:apply-templates select="@*" /> + <xsl:attribute name="id"> + <xsl:choose> + <xsl:when test="number(substring(@text:name,1,1))"> + <!-- Heuristic: If the first character is a number a 'a_' will be set + as prefix, as id have to be of type NMTOKEN --> + <xsl:value-of select="concat('a_',translate(@text:name, '
&<>.,;: %()[]/\+', '___________________________'))"/> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="translate(@text:name, '
&<>.,;: %()[]/\+', '___________________________')"/> + </xsl:otherwise> + </xsl:choose> + </xsl:attribute> + </xsl:element> + + <xsl:apply-templates> + <xsl:with-param name="globalData" select="$globalData"/> + </xsl:apply-templates> + </xsl:template> + + + <xsl:template match="text:reference-mark-start"> + <xsl:param name="globalData"/> + + <xsl:element namespace="{$namespace}" name="a"> + <xsl:apply-templates select="@*" /> + </xsl:element> + </xsl:template> + + <xsl:template match="text:bibliography-mark"> + <xsl:param name="globalData"/> + + <xsl:element namespace="{$namespace}" name="a"> + <xsl:apply-templates select="@* | node()"> + <xsl:with-param name="globalData" select="$globalData"/> + </xsl:apply-templates> + </xsl:element> + </xsl:template> + + <!-- @text:title exist only in text:bibliography-mark --> + <xsl:template match="@text:title"> + <xsl:attribute name="title"> + <xsl:value-of select="."/> + </xsl:attribute> + </xsl:template> + + <!-- @text:url exist only in text:bibliography-mark --> + <xsl:template match="@text:url"> + <xsl:attribute name="href"> + <xsl:value-of select="."/> + </xsl:attribute> + </xsl:template> + + <xsl:template match="text:user-defined"> + <xsl:apply-templates/> + </xsl:template> + + <xsl:template match="office:annotation"> + <xsl:element name="span"> + <xsl:attribute name="title">annotation</xsl:attribute> + <xsl:attribute name="class">annotation_style_by_filter</xsl:attribute> + <xsl:apply-templates select="@*" /> + <br/> + <xsl:text>[ANNOTATION:</xsl:text> + <br/> + <xsl:apply-templates select="*" mode="annotation"/> + <xsl:text>]</xsl:text> + </xsl:element> + </xsl:template> + + <xsl:template match="text:p" mode="annotation"> + <br/> + <xsl:element name="span"> + <xsl:text>NOTE: '</xsl:text> + <xsl:apply-templates /> + <xsl:text>'</xsl:text> + </xsl:element> + </xsl:template> + + <xsl:template match="dc:creator" mode="annotation"> + <br/> + <xsl:element name="span"> + <xsl:attribute name="title">dc:creator</xsl:attribute> + <xsl:text>BY '</xsl:text> + <xsl:apply-templates /> + <xsl:text>'</xsl:text> + </xsl:element> + </xsl:template> + + <xsl:template match="dc:date" mode="annotation"> + <br/> + <xsl:element name="span"> + <xsl:attribute name="title">dc:date</xsl:attribute> + <xsl:text>ON '</xsl:text> + <xsl:apply-templates /> + <xsl:text>'</xsl:text> + </xsl:element> + </xsl:template> + + <xsl:template match="meta:date-string" mode="annotation"> + <br/> + <xsl:element name="span"> + <xsl:attribute name="title">meta-date-string</xsl:attribute> + <xsl:text>META DATE '</xsl:text> + <xsl:apply-templates /> + <xsl:text>'</xsl:text> + </xsl:element> + </xsl:template> + + + <!-- *************** --> + <!-- *** HELPER *** --> + <!-- *************** --> + + + <xsl:template name="create-href"> + <xsl:param name="href"/> + <xsl:param name="mimetype"/> + + <xsl:choose> + <!-- internal OOo URL used in content tables --> + <xsl:when test="contains($href, '%7Coutline') or contains($href, '|outline')"> + <!-- the simplest workaround for content tables in a single document is to create an anchor from every heading element. + Downside: multiple identical headings won't refer always to the first. + --> + <xsl:text>#</xsl:text> + <xsl:variable name="title"> + <xsl:apply-templates mode="concatenate"/> + </xsl:variable> + + <xsl:value-of select="concat('a_', translate(normalize-space($title), '.,;: %()[]/\+', '_____________'))"/> + </xsl:when> + <xsl:when test="self::draw:image[office:binary-data]"> + <xsl:choose> + <xsl:when test="$mimetype"> + <xsl:text>data:</xsl:text><xsl:value-of select="$mimetype"/><xsl:text>;base64,</xsl:text><xsl:value-of select="office:binary-data"/> + </xsl:when> + <xsl:otherwise> + <xsl:text>data:image/*;base64,</xsl:text><xsl:value-of select="office:binary-data"/> + </xsl:otherwise> + </xsl:choose> + </xsl:when> + <xsl:otherwise> + <xsl:choose> + <!-- in case of packed open office document --> + <xsl:when test="starts-with($sourceBaseURL, 'jar:') or $isPackageFormat"> + <xsl:choose> + <!-- for images relative to open office document --> + <xsl:when test="starts-with($href, '../')"> + <!-- creating an absolute http URL to the packed image file (removing the '.')--> + <xsl:value-of select="concat(substring-after(substring-before($sourceBaseURL, '!'), 'jar:'), '/', $href, $optionalURLSuffix)"/> + </xsl:when> + <!-- for absolute URLs & absolute paths --> + <xsl:when test="contains($href, ':') or starts-with($href, '/')"> + <xsl:value-of select="concat($href, $optionalURLSuffix)"/> + </xsl:when> + <!-- for images jared in open office document --> + <xsl:otherwise> + <xsl:value-of select="concat($sourceBaseURL, $href, $optionalURLSuffix)"/> + </xsl:otherwise> + </xsl:choose> + </xsl:when> + <xsl:otherwise> + <xsl:choose> + <!-- for absolute URLs & Paths --> + <xsl:when test="contains($href, ':') or starts-with($href, '/')"> + <xsl:value-of select="concat($href, $optionalURLSuffix)"/> + </xsl:when> + <!-- for relative URLs --> + <xsl:when test="starts-with($href, '#')"> + <!-- intra document ref --> + <xsl:value-of select="$href"/> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="concat($sourceBaseURL, $href, $optionalURLSuffix)"/> + </xsl:otherwise> + </xsl:choose> + </xsl:otherwise> + </xsl:choose> + </xsl:otherwise> + </xsl:choose> + + </xsl:template> + + <xsl:template match="text()" mode="concatenate"> + <xsl:value-of select="."/> + </xsl:template> + <xsl:template match="*" mode="concatenate"> + <xsl:apply-templates mode="concatenate"/> + </xsl:template> + + + <!-- ******************** --> + <!-- *** Common Rules *** --> + <!-- ******************** --> + + <!-- ignore / neglect the following elements --> + <xsl:template match="draw:custom-shape | draw:g | office:forms | text:alphabetical-index-mark | text:alphabetical-index-mark-end | text:alphabetical-index-mark-start | text:bibliography-source | text:number | text:reference-mark-end | text:sequence-decls | text:soft-page-break | text:table-of-content-source | text:tracked-changes | text:user-field-decls"/> + + <!-- default template used by purpose--> + <xsl:template match="text:bibliography | text:change-end | text:change-start"> + <xsl:param name="globalData"/> + + <xsl:apply-templates> + <xsl:with-param name="globalData" select="$globalData"/> + </xsl:apply-templates> + </xsl:template> + + <!-- default template for not recognized elements --> + <xsl:template match="*"> + <xsl:param name="globalData"/> + <xsl:message>Using default element rule for ODF element '<xsl:value-of select="name()"/>'.</xsl:message> + + <xsl:apply-templates> + <xsl:with-param name="globalData" select="$globalData"/> + </xsl:apply-templates> + </xsl:template> + + <xsl:template match="@*"/> + + <!-- allowing all matched text nodes --> + <xsl:template match="text()"> + <xsl:value-of select="."/> + </xsl:template> + +</xsl:stylesheet> diff --git a/filter/source/xslt/odf2xhtml/export/common/styles/style_collector.xsl b/filter/source/xslt/odf2xhtml/export/common/styles/style_collector.xsl new file mode 100644 index 000000000..bac0c5963 --- /dev/null +++ b/filter/source/xslt/odf2xhtml/export/common/styles/style_collector.xsl @@ -0,0 +1,832 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . +--> +<!-- + For further documentation and updates visit http://xml.openoffice.org/odf2xhtml +--> +<xsl:stylesheet version="1.0" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" + xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:dom="http://www.w3.org/2001/xml-events" + xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" + xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" + xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" + xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" + xmlns:math="http://www.w3.org/1998/Math/MathML" + xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" + xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" + xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" + xmlns:ooo="http://openoffice.org/2004/office" + xmlns:oooc="http://openoffice.org/2004/calc" + xmlns:ooow="http://openoffice.org/2004/writer" + xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" + xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" + xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" + xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" + xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" + xmlns:xforms="http://www.w3.org/2002/xforms" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xt="http://www.jclark.com/xt" + xmlns:common="http://exslt.org/common" + xmlns:xalan="http://xml.apache.org/xalan" + exclude-result-prefixes="chart config dc dom dr3d draw fo form math meta number office ooo oooc ooow script style svg table text xforms xlink xsd xsi xt common xalan"> + + + + <!-- ***************************************** --> + <!-- *** Gathering office style properties *** --> + <!-- ***************************************** --> + + <!-- REASON FOR STYLESHEET: + In the OpenOffice documents styles are represented by a hierarchy. + (e.g. most styles are inherited from a default style). + Many other languages (as XHTML/CSS) do not support inherited styles. + The style inheritance have to be made flat/absolute for each style. + + A further reason was, that the earlier style collection mechanism + had problems with CSS inline, which do not inherit from XML office defaults + nor font:family defaults as the style header does + (cp. stylesheet 'style_collector.xsl' and the 'write-default-styles' template) + + RESULT OF STYLESHEET: + All styles will be returned in a variable containing styles with their inherited *: + + <all-styles> + <style style:family="foo" style:name="x1"> + <* fo:padding-left="0cm" fo:margin-right="0cm" /> + </style> + <style style:family="muh" style:name="x2" > + <* fo:padding-left="3cm" ... /> + </style> + ... + + </all-styles> + --> + + + <xsl:template name="collect-global-odf-properties"> + <!-- to access the variable as a node-set by XPATH expressions, it is necessary to convert it + from a result-tree-fragment (RTF) to a node set by a in a XSLT 1.0 non standardized function --> + <xsl:variable name="globalDataRTF"> + <xsl:call-template name="collect-document-links-RTF" /> + </xsl:variable> + + <xsl:choose> + <xsl:when test="function-available('common:node-set')"> + <xsl:call-template name="collect-style-properties"> + <xsl:with-param name="globalData" select="common:node-set($globalDataRTF)" /> + </xsl:call-template> + </xsl:when> + <xsl:when test="function-available('xalan:nodeset')"> + <xsl:call-template name="collect-style-properties"> + <xsl:with-param name="globalData" select="xalan:nodeset($globalDataRTF)" /> + </xsl:call-template> + </xsl:when> + <xsl:when test="function-available('xt:node-set')"> + <xsl:call-template name="collect-style-properties"> + <xsl:with-param name="globalData" select="xt:node-set($globalDataRTF)" /> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:message terminate="yes">The required node-set function was not found!</xsl:message> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + + + <xsl:template name="collect-style-properties"> + <xsl:param name="globalData" /> + + <!-- Add the input file references to the new collected style properties --> + <xsl:variable name="globalDataRTF"> + <xsl:copy-of select="$globalData" /> + <xsl:call-template name="collect-style-properties-RTF"> + <xsl:with-param name="globalData" select="$globalData" /> + </xsl:call-template> + </xsl:variable> + + <xsl:choose> + <xsl:when test="function-available('common:node-set')"> + <xsl:call-template name="map-odf-style-properties"> + <xsl:with-param name="globalData" select="common:node-set($globalDataRTF)" /> + </xsl:call-template> + </xsl:when> + <xsl:when test="function-available('xalan:nodeset')"> + <xsl:call-template name="map-odf-style-properties"> + <xsl:with-param name="globalData" select="xalan:nodeset($globalDataRTF)" /> + </xsl:call-template> + </xsl:when> + <xsl:when test="function-available('xt:node-set')"> + <xsl:call-template name="map-odf-style-properties"> + <xsl:with-param name="globalData" select="xt:node-set($globalDataRTF)" /> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:message terminate="yes">The required node-set function was not found!</xsl:message> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + + <xsl:template name="collect-document-links-RTF"> + <!-- works for zipped office files, unzipped office files as for flat filter single office file format as well --> + <xsl:variable name="documentLinksRTF"> + <xsl:choose> + <xsl:when test="office:document-content"> + <xsl:element name="styles-file" namespace=""> + <xsl:copy-of select="document(concat($sourceBaseURL, 'styles.xml'), .)" /> + </xsl:element> + <xsl:element name="meta-file" namespace=""> + <xsl:copy-of select="document(concat($sourceBaseURL, 'meta.xml'), .)" /> + </xsl:element> + </xsl:when> + <xsl:otherwise> + <xsl:element name="styles-file" namespace=""> + <xsl:copy-of select="/" /> + </xsl:element> + <xsl:element name="meta-file" namespace=""> + <xsl:copy-of select="/" /> + </xsl:element> + </xsl:otherwise> + </xsl:choose> + </xsl:variable> + + <xsl:choose> + <xsl:when test="function-available('common:node-set')"> + <xsl:call-template name="collect-document-links"> + <xsl:with-param name="documentLinks" select="common:node-set($documentLinksRTF)" /> + </xsl:call-template> + </xsl:when> + <xsl:when test="function-available('xalan:nodeset')"> + <xsl:call-template name="collect-document-links"> + <xsl:with-param name="documentLinks" select="xalan:nodeset($documentLinksRTF)" /> + </xsl:call-template> + </xsl:when> + <xsl:when test="function-available('xt:node-set')"> + <xsl:call-template name="collect-document-links"> + <xsl:with-param name="documentLinks" select="xt:node-set($documentLinksRTF)" /> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:message terminate="yes">The required node-set function was not found!</xsl:message> + </xsl:otherwise> + </xsl:choose> + + </xsl:template> + + + <xsl:template name="collect-document-links"> + <xsl:param name="documentLinks" /> + + <xsl:element name="styles-file" namespace=""> + <xsl:copy-of select="$documentLinks/styles-file/*" /> + </xsl:element> + + <xsl:element name="meta-file" namespace=""> + <xsl:copy-of select="$documentLinks/meta-file/*" /> + </xsl:element> + + <xsl:copy-of select="$documentLinks/styles-file/*/office:styles" /> + <xsl:copy-of select="$documentLinks/styles-file/*/office:font-face-decls" /> + + <!-- office:automatic-styles may be contained in two files (i.e. content.xml and styles.xml). + Wild card necessary as top level element differs from flat office files ("SampleName.fsxw") --> + <xsl:copy-of select="/*/office:automatic-styles" /> + + </xsl:template> + + + <xsl:template name="collect-style-properties-RTF"> + <xsl:param name="globalData" /> + + <!--** DEFAULT STYLES: First adding some office defaults unwritten in XML --> + <xsl:variable name="defaultOfficeStyle-RTF"> + <xsl:element name="style" namespace=""> + <xsl:element name="style:properties" /> + </xsl:element> + </xsl:variable> + + <xsl:choose> + <xsl:when test="function-available('common:node-set')"> + <xsl:call-template name="collect-properties-defaults"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="defaultOfficeStyle" select="common:node-set($defaultOfficeStyle-RTF)" /> + </xsl:call-template> + </xsl:when> + <xsl:when test="function-available('xalan:nodeset')"> + <xsl:call-template name="collect-properties-defaults"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="defaultOfficeStyle" select="xalan:nodeset($defaultOfficeStyle-RTF)" /> + </xsl:call-template> + </xsl:when> + <xsl:when test="function-available('xt:node-set')"> + <xsl:call-template name="collect-properties-defaults"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="defaultOfficeStyle" select="xt:node-set($defaultOfficeStyle-RTF)" /> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:message terminate="yes">ERROR: Function not found: 'Nodeset'</xsl:message> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + + <xsl:template name="collect-properties-defaults"> + <xsl:param name="globalData" /> + <xsl:param name="defaultOfficeStyle" /> + + <!--** DEFAULT STYLES: Adding the default styles of a style:family, by adding each office:styles/style:default-style element **--> + <xsl:variable name="defaultFamilyStyles-RTF"> + <xsl:for-each select="$globalData/office:styles/style:default-style"> + <xsl:element name="style" namespace=""> + <xsl:copy-of select="@style:family" /> + <xsl:call-template name="create-inherited-style-properties"> + <xsl:with-param name="inheritedStyleProperties" select="$defaultOfficeStyle/style/*" /> + </xsl:call-template> + </xsl:element> + </xsl:for-each> + </xsl:variable> + + <xsl:choose> + <xsl:when test="function-available('common:node-set')"> + <xsl:call-template name="collect-properties"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="defaultOfficeStyle" select="$defaultOfficeStyle" /> + <xsl:with-param name="defaultFamilyStyles" select="common:node-set($defaultFamilyStyles-RTF)" /> + </xsl:call-template> + </xsl:when> + <xsl:when test="function-available('xalan:nodeset')"> + <xsl:call-template name="collect-properties"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="defaultOfficeStyle" select="$defaultOfficeStyle" /> + <xsl:with-param name="defaultFamilyStyles" select="xalan:nodeset($defaultFamilyStyles-RTF)" /> + </xsl:call-template> + </xsl:when> + <xsl:when test="function-available('xt:node-set')"> + <xsl:call-template name="collect-properties"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="defaultOfficeStyle" select="$defaultOfficeStyle" /> + <xsl:with-param name="defaultFamilyStyles" select="xt:node-set($defaultFamilyStyles-RTF)" /> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:message terminate="yes">ERROR: Function not found: nodeset</xsl:message> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + + <xsl:template name="collect-properties"> + <xsl:param name="globalData" /> + <xsl:param name="defaultOfficeStyle" /> + <xsl:param name="defaultFamilyStyles" /> + + <!--** traversee all style trees - branch after branch - collecting style properties **--> + <xsl:element name="all-doc-styles" namespace=""> + + <!-- Background Information: + + There are two different types of styles in the Office: + 1) The office:styles from the user pre-defined style templates + 2) The automatic:styles, which are created whenever a user uses explicit style formatting. + + The office:styles only have parent styles in the office:styles, + but automatic:styles may inherit from both office:styles and themself. + --> + + <!--** traversee all office:styles trees beginning with the top-level styles **--> + <xsl:for-each select="$globalData/office:styles/style:style[not(@style:parent-style-name)]"> + <!-- Looking for parents from style:family + <xsl:for-each select="$globalData/office:styles/style:style[@style:family=current()/@style:family][not(@style:parent-style-name)]"> --> + <xsl:choose> + <xsl:when test="$defaultFamilyStyles/style[@style:family=current()/@style:family]"> + <xsl:call-template name="inherit-style-for-self-and-children"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="inheritedStyleProperties" select="$defaultFamilyStyles/style[@style:family=current()/@style:family]/*" /> + <xsl:with-param name="searchOnlyInAutomaticStyles" select="false()" /> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:call-template name="inherit-style-for-self-and-children"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="inheritedStyleProperties" select="$defaultOfficeStyle/style/*" /> + <xsl:with-param name="searchOnlyInAutomaticStyles" select="false()" /> + </xsl:call-template> + </xsl:otherwise> + </xsl:choose> + <!--** creates a style element with style:name and style:family attribute and + an element representing the absolute style properties style:property ** --> + </xsl:for-each> + + <!--** traversee all office:automatic-styles trees beginning with the top-level styles **--> + <xsl:for-each select="$globalData/office:automatic-styles/style:style[not(@style:parent-style-name)]"> + <!--** creates a style element with style:name and style:family attribute and + an element representing the absolute style properties style:property ** --> + <xsl:choose> + <xsl:when test="$defaultFamilyStyles/style[@style:family=current()/@style:family]"> + <xsl:call-template name="inherit-style-for-self-and-children"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="inheritedStyleProperties" select="$defaultFamilyStyles/style[@style:family=current()/@style:family]/*" /> + <xsl:with-param name="searchOnlyInAutomaticStyles" select="true()" /> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:call-template name="inherit-style-for-self-and-children"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="inheritedStyleProperties" select="$defaultOfficeStyle/style/*" /> + <xsl:with-param name="searchOnlyInAutomaticStyles" select="true()" /> + </xsl:call-template> + </xsl:otherwise> + </xsl:choose> + + </xsl:for-each> + + </xsl:element> + <!-- debug output in case only styles should be given out (regression test) --> + <xsl:if test="$onlyStyleOutputEnabled"> + <xsl:element name="defaultOfficeStyle" namespace=""> + <xsl:copy-of select="$defaultOfficeStyle" /> + </xsl:element> + <xsl:element name="defaultFamilyStyles" namespace=""> + <xsl:copy-of select="$defaultFamilyStyles" /> + </xsl:element> + </xsl:if> + + </xsl:template> + + + <xsl:template name="inherit-style-for-self-and-children"> + <xsl:param name="globalData" /> + <xsl:param name="inheritedStyleProperties" /> + <xsl:param name="searchOnlyInAutomaticStyles" /> + + <!--** create an absolute style by inheriting properties from the given parent properties **--> + <xsl:variable name="newStyleProperties-RTF"> + <xsl:call-template name="create-inherited-style-properties"> + <xsl:with-param name="inheritedStyleProperties" select="$inheritedStyleProperties" /> + </xsl:call-template> + </xsl:variable> + <xsl:choose> + <xsl:when test="function-available('common:node-set')"> + <xsl:variable name="newStyleProperties" select="common:node-set($newStyleProperties-RTF)" /> + + <xsl:element name="style" namespace=""> + <xsl:copy-of select="@style:family" /> + <xsl:copy-of select="@style:name" /> + <xsl:copy-of select="$newStyleProperties" /> + </xsl:element> + + <xsl:choose> + <xsl:when test="$searchOnlyInAutomaticStyles"> + <xsl:call-template name="get-children"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="searchOnlyInAutomaticStyles" select="true()" /> + <xsl:with-param name="inheritedStyleProperties" select="$newStyleProperties/*" /> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <!--** for all automatic-children of the current office:styles **--> + <xsl:call-template name="get-children"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="searchOnlyInAutomaticStyles" select="false()" /> + <xsl:with-param name="inheritedStyleProperties" select="$newStyleProperties/*" /> + </xsl:call-template> + </xsl:otherwise> + </xsl:choose> + </xsl:when> + <xsl:when test="function-available('xalan:nodeset')"> + <xsl:variable name="newStyleProperties" select="xalan:nodeset($newStyleProperties-RTF)" /> + + <xsl:element name="style" namespace=""> + <xsl:copy-of select="@style:family" /> + <xsl:copy-of select="@style:name" /> + <xsl:copy-of select="$newStyleProperties" /> + </xsl:element> + + <xsl:choose> + <xsl:when test="$searchOnlyInAutomaticStyles"> + <xsl:call-template name="get-children"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="searchOnlyInAutomaticStyles" select="true()" /> + <xsl:with-param name="inheritedStyleProperties" select="$newStyleProperties/*" /> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <!--** for all automatic-children of the current office:styles **--> + <xsl:call-template name="get-children"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="searchOnlyInAutomaticStyles" select="false()" /> + <xsl:with-param name="inheritedStyleProperties" select="$newStyleProperties/*" /> + </xsl:call-template> + </xsl:otherwise> + </xsl:choose> + </xsl:when> + <xsl:when test="function-available('xt:node-set')"> + <xsl:variable name="newStyleProperties" select="xt:node-set($newStyleProperties-RTF)" /> + + <xsl:element name="style" namespace=""> + <xsl:copy-of select="@style:family" /> + <xsl:copy-of select="@style:name" /> + <xsl:copy-of select="$newStyleProperties" /> + </xsl:element> + + <xsl:choose> + <xsl:when test="$searchOnlyInAutomaticStyles"> + <xsl:call-template name="get-children"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="searchOnlyInAutomaticStyles" select="true()" /> + <xsl:with-param name="inheritedStyleProperties" select="$newStyleProperties/*" /> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <!--** for all automatic-children of the current office:styles **--> + <xsl:call-template name="get-children"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="searchOnlyInAutomaticStyles" select="false()" /> + <xsl:with-param name="inheritedStyleProperties" select="$newStyleProperties/*" /> + </xsl:call-template> + </xsl:otherwise> + </xsl:choose> + </xsl:when> + <xsl:otherwise> + <xsl:message terminate="yes">ERROR: Function not found: nodeset</xsl:message> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + + <xsl:template name="get-children"> + <xsl:param name="globalData" /> + <xsl:param name="searchOnlyInAutomaticStyles" /> + <xsl:param name="inheritedStyleProperties" select="*" /> + +<!-- QUESTION: Parent style is only unique by name and family, but what about cross family inheritance? --> + <!-- For each child style (that is every style which has the given parentStyleName as style:parent-style-name and the same style:family --> + <xsl:variable name="parentStyleFamily" select="@style:family" /> + <xsl:variable name="parentStyleName" select="@style:name" /> + <xsl:if test="not($searchOnlyInAutomaticStyles)"> + <xsl:for-each select="$globalData/office:styles/style:style[@style:family=$parentStyleFamily and @style:parent-style-name=$parentStyleName]"> + <xsl:call-template name="inherit-style-for-self-and-children"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="inheritedStyleProperties" select="$inheritedStyleProperties" /> + <xsl:with-param name="searchOnlyInAutomaticStyles" select="$searchOnlyInAutomaticStyles" /> + </xsl:call-template> + </xsl:for-each> + </xsl:if> + <xsl:for-each select="$globalData/office:automatic-styles/style:style[@style:family=$parentStyleFamily and @style:parent-style-name=$parentStyleName]"> + <xsl:call-template name="inherit-style-for-self-and-children"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="inheritedStyleProperties" select="$inheritedStyleProperties" /> + <xsl:with-param name="searchOnlyInAutomaticStyles" select="$searchOnlyInAutomaticStyles" /> + </xsl:call-template> + </xsl:for-each> + </xsl:template> + + + <xsl:template name="create-inherited-style-properties"> + <xsl:param name="inheritedStyleProperties" /> + + <xsl:element name="style:properties"> + <!-- Writing all inherited style properties --> + <xsl:for-each select="$inheritedStyleProperties/@*"> + <xsl:sort select="name()" /> + <xsl:copy-of select="." /> + </xsl:for-each> + + <!-- split border into border parts for better activation-check on style:joint-border feature --> + <xsl:if test="*/@fo:border"> + <xsl:attribute name="fo:border-top"><xsl:value-of select="*/@fo:border"/></xsl:attribute> + <xsl:attribute name="fo:border-left"><xsl:value-of select="*/@fo:border"/></xsl:attribute> + <xsl:attribute name="fo:border-bottom"><xsl:value-of select="*/@fo:border"/></xsl:attribute> + <xsl:attribute name="fo:border-right"><xsl:value-of select="*/@fo:border"/></xsl:attribute> + </xsl:if> + + <!--All current attributes will override already inserted attributes of the same name + XSLT Spec: "Adding an attribute to an element replaces any existing attribute of that element with the same expanded-name." --> + <xsl:for-each select="*/@*[name() != 'style:font-size-rel'][name() != 'fo:border']"> + <xsl:copy-of select="." /> + </xsl:for-each> + + <xsl:if test="*/@style:font-size-rel"> +<!-- + The intheritedStyleProperties should include an absolute Font Size, but + <style:properties + xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" + xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" + style:font-name="Courier New" + fo:language="en" + fo:country="US" + style:font-name-asian=Courier New" + style:font-name-complex="Courier New"/> +--> + <xsl:variable name="fontSizeAbsolute"> + <xsl:call-template name="convert2pt"> + <xsl:with-param name="value" select="$inheritedStyleProperties/@fo:font-size" /> + </xsl:call-template> + </xsl:variable> + + <xsl:variable name="fontSizeRelative"> + <xsl:call-template name="convert2pt"> + <xsl:with-param name="value" select="*/@style:font-size-rel" /> + </xsl:call-template> + </xsl:variable> + + <xsl:attribute name="fo:font-size"> + <xsl:value-of select="$fontSizeAbsolute + $fontSizeRelative"/> + <xsl:text>pt</xsl:text> + </xsl:attribute> + </xsl:if> + + <!-- providing tabulator indentation --> + <xsl:copy-of select="$inheritedStyleProperties/style:tab-stops"/> + <xsl:copy-of select="*/style:tab-stops"/> + </xsl:element> + </xsl:template> + + <!-- debugging & testing purpose --> + <xsl:template name="write-collected-styles"> + <xsl:param name="globalData" /> + + <xsl:message><all-doc-styles></xsl:message> + <xsl:for-each select="$globalData/all-doc-styles/style"> + <xsl:message><style</xsl:message> + <xsl:message>style:family="<xsl:value-of select="current()/@style:family" />"></xsl:message> + <xsl:message>style:name="<xsl:value-of select="current()/@style:name" />" </xsl:message> + <xsl:message> <*</xsl:message> + <xsl:for-each select="*/@*"> + <xsl:message> + <xsl:text></xsl:text> + <xsl:value-of select="name()" />="<xsl:value-of select="." />"</xsl:message> + </xsl:for-each> + <xsl:message>/></xsl:message> + <xsl:message></style></xsl:message> + </xsl:for-each> + <xsl:message></all-doc-styles></xsl:message> + </xsl:template> + + <xsl:template name="map-odf-style-properties"> + <xsl:param name="globalData" /> + + <xsl:choose> + <!--+++++ DEBUG STYLE OUTPUT FOR REGRESSION TEST +++++--> + <!-- create styles file from the style variable (testing switch) --> + <xsl:when test="$onlyStyleOutputEnabled"> + + <xsl:element name="debug-output" namespace=""> + <xsl:copy-of select="$globalData" /> + <xsl:call-template name="map-odf-properties"> + <xsl:with-param name="globalData" select="$globalData" /> + </xsl:call-template> + </xsl:element> + </xsl:when> + + <!-- create XHTML file --> + <xsl:otherwise> + <!-- to access the variable like a node-set it is necessary to convert it + from a result-tree-fragment (RTF) to a node set using the James Clark extension --> + <xsl:variable name="globalDataRTF"> + <!-- raw properties still needed for table width attribute creation --> + <xsl:copy-of select="$globalData" /> + <xsl:call-template name="map-odf-properties"> + <xsl:with-param name="globalData" select="$globalData" /> + </xsl:call-template> + </xsl:variable> + + <xsl:choose> + <xsl:when test="function-available('common:node-set')"> + <xsl:call-template name="start-main"> + <xsl:with-param name="globalData" select="common:node-set($globalDataRTF)" /> + </xsl:call-template> + </xsl:when> + <xsl:when test="function-available('xalan:nodeset')"> + <xsl:call-template name="start-main"> + <xsl:with-param name="globalData" select="xalan:nodeset($globalDataRTF)" /> + </xsl:call-template> + </xsl:when> + <xsl:when test="function-available('xt:node-set')"> + <xsl:call-template name="start-main"> + <xsl:with-param name="globalData" select="xt:node-set($globalDataRTF)" /> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:message terminate="yes">ERROR: Function not found: nodeset</xsl:message> + </xsl:otherwise> + </xsl:choose> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <!-- REASON FOR TEMPLATE: + The OpenOffice style properties gathered in the variable 'globalData' have to be mapped to the CSS style format + --> + <xsl:template name="map-odf-properties"> + <xsl:param name="globalData" /> + <xsl:element name="all-styles" namespace=""> + <xsl:for-each select="$globalData/all-doc-styles/style"> + <xsl:sort select="@style:family" /> + <xsl:sort select="@style:name" /> + + <xsl:call-template name="writeUsedStyles"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="style" select="."/> + </xsl:call-template> + </xsl:for-each> + </xsl:element> + </xsl:template> + + <xsl:key name="elementUsingStyle" match="*" use="@text:style-name | @draw:style-name | @draw:text-style-name | @table:style-name | @table:default-cell-style-name"/> + <xsl:key name="listLabelStyleInStyles" match="/*/office:styles/text:list-style/* | + /*/office:styles/style:graphic-properties/text:list-style/*" use="@text:style-name"/> + + <xsl:key name="listLabelStyleInContent" match="/*/office:automatic-styles/text:list-style/* | /*/office:automatic-styles/style:graphic-properties/text:list-style/*" use="@text:style-name"/> + + + <xsl:variable name="documentRoot" select="/" /> + <xsl:template name="writeUsedStyles"> + <xsl:param name="globalData" /> + <xsl:param name="style"/> + + <!-- for-each changes the key environment from the previously globalData back to the document root --> + <xsl:for-each select="$documentRoot"> + <!-- only styles, which are used in the content are written as CSS styles --> + <xsl:choose> + <xsl:when test="key('elementUsingStyle', $style/@style:name)/@* or key('listLabelStyleInContent', $style/@style:name)/@*"> + <xsl:call-template name="writeUsedStyles2"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="style" select="$style" /> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:choose> + <xsl:when test="not(office:document-content)"> + <xsl:if test="key('listLabelStyleInStyles', $style/@style:name)/@* or /*/office:styles/text:notes-configuration[@text:citation-style-name = $style/@style:name or /*/office:styles/@text:citation-body-style-name=$style/@style:name]"> + <!-- if there are consecutive paragraphs with borders (OR background AND margin ), only the first and the last have the top/bottom border + unless style:join-border="false" --> + <xsl:call-template name="writeUsedStyles2"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="style" select="$style" /> + </xsl:call-template> + </xsl:if> + </xsl:when> + <xsl:otherwise> + <xsl:for-each select="document($stylesFileURL)"> + <xsl:if test="key('listLabelStyleInStyles', $style/@style:name)/@* or /*/office:styles/text:notes-configuration[@text:citation-style-name = $style/@style:name or /*/office:styles/@text:citation-body-style-name=$style/@style:name]"> + <!-- if there are consecutive paragraphs with borders (OR background AND margin ), only the first and the last have the top/bottom border + unless style:join-border="false" --> + <xsl:call-template name="writeUsedStyles2"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="style" select="$style" /> + </xsl:call-template> + </xsl:if> + </xsl:for-each> + </xsl:otherwise> + </xsl:choose> + </xsl:otherwise> + </xsl:choose> + </xsl:for-each> + </xsl:template> + + <xsl:template name="writeUsedStyles2"> + <xsl:param name="globalData" /> + <xsl:param name="style"/> + <!-- activation-check on style:joint-border feature --> + <xsl:choose> + <xsl:when test=" + $style/@style:family='paragraph' + and + ( + $style/*/@fo:border-top + or + $style/*/@fo:border-bottom + ) + and + ( + not($style/*/@fo:border-top='none' and + $style/*/@fo:border-left='none' and + $style/*/@fo:border-right='none' and + $style/*/@fo:border-bottom='none') + ) + and + ( + not($style/*/@style:join-border) + or $style/*/@style:join-border = 'true' + )"> + <xsl:element name="style" namespace=""> + <xsl:copy-of select="$style/@style:family" /> + <xsl:attribute name="style:name"><xsl:value-of select="concat($style/@style:name, '_borderStart')" /></xsl:attribute> + <xsl:element name="final-properties" namespace=""> + <xsl:apply-templates select="$style/*/@*[not(name() = 'fo:border-bottom')][not(name() = 'fo:padding-bottom')][not(name() = 'fo:margin-bottom')][not(name() = 'fo:margin')]"> + <xsl:with-param name="globalData" select="$globalData" /> + </xsl:apply-templates> + <xsl:apply-templates mode="paragraphMerge" select="$style/*/@*[name() = 'fo:margin-bottom' or name() = 'fo:margin']"> + <xsl:with-param name="globalData" select="$globalData" /> + </xsl:apply-templates> + <xsl:text> border-bottom-style:none; </xsl:text> + </xsl:element> + </xsl:element> + <xsl:element name="style" namespace=""> + <xsl:copy-of select="$style/@style:family" /> + <xsl:attribute name="style:name"><xsl:value-of select="concat($style/@style:name, '_borderSides')" /></xsl:attribute> + <xsl:element name="final-properties" namespace=""> + <xsl:apply-templates select="$style/*/@*[not(name() = 'fo:border-top') and not(name() = 'fo:border-bottom')][not(name() = 'fo:padding-top') and not(name() = 'fo:padding-bottom')][not(name() = 'fo:margin-top') and not(name() = 'fo:margin-bottom')][not(name() = 'fo:margin')]"> + <xsl:with-param name="globalData" select="$globalData" /> + </xsl:apply-templates> + <xsl:apply-templates mode="paragraphMerge" select="$style/*/@*[name() = 'fo:margin-top' or name() = 'fo:margin-bottom' or name() = 'fo:margin']"> + <xsl:with-param name="globalData" select="$globalData" /> + </xsl:apply-templates> + <xsl:text> border-top-style:none; border-bottom-style:none; </xsl:text> + </xsl:element> + </xsl:element> + <xsl:element name="style" namespace=""> + <xsl:copy-of select="$style/@style:family" /> + <xsl:attribute name="style:name"><xsl:value-of select="concat($style/@style:name, '_borderEnd')" /></xsl:attribute> + <xsl:element name="final-properties" namespace=""> + <xsl:apply-templates select="$style/*/@*[not(name() = 'fo:border-top')][not(name() = 'fo:padding-top')][not(name() = 'fo:margin-top')][not(name() = 'fo:margin')]"> + <xsl:with-param name="globalData" select="$globalData" /> + </xsl:apply-templates> + <xsl:apply-templates mode="paragraphMerge" select="$style/*/@*[name() = 'fo:margin-top' or name() = 'fo:margin']"> + <xsl:with-param name="globalData" select="$globalData" /> + </xsl:apply-templates> + <xsl:text> border-top-style:none;</xsl:text> + </xsl:element> + </xsl:element> + <xsl:element name="style" namespace=""> + <xsl:copy-of select="$style/@style:family" /> + <xsl:copy-of select="$style/@style:name" /> + <!-- the original name bears the trigger: 'mergedBorder' flag--> + <xsl:attribute name="mergedBorders"><xsl:value-of select="true()" /></xsl:attribute> + <xsl:element name="final-properties" namespace=""> + <xsl:apply-templates select="$style/*/@*"> + <xsl:with-param name="globalData" select="$globalData" /> + </xsl:apply-templates> + </xsl:element> + </xsl:element> + </xsl:when> + <xsl:otherwise> + <xsl:choose> + <xsl:when test="not(key('listLabelStyleInStyles', $style/@style:name)/@*)"> + <xsl:element name="style" namespace=""> + <xsl:copy-of select="$style/@style:family" /> + <xsl:copy-of select="$style/@style:name" /> + <xsl:element name="final-properties" namespace=""> + <xsl:apply-templates select="$style/*/@*"> + <xsl:with-param name="globalData" select="$globalData" /> + </xsl:apply-templates> + </xsl:element> + </xsl:element> + </xsl:when> + <xsl:otherwise> + <xsl:element name="style" namespace=""> + <xsl:attribute name="style:family">none</xsl:attribute> + <xsl:attribute name="style:name"><xsl:value-of select="$style/@style:name"/></xsl:attribute> + <xsl:element name="final-properties" namespace=""> + <xsl:apply-templates select="$style/*/@*"> + <xsl:with-param name="globalData" select="$globalData" /> + </xsl:apply-templates> + </xsl:element> + </xsl:element> + </xsl:otherwise> + </xsl:choose> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + <!-- workaround AOOO#119401 suspicious property fo:margin="100%" in paragraph style --> + <xsl:template match="@fo:margin[string(.) = '100%']" mode="paragraphMerge"/> + + <xsl:template mode="paragraphMerge" match="@fo:margin | @fo:margin-top | @fo:margin-bottom | @fo:margin-left | @fo:margin-right"> + <xsl:text>padding</xsl:text> + <xsl:value-of select="substring-after(name(), 'fo:margin')"/> + <xsl:text>:</xsl:text> + <!-- Map once erroneously used inch shortage 'inch' to CSS shortage 'in' --> + <xsl:choose> + <xsl:when test="contains(., 'inch')"> + <xsl:value-of select="substring-before(.,'ch')"/> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="."/> + </xsl:otherwise> + </xsl:choose> + <xsl:text>; </xsl:text> + </xsl:template> +</xsl:stylesheet> diff --git a/filter/source/xslt/odf2xhtml/export/common/styles/style_mapping_css.xsl b/filter/source/xslt/odf2xhtml/export/common/styles/style_mapping_css.xsl new file mode 100644 index 000000000..c81cc9a1e --- /dev/null +++ b/filter/source/xslt/odf2xhtml/export/common/styles/style_mapping_css.xsl @@ -0,0 +1,380 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + --> +<!-- + For further documentation and updates visit http://xml.openoffice.org/odf2xhtml +--> +<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" exclude-result-prefixes="chart config dc dom dr3d draw fo form math meta number office ooo oooc ooow script style svg table text xforms xlink xsd xsi"> + + + <!-- *** Properties with a 'fo:' prefix *** --> + <xsl:template match="@fo:background-color"> + <xsl:text>background-color:</xsl:text> + <xsl:value-of select="."/> + <xsl:text>; </xsl:text> + </xsl:template> + + <xsl:template match="@fo:border | @fo:border-top | @fo:border-bottom | @fo:border-left | @fo:border-right"> + <xsl:variable name="borderType" select="substring-after(name(), ':')"/> + <xsl:choose> + <xsl:when test=". = 'none'"> + <xsl:value-of select="$borderType"/> + <xsl:text>-style:none; </xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:variable name="borderWidth" select="substring-before(., ' ')"/> + <xsl:variable name="borderStyle" select="substring-before(substring-after(., ' '), ' ')"/> + <xsl:variable name="borderColor" select="substring-after(substring-after(., ' '), ' ')"/> + + <!-- More information at template 'round-up-border-width' --> + <xsl:variable name="borderWidthFixed"> + <xsl:call-template name="round-up-border-width"> + <xsl:with-param name="borderWidth" select="$borderWidth"/> + <xsl:with-param name="multiplier"> + <xsl:choose> + <xsl:when test="$borderStyle = 'double'">3</xsl:when> + <xsl:otherwise>1</xsl:otherwise> + </xsl:choose> + </xsl:with-param> + </xsl:call-template> + </xsl:variable> + + <xsl:value-of select="$borderType"/> + <xsl:text>-width:</xsl:text> + <xsl:choose> + <xsl:when test="$borderWidth = '0.05pt'">thin</xsl:when> + <xsl:otherwise><xsl:value-of select="$borderWidthFixed"/></xsl:otherwise> + </xsl:choose> + <xsl:text>; </xsl:text> + <xsl:value-of select="$borderType"/> + <xsl:text>-style:</xsl:text> + <xsl:value-of select="$borderStyle"/> + <xsl:text>; </xsl:text> + <xsl:value-of select="$borderType"/> + <xsl:text>-color:</xsl:text> + <xsl:value-of select="$borderColor"/> + <xsl:text>; </xsl:text> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <!-- NOTE: Still there have to be placed a <br clear='all' /> to disable the flow!!!!--> + <xsl:template match="@fo:clear"> + <xsl:text>clear:both; </xsl:text> + </xsl:template> + + <!-- text-shadow is a CSS2 feature and yet not common used in user-agents --> + <xsl:template match="@fo:color |@fo:font-size |@fo:font-style |@fo:font-weight |@fo:text-indent |@fo:text-shadow |@text:display"> + <xsl:value-of select="substring-after(name(), ':')"/> + <xsl:text>:</xsl:text> + <xsl:value-of select="."/> + <xsl:text>; </xsl:text> + </xsl:template> + + <!-- text-shadow is a CSS2 feature and yet not common used in user-agents --> + <xsl:template match="@svg:font-family"> + <xsl:value-of select="substring-after(name(), ':')"/> + <xsl:text>:"</xsl:text> + <xsl:value-of select="."/> + <xsl:text>"; </xsl:text> + </xsl:template> + + <!-- workaround AOOO#119401 suspicious property fo:margin="100%" in paragraph style --> + <xsl:template match="@fo:margin[string(.) = '100%']"/> + + <!-- Maps fo:margin as well fo:margin-top, fo:margin-bottom, fo:padding-left, fo:margin-right --> + <!-- Maps fo:padding as well fo:padding-top, fo:padding-bottom, fo:padding-left, fo:padding-right --> + <xsl:template match="@fo:letter-spacing | @fo:line-height | @fo:width |@fo:margin | @fo:margin-top | @fo:margin-bottom | @fo:margin-left | @fo:margin-right | @fo:padding | @fo:padding-top | @fo:padding-bottom | @fo:padding-left | @fo:padding-right"> + <xsl:value-of select="local-name(.)"/> + <xsl:text>:</xsl:text> + <!-- Map once erroneously used inch shortage 'inch' to CSS shortage 'in' --> + <xsl:choose> + <xsl:when test="contains(., 'inch')"> + <xsl:value-of select="substring-before(.,'ch')"/> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="."/> + </xsl:otherwise> + </xsl:choose> + <xsl:text>; </xsl:text> + </xsl:template> + + <xsl:template match="@fo:text-align"> + <!-- 'important' is necessary as table cell value alignment is decided by runtime over the valuetype + Otherwise a table cell style-class would always be outnumbered by the run-time alignment value --> + <xsl:choose> + <xsl:when test="contains(., 'start')"> + <xsl:choose> + <xsl:when test="parent::*/@style:writing-mode and contains(parent::*/@style:writing-mode, 'rl')"> + <xsl:text>text-align:right ! important; </xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:text>text-align:left ! important; </xsl:text> + </xsl:otherwise> + </xsl:choose> + </xsl:when> + <xsl:when test="contains(., 'end')"> + <xsl:choose> + <xsl:when test="parent::*/@style:writing-mode and contains(parent::*/@style:writing-mode, 'rl')"> + <xsl:text>text-align:right ! important;</xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:text>text-align:left ! important; </xsl:text> + </xsl:otherwise> + </xsl:choose> + </xsl:when> + <xsl:otherwise> + <xsl:text>text-align:</xsl:text> + <xsl:value-of select="."/> + <xsl:text> ! important; </xsl:text> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <xsl:template match="@style:vertical-align"> + <xsl:choose> + <xsl:when test="contains(., 'bottom')"> + <xsl:text>vertical-align:bottom; </xsl:text> + </xsl:when> + <xsl:when test="contains(., 'middle')"> + <xsl:text>vertical-align:middle; </xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:text>vertical-align:top; </xsl:text> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + +<!-- *** Properties with a 'style:' prefix *** --> + <!-- NOTE: Can 'inside' | 'from-inside' better be handled: + <!ATTLIST * style:horizontal-pos (from-left|left|center|right|from-inside|inside|outside)#IMPLIED>--> + <xsl:template match="@style:horizontal-pos"> + <xsl:choose> + <xsl:when test=".='left'"> + <xsl:text>text-align:left; </xsl:text> + </xsl:when> + <xsl:when test=". = 'right'"> + <xsl:text>text-align:right; </xsl:text> + </xsl:when> + <xsl:when test=".='center'"> + <xsl:text>text-align:center; </xsl:text> + </xsl:when> + <!-- NOTE: currently other values are not used. + If the property value is from-left or from-inside, + the svg:x attribute associated with the frame element specifies + the horizontal position of the frame. + Otherwise the svg:x attribute is ignored for text documents. + --> + </xsl:choose> + </xsl:template> + + <xsl:template match="@style:column-width"> + <xsl:text>width:</xsl:text> + <xsl:choose> + <!-- changing the distance measure: inch to in --> + <xsl:when test="contains(., 'inch')"> + <xsl:value-of select="substring-before(.,'ch')"/> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="."/> + </xsl:otherwise> + </xsl:choose> + <xsl:text>; </xsl:text> + </xsl:template> + + <xsl:template match="@style:text-underline-style"> + <xsl:text>text-decoration:</xsl:text> + <xsl:choose> + <!-- changing the distance measure: inch to in --> + <xsl:when test=".='none'"> + <xsl:text>none ! important</xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:text>underline</xsl:text> + </xsl:otherwise> + </xsl:choose> + <xsl:text>; </xsl:text> + </xsl:template> + + <xsl:template match="@style:font-name"> + <xsl:param name="globalData" /> + + <xsl:text>font-family:</xsl:text> + <xsl:variable name="content" select="."/> + <xsl:variable name="fontName" select="$globalData/office:font-face-decls/style:font-face[@style:name=$content]/@svg:font-family" /> + <xsl:value-of select="$fontName"/> + <xsl:text>; </xsl:text> + </xsl:template> + + <xsl:template match="@style:row-height"> + <xsl:text>height:</xsl:text> + <xsl:choose> + <!-- changing the distance measure: inch to in --> + <xsl:when test="contains(., 'inch')"> + <xsl:value-of select="substring-before(.,'ch')"/> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="."/> + </xsl:otherwise> + </xsl:choose> + <xsl:text>; </xsl:text> + </xsl:template> + + <xsl:template match="@svg:strikethrough-position"> + <xsl:if test="not(.='none')"> + <xsl:text>text-decoration:line-through; </xsl:text> + </xsl:if> + </xsl:template> + <xsl:template match="@style:text-position"> + <xsl:if test="contains(., 'sub')"> + <xsl:text>vertical-align:sub; </xsl:text> + <xsl:if test="contains(., '%')"> + <xsl:text>font-size:</xsl:text> + <xsl:value-of select="substring-after(., 'sub ')"/> + <xsl:text>;</xsl:text> + </xsl:if> + </xsl:if> + <xsl:if test="contains(., 'super')"> + <xsl:text>vertical-align:super; </xsl:text> + <xsl:if test="contains(., '%')"> + <xsl:text>font-size:</xsl:text> + <xsl:value-of select="substring-after(., 'super ')"/> + <xsl:text>;</xsl:text> + </xsl:if> + </xsl:if> + </xsl:template> + + <xsl:template match="@style:vertical-pos"> + <xsl:choose> + <xsl:when test=".='from-top'"> + <xsl:text>vertical-align:top; </xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:text>vertical-align:</xsl:text> + <xsl:value-of select="."/> + <xsl:text>; </xsl:text> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <xsl:template match="@style:width"> + <xsl:text>width:</xsl:text> + <xsl:choose> + <!-- changing the distance measure: inch to in --> + <xsl:when test="contains(., 'inch')"> + <xsl:value-of select="substring-before(.,'ch')"/> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="."/> + </xsl:otherwise> + </xsl:choose> + <xsl:text>; </xsl:text> + </xsl:template> + <xsl:template match="@style:wrap"> + <xsl:choose> + <xsl:when test=".='left'"> + <xsl:text>float:right; </xsl:text> + </xsl:when> + <xsl:when test=".='right'"> + <xsl:text>float:left; </xsl:text> + </xsl:when> + </xsl:choose> + </xsl:template> + <xsl:template match="@style:writing-mode"> + <xsl:text>writing-mode:</xsl:text> + <xsl:choose> + <xsl:when test=".='rl-tb'"> + <xsl:text>horizontal-tb; direction:rtl; </xsl:text> + </xsl:when> + <xsl:when test=".='lr-tb'"> + <xsl:text>horizontal-tb; direction:ltr; </xsl:text> + </xsl:when> + <xsl:when test=".='tb-rl'"> + <xsl:text>vertical-rl; </xsl:text> + </xsl:when> + <xsl:when test=".='tb-lr'"> + <xsl:text>vertical-lr; </xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:text>horizontal-tb; direction:ltr;</xsl:text> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + <!-- *** Properties with a no 'fo:' or 'style:' prefix *** --> + <xsl:template match="@table:align"> + <xsl:choose> + <xsl:when test=".='left'"> + <xsl:if test="not(../@fo:margin-left)">margin-left:0px; </xsl:if> + <xsl:text>margin-right:auto;</xsl:text></xsl:when> + <xsl:when test=".='right'"> + <xsl:text>margin-left:auto</xsl:text> + <xsl:if test="not(../@fo:margin-right)"> + ; margin-right: 0px; + </xsl:if> + </xsl:when> + <xsl:when test=".='center'"> + margin-left:auto;margin-right:auto; + </xsl:when> + <xsl:otherwise> + <xsl:text>float:none; </xsl:text> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <xsl:template match="style:background-image"> + <xsl:text>background-image:url(</xsl:text> + <xsl:value-of select="@xlink:href"/> + <xsl:text>); </xsl:text> + <xsl:choose> + <xsl:when test="@style:repeat = 'repeat'"> + <xsl:text>background-repeat:repeat; </xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:text>background-repeat:no-repeat; </xsl:text> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <!-- Changing border width measure to cm and enlarging border-width to the Mozilla browser(1.7) + visible minimum width + - 0.0133cm for solid style + - 0.0399cm for double style + as there are three border lines painted --> + <xsl:decimal-format name = "unifiedFormat" decimal-separator = "." /> + <xsl:template name="round-up-border-width"> + <xsl:param name="borderWidth"/> + <xsl:param name="multiplier"/> + + <xsl:variable name="borderWidthByCentimeter"> + <xsl:call-template name="convert2cm"> + <xsl:with-param name="value" select="$borderWidth"/> + </xsl:call-template> + </xsl:variable> + <xsl:variable name="minimalBorderWidth" select="0.0133 * $multiplier"/> + <xsl:choose> + <xsl:when test="number($borderWidthByCentimeter) < $minimalBorderWidth"> + <xsl:value-of select="format-number($minimalBorderWidth,'0.######','unifiedFormat')"/> + <xsl:text>cm</xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="format-number($borderWidthByCentimeter,'0.######','unifiedFormat')"/> + <xsl:text>cm</xsl:text> + </xsl:otherwise> + </xsl:choose> + </xsl:template> +</xsl:stylesheet> diff --git a/filter/source/xslt/odf2xhtml/export/common/table/table.xsl b/filter/source/xslt/odf2xhtml/export/common/table/table.xsl new file mode 100644 index 000000000..cfc1ebbc5 --- /dev/null +++ b/filter/source/xslt/odf2xhtml/export/common/table/table.xsl @@ -0,0 +1,155 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + --> +<!-- + For further documentation and updates visit http://xml.openoffice.org/odf2xhtml +--> +<xsl:stylesheet version="1.0" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" + xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:dom="http://www.w3.org/2001/xml-events" + xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" + xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" + xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" + xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" + xmlns:math="http://www.w3.org/1998/Math/MathML" + xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" + xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" + xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" + xmlns:ooo="http://openoffice.org/2004/office" + xmlns:oooc="http://openoffice.org/2004/calc" + xmlns:ooow="http://openoffice.org/2004/writer" + xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" + xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" + xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" + xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" + xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" + xmlns:xforms="http://www.w3.org/2002/xforms" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + exclude-result-prefixes="chart config dc dom dr3d draw fo form math meta number office ooo oooc ooow script style svg table text xforms xlink xsd xsi"> + + + <!-- table row handling --> + <xsl:include href="table_rows.xsl" /> + <!-- table column handling --> + <xsl:include href="table_columns.xsl" /> + <!-- table cell handling --> + <xsl:include href="table_cells.xsl" /> + + <xsl:param name="tableElement" select="'table'" /> + + <!-- ******************* --> + <!-- *** main table *** --> + <!-- ******************* --> + + + <xsl:template match="table:table" name="table:table"> + <xsl:param name="globalData" /> + + <!-- The table will only be created if the table:scenario is active --> + <xsl:if test="not(table:scenario) or table:scenario/@table:is-active"> + <xsl:call-template name="create-table"> + <xsl:with-param name="globalData" select="$globalData" /> + </xsl:call-template> + </xsl:if> + </xsl:template> + + + + <xsl:template name="create-table"> + <xsl:param name="globalData" /> + + <!-- by default '1', for each new sub/inner/nested table the number counts one up --> + <xsl:variable name="tableLevel" select="count(ancestor-or-self::table:table)" /> + <!-- collecting all visible "table:table-row" elements of the table --> + <xsl:variable name="allVisibleTableRows" select="table:table-row[not(@table:visibility = 'collapse' or @table:visibility = 'filter')][count(ancestor-or-self::table:table) = $tableLevel] | + table:table-header-rows/descendant::table:table-row[not(@table:visibility = 'collapse' or @table:visibility = 'filter')][count(ancestor-or-self::table:table) = $tableLevel] | + table:table-row-group/descendant::table:table-row[not(@table:visibility = 'collapse' or @table:visibility = 'filter')][count(ancestor-or-self::table:table) = $tableLevel]" /> + <!-- As the alignment of a table is by 'align' attribute is deprecated and as the CSS 'float' attribute not well displayed, + we do a trick by encapsulating the table with an aligned 'div' element--> + <xsl:variable name="table-alignment" select="key('styles', @style:name = current()/@table:style-name)/*/@table:align" /> + <xsl:choose> + <xsl:when test="string-length($table-alignment) != 0"> + <xsl:element namespace="{$namespace}" name="div"> + <xsl:attribute name="style"> + <xsl:choose> + <xsl:when test='$table-alignment="left" or $table-alignment="margins"'> + <xsl:text>text-align:left</xsl:text> + </xsl:when> + <xsl:when test='$table-alignment="right"'> + <xsl:text>text-align:right</xsl:text> + </xsl:when> + <xsl:when test='$table-alignment="center"'> + <xsl:text>text-align:center</xsl:text> + </xsl:when> + </xsl:choose> + </xsl:attribute> + <xsl:call-template name="create-table-element"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="allVisibleTableRows" select="$allVisibleTableRows" /> + </xsl:call-template> + </xsl:element> + </xsl:when> + <xsl:otherwise> + <xsl:call-template name="create-table-element"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="allVisibleTableRows" select="$allVisibleTableRows" /> + </xsl:call-template> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + + <xsl:template name="create-table-element"> + <xsl:param name="globalData" /> + <xsl:param name="allVisibleTableRows" /> + + <xsl:element namespace="{$namespace}" name="{$tableElement}"> + <xsl:attribute name="border">0</xsl:attribute> + <xsl:attribute name="cellspacing">0</xsl:attribute> + <xsl:attribute name="cellpadding">0</xsl:attribute> + <xsl:choose> + <xsl:when test='name()="table:table"'> + <xsl:variable name="value" select="$globalData/all-doc-styles/style[@style:name = current()/@table:style-name]/*/@style:rel-width" /> + <xsl:if test="$value"> + <xsl:attribute name="width"> + <xsl:value-of select="$value" /> + </xsl:attribute> + </xsl:if> + </xsl:when> + <xsl:otherwise> + <xsl:attribute name="width">100%</xsl:attribute> + </xsl:otherwise> + </xsl:choose> + + <xsl:apply-templates select="@table:style-name"> + <xsl:with-param name="globalData" select="$globalData" /> + </xsl:apply-templates> + + <xsl:call-template name="create-column-style-variable"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="allVisibleTableRows" select="$allVisibleTableRows" /> + </xsl:call-template> + </xsl:element> + </xsl:template> + +</xsl:stylesheet> diff --git a/filter/source/xslt/odf2xhtml/export/common/table/table_cells.xsl b/filter/source/xslt/odf2xhtml/export/common/table/table_cells.xsl new file mode 100644 index 000000000..3c884138b --- /dev/null +++ b/filter/source/xslt/odf2xhtml/export/common/table/table_cells.xsl @@ -0,0 +1,270 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + --> +<!-- + For further documentation and updates visit http://xml.openoffice.org/odf2xhtml +--> +<xsl:stylesheet version="1.0" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" + xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:dom="http://www.w3.org/2001/xml-events" + xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" + xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" + xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" + xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" + xmlns:math="http://www.w3.org/1998/Math/MathML" + xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" + xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" + xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" + xmlns:ooo="http://openoffice.org/2004/office" + xmlns:oooc="http://openoffice.org/2004/calc" + xmlns:ooow="http://openoffice.org/2004/writer" + xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" + xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" + xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" + xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" + xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" + xmlns:xforms="http://www.w3.org/2002/xforms" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xt="http://www.jclark.com/xt" + xmlns:common="http://exslt.org/common" + xmlns:xalan="http://xml.apache.org/xalan" + exclude-result-prefixes="chart config dc dom dr3d draw fo form math meta number office ooo oooc ooow script style svg table text xforms xlink xsd xsi xt common xalan"> + + + <!-- *********************************** --> + <!-- *** write repeating table cells *** --> + <!-- *********************************** --> + + + <!-- matching cells to give out -> covered table cells are not written out --> + <xsl:template match="table:table-cell"> + <xsl:param name="globalData" /> + <!-- position of the current input cell to get the correct column style (hidden are also counted)--> + <xsl:param name="allTableColumns" /> + <xsl:param name="maxRowLength" /> + <xsl:param name="tableDataType" /> + + + <!-- The column position of the current cell has to be determined + to get the adequate column styles during later cell creation, + or hiding the cell when @table:visibility is not set to 'visible'. + + The position is archived by adding up all table:number-columns-repeated of the preceding cells. + Step1: creating '$precedingCells/quantity/@table:number-columns-repeated'). + Step2: sum(xxx:nodeset($precedingCells)/quantity) + 1 --> + <xsl:variable name="precedingCells"> + <xsl:for-each select="preceding-sibling::*"> + <xsl:choose> + <!-- maybe a parser is used, which reads the DTD files (e.g. Xerces), + then '1' is the default for 'table:number-columns-repeated' --> + <xsl:when test="not(@table:number-columns-repeated and @table:number-columns-repeated > 1)"> + <xsl:element name="quantity" namespace=""> + <xsl:text>1</xsl:text> + </xsl:element> + </xsl:when> + <xsl:otherwise> + <xsl:element name="quantity" namespace=""> + <xsl:value-of select="@table:number-columns-repeated" /> + </xsl:element> + </xsl:otherwise> + </xsl:choose> + </xsl:for-each> + </xsl:variable> + + + + <xsl:choose> + <xsl:when test="function-available('common:node-set')"> + <xsl:call-template name="create-table-cell"> + <!-- position of the current input cell to get the correct column style (hidden are also counted)--> + <xsl:with-param name="allTableColumns" select="$allTableColumns" /> + <xsl:with-param name="maxRowLength" select="$maxRowLength" /> + <xsl:with-param name="precedingColumns" select="sum(common:node-set($precedingCells)/*)" /> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="tableDataType" select="$tableDataType" /> + </xsl:call-template> + </xsl:when> + <xsl:when test="function-available('xalan:nodeset')"> + <xsl:call-template name="create-table-cell"> + <!-- position of the current input cell to get the correct column style (hidden are also counted)--> + <xsl:with-param name="allTableColumns" select="$allTableColumns" /> + <xsl:with-param name="maxRowLength" select="$maxRowLength" /> + <xsl:with-param name="precedingColumns" select="sum(xalan:nodeset($precedingCells)/*)" /> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="tableDataType" select="$tableDataType" /> + </xsl:call-template> + </xsl:when> + <xsl:when test="function-available('xt:node-set')"> + <xsl:call-template name="create-table-cell"> + <!-- position of the current input cell to get the correct column style (hidden are also counted)--> + <xsl:with-param name="allTableColumns" select="$allTableColumns" /> + <xsl:with-param name="maxRowLength" select="$maxRowLength" /> + <xsl:with-param name="precedingColumns" select="sum(xt:node-set($precedingCells)/*)" /> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="tableDataType" select="$tableDataType" /> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:message terminate="yes">ERROR: Function not found: nodeset</xsl:message> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + + <!-- current node is a table:table-cell --> + <xsl:template name="create-table-cell"> + <!-- position of the current input cell to get the correct column style (hidden are also counted)--> + <xsl:param name="allTableColumns" /> + <xsl:param name="globalData" /> + <xsl:param name="maxRowLength" /> + <xsl:param name="precedingColumns" select="0" /> + <xsl:param name="tableDataType" /> + + <xsl:variable name="columnPosition" select="$precedingColumns + 1" /> + + <xsl:if test="$debugEnabled"> + <xsl:message> + <xsl:text> + table:table-cell #</xsl:text> + <xsl:value-of select="$columnPosition" /> + <xsl:text> has been entered with node value: </xsl:text> + <xsl:value-of select="." /> + <xsl:text> + table:number-columns-repeated: </xsl:text> + <xsl:value-of select="@table:number-columns-repeated" /> + <xsl:text> + maxRowLength: </xsl:text> + <xsl:value-of select="$maxRowLength" /> + </xsl:message> + </xsl:if> + + <!-- only non hidden column will be given out --> + <xsl:variable name="currentTableColumn" select="$allTableColumns/table:table-column[position() = $columnPosition]" /> + <xsl:if test="$currentTableColumn[not(@table:visibility = 'collapse' or @table:visibility = 'filter')]"> + <xsl:choose> + <!-- if parser reads DTD the default is set to '1' --> + <xsl:when test="@table:number-columns-repeated > 1"> + <!-- writes multiple entries of a cell --> + <xsl:call-template name="repeat-write-cell"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="allTableColumns" select="$allTableColumns" /> + <xsl:with-param name="columnPosition" select="$columnPosition" /> + <xsl:with-param name="currentTableColumn" select="$currentTableColumn" /> + <xsl:with-param name="maxRowLength" select="$maxRowLength" /> + <xsl:with-param name="numberColumnsRepeated" select="@table:number-columns-repeated" /> + <xsl:with-param name="tableDataType" select="$tableDataType" /> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <!-- writes an entry of a cell --> + <xsl:call-template name="write-cell"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="allTableColumns" select="$allTableColumns" /> + <xsl:with-param name="columnPosition" select="$columnPosition" /> + <xsl:with-param name="currentTableColumn" select="$currentTableColumn" /> + <xsl:with-param name="maxRowLength" select="$maxRowLength" /> + <xsl:with-param name="tableDataType" select="$tableDataType" /> + </xsl:call-template> + </xsl:otherwise> + </xsl:choose> + </xsl:if> + </xsl:template> + + + <xsl:template name="repeat-write-cell"> + <xsl:param name="globalData" /> + <xsl:param name="allTableColumns" /> + <xsl:param name="columnPosition" /> + <xsl:param name="currentTableColumn" /> + <xsl:param name="maxRowLength" /> + <xsl:param name="numberColumnsRepeated" /> + <xsl:param name="tableDataType" /> + + <xsl:choose> + <!-- This is the current workaround for the flood of cells, simulation background by repeating cell --> + <xsl:when test="$numberColumnsRepeated > 1 and $maxRowLength > $columnPosition"> + + <!-- writes an entry of a cell --> + <xsl:call-template name="write-cell"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="allTableColumns" select="$allTableColumns" /> + <xsl:with-param name="columnPosition" select="$columnPosition" /> + <xsl:with-param name="currentTableColumn" select="$currentTableColumn" /> + <xsl:with-param name="tableDataType" select="$tableDataType" /> + </xsl:call-template> + <!-- repeat calling this method until all elements written out --> + <xsl:if test="$debugEnabled"> + <xsl:message>+++++++++ cell repetition +++++++++</xsl:message> + </xsl:if> + <xsl:call-template name="repeat-write-cell"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="allTableColumns" select="$allTableColumns" /> + <xsl:with-param name="columnPosition" select="$columnPosition + 1" /> + <xsl:with-param name="currentTableColumn" select="$allTableColumns/table:table-column[position() = ($columnPosition + 1)]" /> + <xsl:with-param name="maxRowLength" select="$maxRowLength" /> + <xsl:with-param name="numberColumnsRepeated" select="$numberColumnsRepeated - 1" /> + <xsl:with-param name="tableDataType" select="$tableDataType" /> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <!-- This is the current workaround for the flood of cells, simulation background by repeating cell --> + <!-- When the maxRowLength is reached a last entry of a cell is written --> + <xsl:call-template name="write-cell"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="allTableColumns" select="$allTableColumns" /> + <xsl:with-param name="columnPosition" select="$columnPosition" /> + <xsl:with-param name="currentTableColumn" select="$currentTableColumn" /> + <xsl:with-param name="tableDataType" select="$tableDataType" /> + </xsl:call-template> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + + <xsl:template name="write-cell"> + <xsl:param name="globalData" /> + <xsl:param name="allTableColumns" /> + <xsl:param name="columnPosition" /> + <xsl:param name="currentTableColumn" /> + <xsl:param name="tableDataType" /> + + <!-- a non hidden column will be give out --> + <xsl:choose> + <xsl:when test="$currentTableColumn[not(@table:visibility = 'collapse' or @table:visibility = 'filter')]"> + <xsl:call-template name="create-table-cell-content"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="allTableColumns" select="$allTableColumns" /> + <xsl:with-param name="columnPosition" select="$columnPosition" /> + <xsl:with-param name="currentTableColumn" select="$currentTableColumn" /> + <xsl:with-param name="tableDataType" select="$tableDataType" /> + </xsl:call-template> + </xsl:when> + <!-- a hidden column --> + <xsl:otherwise> + <xsl:if test="$debugEnabled"> + <xsl:message>table column is hidden!</xsl:message> + </xsl:if> + </xsl:otherwise> + </xsl:choose> + </xsl:template> +</xsl:stylesheet> diff --git a/filter/source/xslt/odf2xhtml/export/common/table/table_columns.xsl b/filter/source/xslt/odf2xhtml/export/common/table/table_columns.xsl new file mode 100644 index 000000000..f83302fa0 --- /dev/null +++ b/filter/source/xslt/odf2xhtml/export/common/table/table_columns.xsl @@ -0,0 +1,232 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + --> +<!-- + For further documentation and updates visit http://xml.openoffice.org/odf2xhtml +--> +<xsl:stylesheet version="1.0" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" + xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:dom="http://www.w3.org/2001/xml-events" + xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" + xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" + xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" + xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" + xmlns:math="http://www.w3.org/1998/Math/MathML" + xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" + xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" + xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" + xmlns:ooo="http://openoffice.org/2004/office" + xmlns:oooc="http://openoffice.org/2004/calc" + xmlns:ooow="http://openoffice.org/2004/writer" + xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" + xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" + xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" + xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" + xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" + xmlns:xforms="http://www.w3.org/2002/xforms" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xt="http://www.jclark.com/xt" + xmlns:common="http://exslt.org/common" + xmlns:xalan="http://xml.apache.org/xalan" + exclude-result-prefixes="chart config dc dom dr3d draw fo form math meta number office ooo oooc ooow script style svg table text xforms xlink xsd xsi xt common xalan"> + + <xsl:param name="tableColumnElement" select="'col'" /> + + <!-- ******************************************** --> + <!-- *** Create table columns style variable *** --> + <!-- ******************************************** --> + + <!-- current node is a table:table --> + <xsl:template name="create-column-style-variable"> + <xsl:param name="globalData" /> + <xsl:param name="allVisibleTableRows" /> + + <!-- all columns of the table --> + <xsl:variable name="allTableColumns" select="table:table-column | + table:table-column-group/descendant::table:table-column | + table:table-header-columns/descendant::table:table-column" /> + <!-- allTableColumns: Containing all columns of the table, hidden and viewed. + - if a column is hidden, if table:visibility has the value 'collapse' or 'filter', otherwise the value is 'visible' + - if a column is being repeated, each repeated column is explicitly written as entry in this variable. + Later (during template "write-cell") the style of the column will be mixed with the cell-style by using + the position() of the column entry and comparing it with the iterating cell number. --> + <xsl:variable name="allTableColumns-RTF"> + <xsl:for-each select="$allTableColumns"> + <xsl:call-template name="adding-column-styles-entries"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="allTableColumns" select="$allTableColumns" /> + </xsl:call-template> + </xsl:for-each> + </xsl:variable> + + <xsl:choose> + <xsl:when test="function-available('common:node-set')"> + <xsl:call-template name="create-table-children"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="allVisibleTableRows" select="$allVisibleTableRows" /> + <xsl:with-param name="allTableColumns" select="common:node-set($allTableColumns-RTF)" /> + </xsl:call-template> + </xsl:when> + <xsl:when test="function-available('xalan:nodeset')"> + <xsl:call-template name="create-table-children"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="allVisibleTableRows" select="$allVisibleTableRows" /> + <xsl:with-param name="allTableColumns" select="xalan:nodeset($allTableColumns-RTF)" /> + </xsl:call-template> + </xsl:when> + <xsl:when test="function-available('xt:node-set')"> + <xsl:call-template name="create-table-children"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="allVisibleTableRows" select="$allVisibleTableRows" /> + <xsl:with-param name="allTableColumns" select="xt:node-set($allTableColumns-RTF)" /> + </xsl:call-template> + </xsl:when> + </xsl:choose> + </xsl:template> + + <!-- current node is a table:table --> + <xsl:template name="create-table-children"> + <xsl:param name="globalData" /> + <xsl:param name="allVisibleTableRows" /> + <xsl:param name="allTableColumns" /> + + + <xsl:for-each select="$allTableColumns/table:table-column"> + <xsl:if test="not(@table:visibility = 'collapse' or @table:visibility = 'filter')"> + + <xsl:call-template name="create-column-element"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="allVisibleTableRows" select="$allVisibleTableRows" /> + <xsl:with-param name="allTableColumns" select="$allTableColumns" /> + </xsl:call-template> + </xsl:if> + </xsl:for-each> + + <xsl:call-template name="create-table-rows"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="allVisibleTableRows" select="$allVisibleTableRows" /> + <xsl:with-param name="allTableColumns" select="$allTableColumns" /> + </xsl:call-template> + </xsl:template> + + <!-- To be OVERWRITTEN --> + <xsl:template name="create-column-element" /> + + <!-- current node is a table:table-column --> + <xsl:template name="adding-column-styles-entries"> + <xsl:param name="globalData" /> + <xsl:param name="allTableColumns" /> + + <xsl:choose> + <!-- if parser reads DTD the default is set to '1' --> + <xsl:when test="not(@table:number-columns-repeated and @table:number-columns-repeated > 1)"> + <!-- writes an entry of a column in the columns-variable --> + <xsl:copy-of select="." /> + </xsl:when> + <!-- No higher repetition of cells greater than 99 for the last and second last column. + This is a workaround for some sample document (Waehrungsumrechner.sxc), + having 230 repeated columns in the second last column to emulate background --> + <!-- NOTE: Testcase with a table containing table:table-column-group and/or table:table-header-columns --> + <xsl:when test="(last() or (last() - 1)) and @table:number-columns-repeated > 99"> + <!-- writes an entry of a column in the columns-variable --> + <xsl:call-template name="repeat-adding-table-column"> + <xsl:with-param name="numberColumnsRepeated" select="1" /> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <!-- repeated columns will be written explicit several times in the variable--> + <xsl:call-template name="repeat-adding-table-column"> + <xsl:with-param name="numberColumnsRepeated" select="@table:number-columns-repeated" /> + </xsl:call-template> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + + <!-- WRITES THE REPEATED COLUMN STYLE EXPLICIT AS AN ELEMENT IN THE COLUMNS-VARIABLE --> + <!-- current node is a table:table-column --> + <xsl:template name="repeat-adding-table-column"> + <xsl:param name="table:table-column" /> + <xsl:param name="numberColumnsRepeated" /> + + + <xsl:choose> + <xsl:when test="$numberColumnsRepeated > 1"> + <!-- writes an entry of a column in the columns-variable --> + <xsl:copy-of select="." /> + <!-- repeat calling this method until all elements written out --> + <xsl:call-template name="repeat-adding-table-column"> + <xsl:with-param name="numberColumnsRepeated" select="$numberColumnsRepeated - 1" /> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <!-- writes an entry of a column in the columns-variable --> + <xsl:copy-of select="." /> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + + <!--debugEnabled-START--> + <!-- giving out the 'allColumnStyle' variable: + For each 'table:table-column' of the 'allTableColumns' variable the style-name is given out. + In case of 'column-hidden-flag' attribute the text 'Column is hidden is given out.--> + <!-- current node is a table:table --> + <xsl:template name="table-debug-allTableColumns"> + <xsl:param name="allTableColumns" /> + + <!-- debug output as table summary attribute in html --> + <xsl:attribute name="summary"> + <xsl:call-template name="table-debug-column-out"> + <xsl:with-param name="allTableColumns" select="$allTableColumns" /> + </xsl:call-template> + </xsl:attribute> + <!-- debug output to console --> + <xsl:message> + <xsl:call-template name="table-debug-column-out"> + <xsl:with-param name="allTableColumns" select="$allTableColumns" /> + </xsl:call-template> + </xsl:message> + </xsl:template> + + <!-- current node is a table:table --> + <xsl:template name="table-debug-column-out"> + <xsl:param name="allTableColumns" /> + <xsl:text> + DebugInformation: For each 'table:table-column' of the 'allTableColumns' variable the style-name is given out. + In case of table:visibility attribute unequal 'visible' the 'column is hidden' no text is given out. + </xsl:text> + <xsl:for-each select="$allTableColumns/table:table-column"> + <xsl:choose> + <xsl:when test="@table:visibility = 'collapse' or @table:visibility = 'filter' "> + <xsl:text> </xsl:text><xsl:value-of select="@table:style-name" /><xsl:text>column is hidden</xsl:text><xsl:text></xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:text> </xsl:text><xsl:value-of select="@table:style-name" /><xsl:text> </xsl:text><xsl:value-of select="@table:default-cell-style-name" /><xsl:text></xsl:text> + </xsl:otherwise> + </xsl:choose> + </xsl:for-each> + </xsl:template> + <!--debugEnabled-END--> + +</xsl:stylesheet> diff --git a/filter/source/xslt/odf2xhtml/export/common/table/table_rows.xsl b/filter/source/xslt/odf2xhtml/export/common/table/table_rows.xsl new file mode 100644 index 000000000..2d6cd7285 --- /dev/null +++ b/filter/source/xslt/odf2xhtml/export/common/table/table_rows.xsl @@ -0,0 +1,203 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + --> +<!-- + For further documentation and updates visit http://xml.openoffice.org/odf2xhtml +--> +<xsl:stylesheet version="1.0" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" + xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:dom="http://www.w3.org/2001/xml-events" + xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" + xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" + xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" + xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" + xmlns:math="http://www.w3.org/1998/Math/MathML" + xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" + xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" + xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" + xmlns:ooo="http://openoffice.org/2004/office" + xmlns:oooc="http://openoffice.org/2004/calc" + xmlns:ooow="http://openoffice.org/2004/writer" + xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" + xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" + xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" + xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" + xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" + xmlns:xforms="http://www.w3.org/2002/xforms" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + exclude-result-prefixes="chart config dc dom dr3d draw fo form math meta number office ooo oooc ooow script style svg table text xforms xlink xsd xsi"> + + + <xsl:param name="rowElement" select="'tr'" /> + + <!-- ********************************** --> + <!-- *** write repeating table rows *** --> + <!-- ********************************** --> + + <!-- current node is a table:table --> + <xsl:template name="create-table-rows"> + <xsl:param name="globalData" /> + <xsl:param name="allVisibleTableRows" /> + <xsl:param name="allTableColumns" /> + + <!-- Some Office Calc documents simulate a background by repeating one of the later cells until end of used space + (The value of "table:number-columns-repeated" is enormous). Writing out all these cells would be fatal in time + and output size. Therefore, this global variable shows us the longest row with content. --> + <xsl:variable name="maxRowLength" select="count($allTableColumns/table:table-column)" /> + <xsl:if test="$debugEnabled"> + <xsl:message>maxRowLength: <xsl:value-of select="$maxRowLength" /></xsl:message> + <xsl:call-template name="table-debug-allTableColumns"> + <xsl:with-param name="allTableColumns" select="$allTableColumns" /> + </xsl:call-template> + </xsl:if> + + <!-- a table is a table header, when it has a "table:table-header-rows" ancestor --> + <xsl:variable name="tableDataType"> + <xsl:choose> + <xsl:when test="ancestor::table:table-header-rows"> + <xsl:text>th</xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:text>td</xsl:text> + </xsl:otherwise> + </xsl:choose> + </xsl:variable> + + <!-- removes repetition of rows, most probably done for background emulating --> + <xsl:for-each select="$allVisibleTableRows"> + <xsl:choose> + <xsl:when test="(last() or (last() - 1)) and @table:number-rows-repeated > 99"> + <xsl:call-template name="repeat-write-row"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="allTableColumns" select="$allTableColumns" /> + <xsl:with-param name="numberRowsRepeated" select="1" /> + <xsl:with-param name="maxRowLength" select="$maxRowLength" /> + <xsl:with-param name="tableDataType" select="$tableDataType" /> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:call-template name="repeat-write-row"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="allTableColumns" select="$allTableColumns" /> + <xsl:with-param name="numberRowsRepeated" select="@table:number-rows-repeated" /> + <xsl:with-param name="maxRowLength" select="$maxRowLength" /> + <xsl:with-param name="tableDataType" select="$tableDataType" /> + </xsl:call-template> + </xsl:otherwise> + </xsl:choose> + </xsl:for-each> + </xsl:template> + + + <xsl:template name="repeat-write-row"> + <xsl:param name="globalData" /> + <xsl:param name="allTableColumns" /> + <xsl:param name="numberRowsRepeated" select="1" /> + <xsl:param name="maxRowLength" /> + <xsl:param name="tableDataType" /> + + <xsl:choose> + <!-- write an entry of a row and repeat calling this method until all elements are written out --> + <xsl:when test="$numberRowsRepeated > 1 and table:table-cell"> + <xsl:call-template name="write-row"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="allTableColumns" select="$allTableColumns" /> + <xsl:with-param name="maxRowLength" select="$maxRowLength" /> + <xsl:with-param name="tableDataType" select="$tableDataType" /> + </xsl:call-template> + + <!-- NOTE: take variable from the output of repeated write-row and iterate giving out the variable --> + <xsl:call-template name="repeat-write-row"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="allTableColumns" select="$allTableColumns" /> + <xsl:with-param name="maxRowLength" select="$maxRowLength" /> + <xsl:with-param name="numberRowsRepeated" select="$numberRowsRepeated - 1" /> + <xsl:with-param name="tableDataType" select="$tableDataType" /> + </xsl:call-template> + </xsl:when> + <!-- write a single entry of a row --> + <xsl:otherwise> + <xsl:call-template name="write-row"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="allTableColumns" select="$allTableColumns" /> + <xsl:with-param name="maxRowLength" select="$maxRowLength" /> + <xsl:with-param name="tableDataType" select="$tableDataType" /> + </xsl:call-template> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + + <xsl:template name="add-table-row-attributes"> + <xsl:param name="globalData" /> + + <!-- writing the style of the row --> + <xsl:if test="@table:style-name"> + <xsl:call-template name='add-style-properties'> + <xsl:with-param name="globalData" select="$globalData" /> + </xsl:call-template> + </xsl:if> + </xsl:template> + + <xsl:template name="write-row"> + <xsl:param name="globalData" /> + <xsl:param name="allTableColumns" /> + <xsl:param name="maxRowLength" /> + <xsl:param name="tableDataType" /> + + + <xsl:element namespace="{$namespace}" name="{$rowElement}"> + <xsl:call-template name='add-table-row-attributes'> + <xsl:with-param name="globalData" select="$globalData" /> + </xsl:call-template> + + <xsl:if test="$debugEnabled"> + <xsl:message>'tr' element has been added!</xsl:message> + </xsl:if> + + <xsl:apply-templates select="table:table-cell"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="allTableColumns" select="$allTableColumns" /> + <xsl:with-param name="maxRowLength" select="$maxRowLength" /> + <xsl:with-param name="tableDataType" select="$tableDataType" /> + </xsl:apply-templates> + + </xsl:element> + </xsl:template> + + + <!-- **************************** --> + <!-- *** HELPER: table styles *** --> + <!-- **************************** --> + + <xsl:template name="add-style-properties"> + <xsl:param name="globalData" /> + <xsl:param name="allTableColumns" /> + <xsl:param name="node-position" /> + + <xsl:attribute name="class"> + <xsl:value-of select="translate(@table:style-name, '. %()/\+', '')" /> + </xsl:attribute> + </xsl:template> + +</xsl:stylesheet> diff --git a/filter/source/xslt/odf2xhtml/export/common/table_of_content.xsl b/filter/source/xslt/odf2xhtml/export/common/table_of_content.xsl new file mode 100644 index 000000000..f26e2cc0a --- /dev/null +++ b/filter/source/xslt/odf2xhtml/export/common/table_of_content.xsl @@ -0,0 +1,579 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . +--> +<!-- + For further documentation and updates visit http://xml.openoffice.org/odf2xhtml +--> +<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:java="http://xml.apache.org/xslt/java" xmlns:sxg="http://www.jclark.com/xt/java/org.openoffice.xslt.OOoMasterDocument" xmlns:common="http://exslt.org/common" xmlns:xt="http://www.jclark.com/xt" xmlns:xalan="http://xml.apache.org/xalan" exclude-result-prefixes="chart config dc dom dr3d draw fo form math meta number office ooo oooc ooow script style svg table text xforms xlink xsd xsi java sxg xt common xalan"> + + <!-- ****************************** --> + <!-- *** Table of Content *** --> + <!-- ****************************** --> + + <xsl:param name="currentChildContentRef" /> + <xsl:param name="contentTableHeadings" /> + <xsl:param name="contentTableURL" /> + <xsl:template match="text:table-of-content"> + <xsl:param name="globalData"/> + + <xsl:apply-templates> + <xsl:with-param name="globalData" select="$globalData"/> + </xsl:apply-templates> + </xsl:template> + + + <xsl:template match="text:index-body"> + <xsl:param name="globalData"/> + + <xsl:choose> + <xsl:when test="parent::table-of-content and */text:tab[1] or */*/text:tab[1]"> + <xsl:call-template name="createIndexBodyTable"> + <xsl:with-param name="globalData" select="$globalData"/> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:apply-templates> + <xsl:with-param name="globalData" select="$globalData"/> + </xsl:apply-templates> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <xsl:template match="text:index-title" mode="content-table"> + <xsl:param name="globalData"/> + + <xsl:apply-templates> + <xsl:with-param name="globalData" select="$globalData"/> + </xsl:apply-templates> + </xsl:template> + + <xsl:template name="createIndexBodyTable"> + <xsl:param name="globalData"/> + <xsl:variable name="allStyleTabStops-RTF"> + <xsl:element name="style:tab-stops"> + <xsl:call-template name="get-tab-stops"> + <xsl:with-param name="globalData" select="$globalData"/> + <xsl:with-param name="styleName" select="current()/@text:style-name"/> + + <!-- + Currently only the style of text:index-body is recognized, but not of a paragraph child containing the text:tab element! + <xsl:with-param name="styleName" select="descendant-or-self::*/@text:style-name"/> + + The column width needs to be tabstop plus fo:margin-left paragraph-properties + --> + </xsl:call-template> + </xsl:element> + </xsl:variable> + <xsl:element namespace="{$namespace}" name="table"> + + <xsl:attribute name="border">0</xsl:attribute> + <xsl:attribute name="cellspacing">0</xsl:attribute> + <xsl:attribute name="cellpadding">0</xsl:attribute> + <xsl:if test="parent::*/@text:style-name"> + <!-- parent as index:body has no style --> + <xsl:variable name="value" select="$globalData/all-doc-styles/style[@style:name = current()/parent::*/@text:style-name]/*/@style:rel-width"/> + <xsl:if test="$value"> + <xsl:attribute name="width"> + <xsl:value-of select="$value"/> + </xsl:attribute> + </xsl:if> + <xsl:attribute name="class"> + <xsl:value-of select="translate(parent::*/@text:style-name, '.,;: %()[]/\+', '_____________')"/> + </xsl:attribute> + </xsl:if> + + <xsl:element namespace="{$namespace}" name="colgroup"> + <xsl:choose> + <xsl:when test="function-available('common:node-set')"> + <xsl:call-template name="create-col-element"> + <xsl:with-param name="lastNodePosition" select="count(common:node-set($allStyleTabStops-RTF)/style:tab-stops/style:tab-stop)"/> + <xsl:with-param name="allStyleTabStops" select="common:node-set($allStyleTabStops-RTF)"/> + </xsl:call-template> + </xsl:when> + <xsl:when test="function-available('xalan:nodeset')"> + <xsl:call-template name="create-col-element"> + <xsl:with-param name="lastNodePosition" select="count(xalan:nodeset($allStyleTabStops-RTF)/style:tab-stops/style:tab-stop)"/> + <xsl:with-param name="allStyleTabStops" select="xalan:nodeset($allStyleTabStops-RTF)"/> + </xsl:call-template> + </xsl:when> + <xsl:when test="function-available('xt:node-set')"> + <xsl:call-template name="create-col-element"> + <xsl:with-param name="lastNodePosition" select="count(xt:node-set($allStyleTabStops-RTF)/style:tab-stops/style:tab-stop)"/> + <xsl:with-param name="allStyleTabStops" select="xt:node-set($allStyleTabStops-RTF)"/> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:message terminate="yes">ERROR: Function not found: nodeset</xsl:message> + </xsl:otherwise> + </xsl:choose> + </xsl:element> + + <!-- add table data --> + <xsl:choose> + <xsl:when test="function-available('common:node-set')"> + <xsl:apply-templates mode="content-table"> + <xsl:with-param name="globalData" select="$globalData"/> + <xsl:with-param name="allStyleTabStops" select="common:node-set($allStyleTabStops-RTF)"/> + </xsl:apply-templates> + </xsl:when> + <xsl:when test="function-available('xalan:nodeset')"> + <xsl:apply-templates mode="content-table"> + <xsl:with-param name="globalData" select="$globalData"/> + <xsl:with-param name="allStyleTabStops" select="xalan:nodeset($allStyleTabStops-RTF)"/> + </xsl:apply-templates> + </xsl:when> + <xsl:when test="function-available('xt:node-set')"> + <xsl:apply-templates mode="content-table"> + <xsl:with-param name="globalData" select="$globalData"/> + <xsl:with-param name="allStyleTabStops" select="xt:node-set($allStyleTabStops-RTF)"/> + </xsl:apply-templates> + </xsl:when> + <xsl:otherwise> + <xsl:message terminate="yes">ERROR: Function not found: nodeset</xsl:message> + </xsl:otherwise> + </xsl:choose> + + </xsl:element> + </xsl:template> + + + <!-- ************************************************ --> + <!-- *** Create Table for Content Table Paragraph *** --> + <!-- ************************************************ --> + + <!-- Usually the paragraphs in a content-table are ordered by tab-stops, which can not be displayed correctly by XHTML/CSS + Therefore they will be simulated by a table --> + <xsl:template match="text:p" mode="content-table"> + <xsl:param name="globalData"/> + <xsl:param name="allStyleTabStops"/> + + <!-- all elements before the first tabStop --> + <xsl:variable name="testNo-RTF"> + <xsl:apply-templates select="node()" mode="cell-content"/> + </xsl:variable> + + <xsl:choose> + <xsl:when test="function-available('common:node-set')"> + <xsl:variable name="tabNodePositions" select="common:node-set($testNo-RTF)"/> + <xsl:element namespace="{$namespace}" name="tr"> + <xsl:call-template name="create-td-elements"> + <xsl:with-param name="lastNodePosition" select="count($allStyleTabStops/style:tab-stops/style:tab-stop)"/> + <xsl:with-param name="position" select="1"/> + <xsl:with-param name="allStyleTabStops" select="$allStyleTabStops"/> + <xsl:with-param name="tabNodePositions" select="$tabNodePositions"/> + <xsl:with-param name="globalData" select="$globalData"/> + </xsl:call-template> + </xsl:element> + </xsl:when> + <xsl:when test="function-available('xalan:nodeset')"> + <xsl:variable name="tabNodePositions" select="xalan:nodeset($testNo-RTF)"/> + <xsl:element namespace="{$namespace}" name="tr"> + <xsl:call-template name="create-td-elements"> + <xsl:with-param name="lastNodePosition" select="count($allStyleTabStops/style:tab-stops/style:tab-stop)"/> + <xsl:with-param name="position" select="1"/> + <xsl:with-param name="allStyleTabStops" select="$allStyleTabStops"/> + <xsl:with-param name="tabNodePositions" select="$tabNodePositions"/> + <xsl:with-param name="globalData" select="$globalData"/> + </xsl:call-template> + </xsl:element> + </xsl:when> + <xsl:when test="function-available('xt:node-set')"> + <xsl:variable name="tabNodePositions" select="xt:node-set($testNo-RTF)"/> + <xsl:element namespace="{$namespace}" name="tr"> + <xsl:call-template name="create-td-elements"> + <xsl:with-param name="lastNodePosition" select="count($allStyleTabStops/style:tab-stops/style:tab-stop)"/> + <xsl:with-param name="position" select="1"/> + <xsl:with-param name="allStyleTabStops" select="$allStyleTabStops"/> + <xsl:with-param name="tabNodePositions" select="$tabNodePositions"/> + <xsl:with-param name="globalData" select="$globalData"/> + </xsl:call-template> + </xsl:element> + </xsl:when> + <xsl:otherwise> + <xsl:message terminate="yes">ERROR: Function not found: nodeset</xsl:message> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <!-- Gathering all style:tab-stops from a style-hierarchy as siblings --> + <xsl:template name="get-tab-stops"> + <xsl:param name="globalData"/> + <xsl:param name="styleName"/> + <xsl:variable name="tabStyle" select="key('styles', $styleName)"/> + + <xsl:if test="$tabStyle/*/style:tab-stops/style:tab-stop/@style:position"> + <xsl:for-each select="$tabStyle/*/style:tab-stops/style:tab-stop"> + <xsl:copy-of select="."/> + </xsl:for-each> + </xsl:if> + + <xsl:if test="$tabStyle/@style:parent-style-name"> + <xsl:call-template name="get-tab-stops"> + <xsl:with-param name="globalData" select="$globalData"/> + <xsl:with-param name="styleName" select="$tabStyle/@style:parent-style-name"/> + </xsl:call-template> + </xsl:if> + </xsl:template> + + <xsl:template name="create-col-element"> + <xsl:param name="lastNodePosition"/> + <xsl:param name="allStyleTabStops"/> + + <xsl:for-each select="$allStyleTabStops/style:tab-stops/style:tab-stop"> + <xsl:element namespace="{$namespace}" name="col"> + <xsl:attribute name="style"> + <xsl:text>width: </xsl:text> + <xsl:choose> + <xsl:when test="contains(@style:position, 'cm')"> + <xsl:call-template name="create-cell-width"> + <xsl:with-param name="width" select="number(substring-before(@style:position,'cm'))"/> + <xsl:with-param name="unit" select="'cm'"/> + <xsl:with-param name="position" select="position() - 1"/> + <xsl:with-param name="allStyleTabStops" select="$allStyleTabStops"/> + </xsl:call-template> + </xsl:when> + <xsl:when test="contains(@style:position, 'in')"> + <xsl:call-template name="create-cell-width"> + <xsl:with-param name="width" select="number(substring-before(@style:position,'in'))"/> + <xsl:with-param name="unit" select="'in'"/> + <xsl:with-param name="position" select="position() - 1"/> + <xsl:with-param name="allStyleTabStops" select="$allStyleTabStops"/> + </xsl:call-template> + </xsl:when> + <xsl:when test="contains(@style:position, 'ch')"> + <xsl:call-template name="create-cell-width"> + <xsl:with-param name="width" select="number(substring-before(@style:position,'ch'))"/> + <xsl:with-param name="unit" select="'ch'"/> + <xsl:with-param name="position" select="position() - 1"/> + <xsl:with-param name="allStyleTabStops" select="$allStyleTabStops"/> + </xsl:call-template> + </xsl:when> + <xsl:when test="contains(@style:position, 'pt')"> + <xsl:call-template name="create-cell-width"> + <xsl:with-param name="width" select="number(substring-before(@style:position,'pt'))"/> + <xsl:with-param name="unit" select="'pt'"/> + <xsl:with-param name="position" select="position() - 1"/> + <xsl:with-param name="allStyleTabStops" select="$allStyleTabStops"/> + </xsl:call-template> + </xsl:when> + </xsl:choose> + + </xsl:attribute> + </xsl:element> + </xsl:for-each> + + </xsl:template> +<!-- +Scenarios tabstops + +1) style:type of style:tab-stop is 'right' and earlier tabStop is not right + -> Earlier text-nodes and following text-nodes, will be put into an inner table, with two TD first aligned left, with preceding textnodes, the latter aligned right. + +2) style:type is 'right' and earlier tabStop is right + -> following text-nodes, will be put into a right aligned TD + +3) style:type is 'non-right' and earlier tabStop 'non-right' as well + -> put the preceding tab stops into a TD (left aligned is default) + +4) first style:type would have no right preceding tabStop + -> works well with first sceanrios 1 and 3 + +5) last style:type would be a special case, if it would be left aligned, but this won't happen in our case... :D + +Scenarios unmatched: +- text:styleposition 'center' will not be matched in our case (effort for nothing), there will be only 'right' and not 'right' +- If the last tabStop is not from text:styleposition 'right', the length of the last cell is undefined and a document length must be found. + Not happens in our master document case. Also the algorithm below would have to be expanded (cp. scenario 5). + +--> + <xsl:template name="create-td-elements"> + <xsl:param name="globalData"/> + <xsl:param name="lastNodePosition"/> + <xsl:param name="position"/> + <xsl:param name="allStyleTabStops"/> + <xsl:param name="tabNodePositions"/> + + <xsl:variable name="currentTabStop" select="$allStyleTabStops/style:tab-stops/style:tab-stop[$position]"/> + <xsl:variable name="earlierTabStop" select="$allStyleTabStops/style:tab-stops/style:tab-stop[$position - 1]"/> + <xsl:choose> + <xsl:when test="not($currentTabStop/@style:position) and not($earlierTabStop/@style:position)"> + <!-- in case no TAB STOP is being set --> + <xsl:element namespace="{$namespace}" name="td"> + <xsl:element namespace="{$namespace}" name="p"> + <xsl:if test="$position = 1"> + <xsl:attribute name="class"> + <xsl:value-of select="translate(@text:style-name, '.,;: %()[]/\+', '_____________')"/> + </xsl:attribute> + </xsl:if> + <xsl:apply-templates mode="content-table"> + <xsl:with-param name="globalData" select="$globalData"/> + </xsl:apply-templates> + </xsl:element> + </xsl:element> + </xsl:when> + <xsl:otherwise> + <xsl:choose> + <xsl:when test="$currentTabStop/@style:type = 'right'"> + <xsl:choose> + <xsl:when test="$earlierTabStop/@style:type = 'right'"> + <!-- + 2) style:type is 'right' and earlier tabStop is right + -> following text-nodes, will be put into a right aligned TD --> + <xsl:element namespace="{$namespace}" name="td"> + <xsl:attribute name="style"> + <xsl:text>align: right</xsl:text> + </xsl:attribute> + <xsl:element namespace="{$namespace}" name="p"> + <xsl:if test="$position = 1"> + <xsl:attribute name="class"> + <xsl:value-of select="translate(@text:style-name, '.,;: %()[]/\+', '_____________')"/> + </xsl:attribute> + </xsl:if> + <xsl:call-template name="grab-cell-content-before-tab-stop"> + <xsl:with-param name="globalData" select="$globalData"/> + <xsl:with-param name="endingTabStopPosition" select="$position + 1"/> + <xsl:with-param name="lastNodePosition" select="$lastNodePosition"/> + <xsl:with-param name="tabNodePositions" select="$tabNodePositions"/> + </xsl:call-template> + </xsl:element> + </xsl:element> + </xsl:when> + <xsl:otherwise> + <xsl:element namespace="{$namespace}" name="td"> + <xsl:element namespace="{$namespace}" name="p"> + <xsl:if test="$position = 1"> + <xsl:attribute name="class"> + <xsl:value-of select="translate(@text:style-name, '.,;: %()[]/\+', '_____________')"/> + </xsl:attribute> + </xsl:if> + <xsl:call-template name="grab-cell-content-before-tab-stop"> + <xsl:with-param name="globalData" select="$globalData"/> + <xsl:with-param name="endingTabStopPosition" select="$position"/> + <xsl:with-param name="lastNodePosition" select="$lastNodePosition"/> + <xsl:with-param name="tabNodePositions" select="$tabNodePositions"/> + </xsl:call-template> + </xsl:element> + </xsl:element> + </xsl:otherwise> + </xsl:choose> + </xsl:when> + <xsl:otherwise> + <xsl:choose> + <xsl:when test="$earlierTabStop/@style:type = 'right'"></xsl:when> + <xsl:otherwise> + <!-- + 3) style:type is 'non-right' and earlier tabStop 'non-right' as well + -> put the preceding tab stops into a TD (left aligned is default) --> + <xsl:element namespace="{$namespace}" name="p"> + <xsl:if test="$position = 1"> + <xsl:attribute name="class"> + <xsl:value-of select="translate(@text:style-name, '.,;: %()[]/\+', '_____________')"/> + </xsl:attribute> + </xsl:if> + <xsl:element namespace="{$namespace}" name="td"> + <xsl:call-template name="grab-cell-content-before-tab-stop"> + <xsl:with-param name="globalData" select="$globalData"/> + <xsl:with-param name="endingTabStopPosition" select="$position"/> + <xsl:with-param name="lastNodePosition" select="$lastNodePosition"/> + <xsl:with-param name="tabNodePositions" select="$tabNodePositions"/> + </xsl:call-template> + </xsl:element> + </xsl:element> + </xsl:otherwise> + </xsl:choose> + </xsl:otherwise> + </xsl:choose> + + <xsl:if test="$position != $lastNodePosition"> + <xsl:call-template name="create-td-elements"> + <xsl:with-param name="globalData" select="$globalData"/> + <xsl:with-param name="lastNodePosition" select="$lastNodePosition"/> + <xsl:with-param name="position" select="$position + 1"/> + <xsl:with-param name="allStyleTabStops" select="$allStyleTabStops"/> + <xsl:with-param name="tabNodePositions" select="$tabNodePositions"/> + </xsl:call-template> + </xsl:if> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <xsl:template name="grab-cell-content-before-tab-stop"> + <xsl:param name="globalData"/> + <xsl:param name="endingTabStopPosition"/> + <xsl:param name="tabNodePositions"/> + <xsl:param name="lastNodePosition"/> + + <xsl:choose> + <xsl:when test="$endingTabStopPosition = 1"> + <xsl:apply-templates mode="content-table" select="node()[position() < $tabNodePositions/tab-stop-node-position[$endingTabStopPosition]]"> + <xsl:with-param name="globalData" select="$globalData"/> + </xsl:apply-templates> + </xsl:when> + <xsl:when test="$endingTabStopPosition > $lastNodePosition"> + <xsl:apply-templates mode="content-table" select="node()[position() > $tabNodePositions/tab-stop-node-position[$endingTabStopPosition - 1]]"> + <xsl:with-param name="globalData" select="$globalData"/> + </xsl:apply-templates> + </xsl:when> + <xsl:otherwise> + <xsl:variable name="nodesOfNextColumn" select="node()[position() < $tabNodePositions/tab-stop-node-position[$endingTabStopPosition]][position() > $tabNodePositions/tab-stop-node-position[$endingTabStopPosition - 1]]"/> + <xsl:choose> + <xsl:when test="$nodesOfNextColumn != ''"> + <xsl:apply-templates mode="content-table" select="$nodesOfNextColumn"> + <xsl:with-param name="globalData" select="$globalData"/> + </xsl:apply-templates> + </xsl:when> + <xsl:otherwise> + <xsl:apply-templates mode="content-table"> + <xsl:with-param name="globalData" select="$globalData"/> + </xsl:apply-templates> + </xsl:otherwise> + </xsl:choose> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <!-- As the span width will be mapped to column width, the preceding span widths have to be subtracted --> + <xsl:template name="create-cell-width"> + <xsl:param name="width"/> + <xsl:param name="unit"/> + <xsl:param name="position"/> + <xsl:param name="allStyleTabStops"/> + + <xsl:choose> + <!-- beyond second width --> + <xsl:when test="$position > 1"> + <xsl:call-template name="create-cell-width"> + <xsl:with-param name="width" select="$width - number(substring-before($allStyleTabStops/style:tab-stops/style:tab-stop[$position]/@style:position,$unit))"/> + <xsl:with-param name="unit" select="$unit"/> + <xsl:with-param name="position" select="$position - 1"/> + <xsl:with-param name="allStyleTabStops" select="$allStyleTabStops"/> + </xsl:call-template> + </xsl:when> + <!-- second width --> + <xsl:when test="$position = 1"> + <xsl:value-of select="concat($width - number(substring-before($allStyleTabStops/style:tab-stops/style:tab-stop[$position]/@style:position,$unit)), $unit)"/> + </xsl:when> + <!-- first width --> + <xsl:otherwise> + <xsl:value-of select="concat($width, $unit)"/> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + + <!-- ************************************** --> + <!-- CREATION OF A CONTENT TABLE LINK --> + <!-- ************************************** --> + + <xsl:key name="bookmark" match="text:bookmark | text:bookmark-start" use="@text:name"/> + + <!-- content table link --> + <xsl:template match="text:a" mode="content-table"> + <xsl:param name="globalData"/> + + <xsl:variable name="name" select="substring(@xlink:href,2)"/> + + <xsl:variable name="text"> + <xsl:choose> + <!-- heuristic assumption that first in a content table row, there is numbering (if at all) and then the text, + furthermore that a tab will separate the to be neglected page number --> + <xsl:when test="text:tab"> + <xsl:call-template name="write-text-without-line-numbers"> + <xsl:with-param name="textCount" select="count(text())"/> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="text()"/> + </xsl:otherwise> + </xsl:choose> + </xsl:variable> + + <!-- REFERENCE HANDLING - HREF --> + <xsl:element namespace="{$namespace}" name="a"> + <xsl:attribute name="href"> + <xsl:text>#</xsl:text> + <xsl:choose> + <xsl:when test="key('bookmark',$name)"> + <xsl:value-of select="$name"/> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select='concat("a_", translate(normalize-space($text), "
&<>.,;: %()[]/\+", "_______________________________"))'/> + </xsl:otherwise> + </xsl:choose> + </xsl:attribute> + <xsl:value-of select="$text"/> + </xsl:element> + </xsl:template> + + <!-- Heuristic: write out text separated by elements, leaving the last number out (mostly text number) --> + <xsl:template name="write-text-without-line-numbers"> + <xsl:param name="textCount"/> + <xsl:param name="textNodeNumber" select="1"/> + + <xsl:choose> + <xsl:when test="$textCount > $textNodeNumber"> + <xsl:value-of select="text()[$textNodeNumber]"/> + <xsl:call-template name="write-text-without-line-numbers"> + <xsl:with-param name="textCount" select="$textCount"/> + <xsl:with-param name="textNodeNumber" select="$textNodeNumber + 1"/> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:if test="not(number(text()[$textNodeNumber]) > -1)"> + <xsl:value-of select="text()[$textNodeNumber]"/> + </xsl:if> + </xsl:otherwise> + </xsl:choose> + + </xsl:template> + + <xsl:template match="text:s" mode="content-table"> + <xsl:call-template name="write-breakable-whitespace"> + <xsl:with-param name="whitespaces" select="@text:c"/> + </xsl:call-template> + </xsl:template> + + <!-- ******************** --> + <!-- *** Common Rules *** --> + <!-- ******************** --> + + <xsl:template match="*" mode="content-table"> + <xsl:param name="globalData"/> + + <xsl:apply-templates select="."> + <xsl:with-param name="globalData" select="$globalData"/> + </xsl:apply-templates> + </xsl:template> + + <xsl:template match="*" mode="cell-content"> + <xsl:if test="name() = 'text:tab' or *[name() = 'text:tab']"> + <xsl:element name="tab-stop-node-position" namespace=""> + <xsl:value-of select="position()"/> + </xsl:element> + </xsl:if> + </xsl:template> + + <xsl:template match="text()" mode="content-table"> + <!-- Heuristic to remove page numbers (useless in HTML) in the content table + usually after a tab --> + <xsl:if test="name(preceding-sibling::*[1]) != 'text:tab' and not(number() > -1)"> + <xsl:value-of select="."/> + </xsl:if> + </xsl:template> + +</xsl:stylesheet> diff --git a/filter/source/xslt/odf2xhtml/export/xhtml/body.xsl b/filter/source/xslt/odf2xhtml/export/xhtml/body.xsl new file mode 100644 index 000000000..430b834b3 --- /dev/null +++ b/filter/source/xslt/odf2xhtml/export/xhtml/body.xsl @@ -0,0 +1,3022 @@ +<?xml version="1.0" encoding="UTF-8"?> <!-- -*- fill-column: 130; nxml-child-indent: 4; tab-width: 4; indent-tabs-mode: nil -*- --> +<!-- + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . +--> +<!-- + For further documentation and updates visit http://xml.openoffice.org/odf2xhtml +--> +<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xt="http://www.jclark.com/xt" xmlns:common="http://exslt.org/common" xmlns:xalan="http://xml.apache.org/xalan" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" exclude-result-prefixes="chart config dc dom dr3d draw fo form loext math meta number office ooo oooc ooow script style svg table text xforms xlink xsd xsi xt common xalan" xmlns="http://www.w3.org/1999/xhtml"> + + + <!--+++++ INCLUDED XSL MODULES +++++--> + + <!-- helper collection, to convert measures (e.g. inch to pixel using DPI (dots per inch) parameter)--> + <xsl:import href="../../common/measure_conversion.xsl"/> + + <!-- common office body element handling --> + <xsl:import href="../common/body.xsl"/> + + <!-- common table handling --> + <xsl:import href="../common/table/table.xsl"/> + + <!-- xhtml table handling --> + <xsl:include href="table.xsl"/> + + <!-- Useful in case of 'style:map', conditional formatting, where a style references to another --> + <xsl:key name="styles" match="/*/office:styles/style:style | /*/office:automatic-styles/style:style" use="@style:name"/> + + + <!-- ************ --> + <!-- *** body *** --> + <!-- ************ --> + + <xsl:key match="style:style/@style:master-page-name" name="masterPage" use="'count'"/> + <xsl:key match="style:master-page" name="masterPageElements" use="@style:name"/> + <xsl:key match="style:page-layout" name="pageLayoutElements" use="@style:name"/> + <xsl:key name="writingModeStyles" match="/*/office:styles/style:style/style:paragraph-properties/@style:writing-mode | /*/office:automatic-styles/style:style/style:paragraph-properties/@style:writing-mode" use="'test'"/> + <xsl:template name="create-body"> + <xsl:param name="globalData"/> + <xsl:call-template name="create-body.collect-page-properties"> + <xsl:with-param name="globalData" select="$globalData"/> + </xsl:call-template> + </xsl:template> + + <xsl:template name="create-body.collect-page-properties"> + <xsl:param name="globalData"/> + + <!-- approximation to find the correct master page style (with page dimensions) --> + <xsl:variable name="masterPageNames"> + <!-- Loop over every style:style containing a @style:master-page-name attribute --> + <xsl:for-each select="key('masterPage','count')"> + <!-- Check if this style is being used in the body --> + <xsl:if test="key('elementUsingStyle', ../@style:name)"> + <!-- Check every master-page-name if it is not empty and return as ';' separated list --> + <xsl:if test="string-length(../@style:master-page-name) > 0"> + <xsl:value-of select="../@style:master-page-name"/>; + </xsl:if> + </xsl:if> + </xsl:for-each> + </xsl:variable> + + <!-- Take the first of the masterpage list and get the according style:master-page element and find the @style:page-layout-name --> + <xsl:variable name="pageLayoutName" select="key('masterPageElements', substring-before($masterPageNames,';'))/@style:page-layout-name"/> + <xsl:variable name="pagePropertiesRTF"> + <xsl:choose> + <xsl:when test="not($pageLayoutName) or $pageLayoutName = ''"> + <xsl:copy-of select="$globalData/styles-file/*/office:automatic-styles/style:page-layout[1]/style:page-layout-properties"/> + </xsl:when> + <xsl:otherwise> + <!-- Find the according style:page-layout and store the properties in a variable --> + <xsl:copy-of select="key('pageLayoutElements', $pageLayoutName)/style:page-layout-properties"/> + </xsl:otherwise> + </xsl:choose> + </xsl:variable> + + <xsl:choose> + <xsl:when test="function-available('common:node-set')"> + <xsl:call-template name="create-body.create"> + <xsl:with-param name="globalData" select="common:node-set($globalData)"/> + <xsl:with-param name="pageProperties" select="common:node-set($pagePropertiesRTF)"/> + </xsl:call-template> + </xsl:when> + <xsl:when test="function-available('xalan:nodeset')"> + <xsl:call-template name="create-body.create"> + <xsl:with-param name="globalData" select="xalan:nodeset($globalData)"/> + <xsl:with-param name="pageProperties" select="xalan:nodeset($pagePropertiesRTF)"/> + </xsl:call-template> + </xsl:when> + <xsl:when test="function-available('xt:node-set')"> + <xsl:call-template name="create-body.create"> + <xsl:with-param name="globalData" select="xt:node-set($globalData)"/> + <xsl:with-param name="pageProperties" select="xt:node-set($pagePropertiesRTF)"/> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:message terminate="yes">The required node-set function was not found!</xsl:message> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <xsl:template name="create-body.create"> + <xsl:param name="globalData"/> + <xsl:param name="pageProperties"/> + + <xsl:element name="body"> + <!-- direction of text flow --> + <xsl:variable name="writingMode" select="$pageProperties/style:page-layout-properties/@style:writing-mode"/> + <xsl:choose> + <xsl:when test="$writingMode"> + <xsl:choose> + <xsl:when test="contains($writingMode, 'lr')"> + <xsl:attribute name="dir">ltr</xsl:attribute> + </xsl:when> + <xsl:when test="contains($writingMode, 'rl')"> + <xsl:attribute name="dir">rtl</xsl:attribute> + </xsl:when> + </xsl:choose> + </xsl:when> + <xsl:otherwise> + <!-- As CSS writing-mode is not implemented by all browsers, a heuristic is done --> + <xsl:variable name="writingModeTest" select="key('writingModeStyles', 'test')"/> + <xsl:if test="contains($writingModeTest, 'rl')"> + <xsl:attribute name="dir">rtl</xsl:attribute> + </xsl:if> + </xsl:otherwise> + </xsl:choose> + <!-- adapt page size --> + <xsl:variable name="pageWidth" select="$pageProperties/style:page-layout-properties/@fo:page-width"/> + + <!-- multiple backgroundimages for different page styles (never used in html) --> + <xsl:variable name="backgroundImage" select="$pageProperties/style:page-layout-properties/style:background-image"/> + <!-- page margins & background image --> + <xsl:if test="$pageWidth or $pageProperties/style:page-layout-properties/@fo:* or $backgroundImage/@xlink:href"> + <xsl:attribute name="style"> + <xsl:if test="$pageWidth"> + <xsl:text>max-width:</xsl:text> + <xsl:value-of select="$pageWidth"/> + <xsl:text>;</xsl:text> + </xsl:if> + <xsl:if test="$pageProperties/style:page-layout-properties/@fo:* or $backgroundImage/@xlink:href"> + <xsl:apply-templates select="$pageProperties/style:page-layout-properties/@fo:*"/> + <xsl:if test="$backgroundImage/@xlink:href"> + <xsl:text>background-image:url(</xsl:text> + <xsl:call-template name="create-href"> + <xsl:with-param name="href" select="$backgroundImage/@xlink:href"/> + </xsl:call-template> + <xsl:text>);</xsl:text> + + <xsl:if test="$backgroundImage/@style:repeat"> + <xsl:choose> + <xsl:when test="$backgroundImage/@style:repeat = 'no-repeat'"> + <xsl:text>background-repeat:no-repeat;</xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:text>background-repeat:repeat;</xsl:text> + </xsl:otherwise> + </xsl:choose> + </xsl:if> + <xsl:if test="$backgroundImage/@style:position"> + <xsl:text>background-position:</xsl:text> + <xsl:value-of select="$backgroundImage/@style:position"/> + <xsl:text>;</xsl:text> + </xsl:if> + </xsl:if> + </xsl:if> + </xsl:attribute> + </xsl:if> + <!-- processing the content of the OpenDocument content file --> + <xsl:apply-templates select="/*/office:body/*"> + <xsl:with-param name="globalData" select="$globalData"/> + </xsl:apply-templates> + + </xsl:element> + </xsl:template> + + <!-- processing the content of the OpenDocument content file --> + <xsl:template match="office:body/*"> + <xsl:param name="globalData"/> + + <!-- not using of 'apply-styles-and-content' as the content table information might have been added to 'globalData' variable --> + <xsl:apply-templates select="@text:style-name | @draw:style-name | @draw:text-style-name | @table:style-name"><!-- | @presentation:style-name --> + <xsl:with-param name="globalData" select="$globalData"/> + </xsl:apply-templates> + + <xsl:apply-templates> + <xsl:with-param name="globalData" select="$globalData"/> + </xsl:apply-templates> + + <!-- writing the footer- and endnotes beyond the body --> + <xsl:call-template name="write-text-nodes"> + <xsl:with-param name="globalData" select="$globalData"/> + </xsl:call-template> + </xsl:template> + + <!-- ******************************* --> + <!-- *** User Field Declarations *** --> + <!-- ******************************* --> + + <xsl:template match="text:user-field-get | text:user-field-input"> + <xsl:param name="globalData"/> + + <xsl:value-of select="."/> + </xsl:template> + + <xsl:template match="text:conditional-text"> + <xsl:param name="globalData"/> + + <xsl:value-of select="."/> + </xsl:template> + + <!-- ODF text fields --> + <xsl:template match="text:author-initials | text:author-name | text:chapter | text:character-count | text:creation-date | text:creation-time | text:creator | text:date | text:description | text:editing-cycles | text:editing-duration | text:file-name | text:image-count | text:initial-creator | text:keywords | text:modification-date | text:modification-time | text:object-count | text:page-continuation | text:page-count | text:page-number | text:paragraph-count | text:print-date | text:print-time | text:printed-by | text:sender-city | text:sender-company | text:sender-country | text:sender-email | text:sender-fax | text:sender-firstname | text:sender-initials | text:sender-lastname | text:sender-phone-private | text:sender-phone-work | text:sender-position | text:sender-postal-code | text:sender-state-or-province | text:sender-street | text:sender-title | text:sheet-name | text:subject | text:table-count | text:time | text:title | text:user-defined | text:word-count"> + <xsl:param name="globalData"/> + + <xsl:element name="span"> + <xsl:attribute name="title"> + <xsl:value-of select="local-name()"/> + </xsl:attribute> + <xsl:apply-templates> + <xsl:with-param name="globalData" select="$globalData"/> + </xsl:apply-templates> + </xsl:element> + </xsl:template> + + + + <!-- *************** --> + <!-- *** Textbox *** --> + <!-- *************** --> + + <xsl:template match="draw:text-box"> + <xsl:param name="globalData"/> + + <xsl:comment>Next 'div' was a 'draw:text-box'.</xsl:comment> + <xsl:element name="div"> + <xsl:variable name="dimension"> + <xsl:apply-templates select="@fo:min-width"/> + <xsl:apply-templates select="@fo:max-width"/> + <xsl:apply-templates select="@fo:min-height"/> + <xsl:apply-templates select="@fo:max-height"/> + </xsl:variable> + <xsl:if test="$dimension"> + <xsl:attribute name="style"> + <xsl:value-of select="$dimension"/> + </xsl:attribute> + </xsl:if> + <xsl:apply-templates select="@draw:name"> + <xsl:with-param name="globalData" select="$globalData"/> + </xsl:apply-templates> + + <xsl:apply-templates select="node()"> + <xsl:with-param name="globalData" select="$globalData"/> + </xsl:apply-templates> + </xsl:element> + </xsl:template> + + <xsl:template match="@fo:min-width"> + <xsl:text>min-width:</xsl:text> + <xsl:value-of select="."/> + <xsl:text>;</xsl:text> + </xsl:template> + <xsl:template match="@fo:max-width"> + <xsl:text>max-width:</xsl:text> + <xsl:value-of select="."/> + <xsl:text>;</xsl:text> + </xsl:template> + <xsl:template match="@fo:min-height"> + <xsl:text>min-height:</xsl:text> + <xsl:value-of select="."/> + <xsl:text>;</xsl:text> + </xsl:template> + <xsl:template match="@fo:max-height"> + <xsl:text>max-height:</xsl:text> + <xsl:value-of select="."/> + <xsl:text>;</xsl:text> + </xsl:template> + + + <!-- inline style helper for the 'div' boxes --> + <xsl:template name="svg:height"> + <xsl:text>height:</xsl:text> + <xsl:choose> + <!-- changing the distance measure: inch to in --> + <xsl:when test="contains(@svg:height, 'inch')"> + <xsl:value-of select="substring-before(@svg:height, 'ch')"/> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="@svg:height"/> + </xsl:otherwise> + </xsl:choose> + <xsl:text>;</xsl:text> + </xsl:template> + + <!-- inline style helper for the 'div' boxes --> + <xsl:template name="svg:width"> + <xsl:text>width:</xsl:text> + <xsl:choose> + <!-- changing the distance measure: inch to in --> + <xsl:when test="contains(@svg:width, 'inch')"> + <xsl:value-of select="substring-before(@svg:width, 'ch')"/> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="@svg:width"/> + </xsl:otherwise> + </xsl:choose> + <xsl:text>;</xsl:text> + </xsl:template> + + + + <!-- ****************** --> + <!-- *** Paragraphs *** --> + <!-- ****************** --> + + <xsl:template match="text:p | draw:page"> + <xsl:param name="globalData"/> + <!-- The footnote symbol is the prefix for a footnote in the footer --> + <xsl:param name="footnotePrefix"/> + <!-- 1) In ODF sometimes the following children are nested + <text:p> + <draw:frame> + <draw:text-box> + <text:p> + Which results in a paragraphs (the last text:p) having a paragraph as its ancestor. + In HTML a 'p' can only have inline documents (no other 'p' as children'), + a 'div' will be given for the ancestors instead. + 2) ODF images are embedded in a paragraph, but CSS is not able to express a horizontal alignment for an HTML image (text:align is only valid for block elements). + A surrounding 'div' element taking over the image style solves that problem, but the div is invalid as child of a paragraph + Therefore the paragraph has to be exchanged with a HTML div element + --> + <!-- TODO page alignment fix - PART1 --> + <xsl:variable name="childText"><xsl:apply-templates mode="getAllTextChildren"/></xsl:variable> + <xsl:choose> + <xsl:when test="name() = 'text:p' and not(*) and (normalize-space($childText) = '')"> + <!-- WorkAround: Test if the empty paragraph was added after an image, which OOO often does --> + <xsl:variable name="isFollowingImage"> + <xsl:call-template name="follows-empty-paragraphs-and-image"> + <xsl:with-param name="precedingElement" select="preceding-sibling::node()[1]"/> + </xsl:call-template> + </xsl:variable> + <xsl:if test="$isFollowingImage = 'no'"> + <xsl:call-template name="create-paragraph"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="footnotePrefix" select="$footnotePrefix" /> + </xsl:call-template> + </xsl:if> + + </xsl:when> + <xsl:when test="draw:frame and ((normalize-space($childText) != '') or (((count(*) - count(text:soft-page-break)) > 1)))"> + <!-- If there is a 'draw:frame' child with text (not being whitespace alone) and more than the draw:frame alone and + not the draw:frame and a soft-page-break alone (which is quite often) --> + + <!-- If there is a frame within the text:p or draw:page, its siblings are surrounded as well by a div and are floating (CSS float) --> + <!-- But it makes no sense to create floating if the frame is alone or only together with a soft-page-break not usable for HTML --> + <!-- The paragraph is written as DIV as there might be nested paragraphs (see above choose block) --> + <xsl:choose> + <xsl:when test="name() = 'text:p'"> + <xsl:comment>Next 'div' was a 'text:p'.</xsl:comment> + </xsl:when> + <xsl:otherwise> + <xsl:comment>Next 'div' was a 'draw:page'.</xsl:comment> + </xsl:otherwise> + </xsl:choose> + <xsl:element name="div"> + <xsl:apply-templates select="@*"> + <xsl:with-param name="globalData" select="$globalData"/> + </xsl:apply-templates> + <!-- the footnote symbol is the prefix for a footnote in the footer --> + <xsl:copy-of select="$footnotePrefix"/> + <!-- deal with none draw:frame ahead of the <draw:frame> --> + <xsl:if test="name(node()[1]) != 'draw:frame'"> + <xsl:apply-templates select="node()[1]" mode="frameFloating"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="previousFrameWidths" select="0"/> + <xsl:with-param name="previousFrameHeights" select="0"/> + <xsl:with-param name="leftPosition" select="0" /> + <xsl:with-param name="stopAtFirstFrame" select="true()" /> + <!-- TODO for me (Svante) - Not used, uncertain for now... + <xsl:with-param name="pageMarginLeft"> + <xsl:call-template name="getPageMarginLeft"/> + </xsl:with-param>--> + </xsl:apply-templates> + </xsl:if> + <!-- start floating of frames (each take care of its siblings till next draw:frame) --> + <xsl:apply-templates select="draw:frame" mode="frameFloating"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="previousFrameWidths" select="0"/> + <xsl:with-param name="previousFrameHeights" select="0"/> + <xsl:with-param name="leftPosition" select="0"/> + + <!-- TODO for me (Svante) - Not used, uncertain for now... + <xsl:with-param name="pageMarginLeft"> + <xsl:call-template name="getPageMarginLeft"/> + </xsl:with-param>--> + </xsl:apply-templates> + </xsl:element> + <!-- after the last draw:frame sibling the CSS float is disabled +   is an unbreakable whitespace to give content to the element and force a browser not to ignore the element --> + <div style="clear:both; line-height:0; width:0; height:0; margin:0; padding:0;"> </div> + </xsl:when> + <xsl:when test="text:tab and not(ancestor::text:index-body)"> + <!-- If there is a tabulator (ie. text:tab) within a paragraph, a heuristic for ODF tabulators creates a + span for every text:tab embracing the following text nodes aligning them according to the tabulator. + A line break or another text:tab starts a new text:span, line break even the tab counter for the line. + --> + <xsl:element name="p"> + <xsl:apply-templates select="@*"> + <xsl:with-param name="globalData" select="$globalData" /> + </xsl:apply-templates> + <!-- start with first child of the paragraph --> + <xsl:variable name="firstChildNode" select="node()[1]" /> + <xsl:apply-templates select="$firstChildNode" mode="tabHandling"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="tabStops" select="$globalData/all-doc-styles/style[@style:name = current()/@text:style-name]/*/style:tab-stops"/> + <xsl:with-param name="parentMarginLeft"> + <!-- Styles of first paragraph in list item, including ancestor styles (inheritance) --> + <xsl:variable name="paragraphName" select="@text:style-name" /> + <xsl:variable name="imageParagraphStyle" select="$globalData/all-styles/style[@style:name = $paragraphName]/final-properties"/> + <!-- Only the left margin of the first paragraph of a list item will be added to the margin of the complete list (all levels)--> +<!-- TODO: left-margin in order with bidirectional --> + <xsl:choose> + <xsl:when test="contains($imageParagraphStyle, 'margin-left:')"> + <xsl:call-template name="convert2cm"> + <xsl:with-param name="value" select="normalize-space(substring-before(substring-after($imageParagraphStyle, 'margin-left:'), ';'))"/> + </xsl:call-template> + </xsl:when> + <xsl:otherwise>0</xsl:otherwise> + </xsl:choose> + </xsl:with-param> + <xsl:with-param name="pageMarginLeft"> + <xsl:call-template name="getPageMarginLeft"/> + </xsl:with-param> + </xsl:apply-templates> + </xsl:element> + </xsl:when> + <xsl:when test="text:tab and text:a and ancestor::text:index-body"> + <xsl:element name="p"> + <xsl:apply-templates select="attribute::* | child::text:a"> + <xsl:with-param name="globalData" select="$globalData" /> + </xsl:apply-templates> + </xsl:element> + </xsl:when> + <xsl:otherwise> + <xsl:choose> + <!-- !!Check if paragraph is empty!! + OOo writes out empty paragraphs layouted behind an image (= draw:image within draw:frame) + those have to be neglected in HTML --> + <xsl:when test="name() = 'text:p' and not($childText) and not(*)"> + <xsl:variable name="isFollowingImage"> + <xsl:call-template name="follows-empty-paragraphs-and-image"> + <xsl:with-param name="precedingElement" select="preceding-sibling::node()[1]"/> + </xsl:call-template> + </xsl:variable> + <xsl:if test="$isFollowingImage = 'no'"> + <xsl:call-template name="create-paragraph"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="footnotePrefix" select="$footnotePrefix" /> + </xsl:call-template> + </xsl:if> + </xsl:when> + <xsl:otherwise> + <xsl:call-template name="create-paragraph"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="footnotePrefix" select="$footnotePrefix" /> + </xsl:call-template> + </xsl:otherwise> + </xsl:choose> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <!-- Return the text --> + <xsl:template match="text()" mode="getAllTextChildren"> + <xsl:value-of select="."/> + </xsl:template> + + <!-- A span will be created for every text:tab embracing the following text nodes. + A line break or another text:tab starts a new text:span --> + <xsl:template match="* | text()" mode="tabHandling"> + <xsl:param name="globalData"/> + <xsl:param name="tabStops"/> + <!-- there can be multiple tabs in one line, tabNo guesses the one to apply. By default the first i.e. "1" --> + <xsl:param name="tabCount" select="0"/> + <xsl:param name="parentMarginLeft" /> + <xsl:param name="pageMarginLeft" /> + +<!-- TODO: EXCHANGE FOLLOWING SIBLING BY VARIABLE --> + <xsl:variable name="followingSiblingNode" select="following-sibling::node()[1]"/> + + + <!-- + Every tabulator indents its following content, encapuslated in a span + element. + + This template have two modes: + + 1) Before the first tabulator it will match as usually paragraph content + to HTML. + 2) After the first paragraph it will always triggers two recursions. + One embraces the following content of a paragraph element into a span. + (tabContentHandling) + The other calls this template and will now ignore anything else than + TAB and LINE-BREAK. + + + The tabulators and linebreaks are being iterated, one by one to keep track of the tab number + --> + + + <xsl:choose> + <xsl:when test="name() = 'text:tab'"> + <!-- every frame sibling have to be encapsulated within a div with left indent --> + <xsl:element name="span"> + <xsl:choose> + <xsl:when test="count($tabStops/style:tab-stop) > 0 and count($tabStops/style:tab-stop) < 3"> + <!-- only allow the heuristic when the style has less than 3 TABS --> + <!-- ignore heuristics if no TABS are defined --> + <xsl:attribute name="style"> + <xsl:call-template name="createTabIndent"> + <xsl:with-param name="globalData" select="$globalData"/> + <xsl:with-param name="tabStops" select="$tabStops"/> + <xsl:with-param name="tabCount" select="$tabCount + 1"/> + <xsl:with-param name="parentMarginLeft" select="$parentMarginLeft"/> + <xsl:with-param name="pageMarginLeft" select="$pageMarginLeft"/> + </xsl:call-template> + </xsl:attribute> + </xsl:when> + <xsl:otherwise> + <!-- if there are more than 3 TABS in the style, create a none-breakable-space as whitespace --> + <xsl:text> </xsl:text> + </xsl:otherwise> + </xsl:choose> + <xsl:apply-templates select="following-sibling::node()[1]" mode="tabContentHandling"> + <xsl:with-param name="globalData" select="$globalData"/> + </xsl:apply-templates> + </xsl:element> + <xsl:apply-templates select="following-sibling::node()[1]" mode="tabHandling"> + <xsl:with-param name="globalData" select="$globalData"/> + <xsl:with-param name="tabStops" select="$tabStops"/> + <xsl:with-param name="tabCount" select="$tabCount + 1"/> + <xsl:with-param name="parentMarginLeft" select="$parentMarginLeft"/> + <xsl:with-param name="pageMarginLeft" select="$pageMarginLeft"/> + </xsl:apply-templates> + </xsl:when> + <xsl:when test="name() = 'text:line-break'"> + <!-- A line-break resets the tabCount to '0' --> + <br/> + <xsl:apply-templates select="following-sibling::node()[1]" mode="tabHandling"> + <xsl:with-param name="globalData" select="$globalData"/> + <xsl:with-param name="tabStops" select="$tabStops"/> + <xsl:with-param name="tabCount" select="0"/> + <xsl:with-param name="parentMarginLeft" select="$parentMarginLeft"/> + <xsl:with-param name="pageMarginLeft" select="$pageMarginLeft"/> + </xsl:apply-templates> + </xsl:when> + <xsl:otherwise> + <!-- only before the first tab all content is written out --> + <xsl:if test="$tabCount = 0"> + <xsl:apply-templates select="."> + <xsl:with-param name="globalData" select="$globalData"/> + </xsl:apply-templates> + </xsl:if> + <xsl:apply-templates select="following-sibling::node()[1]" mode="tabHandling"> + <xsl:with-param name="globalData" select="$globalData"/> + <xsl:with-param name="tabStops" select="$tabStops"/> + <xsl:with-param name="tabCount" select="$tabCount"/> + <xsl:with-param name="parentMarginLeft" select="$parentMarginLeft"/> + <xsl:with-param name="pageMarginLeft" select="$pageMarginLeft"/> + </xsl:apply-templates> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <!-- + This recursion creates the content of a tab (i.e. following siblings + till next TAB or LINE BREAK) and ends with the next + TAB, LINE-BREAK or with the end of the paragraph. + --> + <xsl:template match="* | text()" mode="tabContentHandling"> + <xsl:param name="globalData"/> + + <xsl:if test="(name() != 'text:tab') and (name() != 'text:line-break')"> + <!-- Write out content --> + <xsl:apply-templates select="."> + <xsl:with-param name="globalData" select="$globalData"/> + </xsl:apply-templates> + <!-- Apply for the next node --> + <xsl:apply-templates select="following-sibling::node()[1]" mode="tabContentHandling"> + <xsl:with-param name="globalData" select="$globalData"/> + </xsl:apply-templates> + </xsl:if> + </xsl:template> + + <xsl:template name="createTabIndent"> + <xsl:param name="globalData"/> + <xsl:param name="tabStops"/> + <xsl:param name="tabCount"/> + <xsl:param name="parentMarginLeft" /> + <xsl:param name="pageMarginLeft" /> + + <xsl:text>position:absolute;left:</xsl:text> + <xsl:variable name="tabPosition"> + <xsl:call-template name="convert2cm"> + <xsl:with-param name="value" select="$tabStops/style:tab-stop[$tabCount]/@style:position"/> + </xsl:call-template> + </xsl:variable> + <xsl:variable name="tabIndent"> + <xsl:choose> + <xsl:when test="$tabStops/style:tab-stop[$tabCount]/@style:type = 'center'"> + <!-- in case of style:type 'center' the text is even before the tab stop, + centered around the beginning. As I see currently no way in mapping this, + therefore I do some HEURISTIC (minus -2.5cm) --> + <xsl:value-of select="$tabPosition + $parentMarginLeft + $pageMarginLeft - 2.5"/> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="$tabPosition + $parentMarginLeft + $pageMarginLeft"/> + </xsl:otherwise> + </xsl:choose> + </xsl:variable> + <!--<xsl:message>TAB: tabCount= + <xsl:value-of select="$tabCount"/>, tabPosition= + <xsl:value-of select="$tabPosition"/>, tabIndent= + <xsl:value-of select="$tabIndent"/> + </xsl:message>--> + <xsl:choose> + <xsl:when test="$tabIndent='NaN'"> + <xsl:variable name="tabPositionTmp"> + <xsl:call-template name="convert2cm"> + <xsl:with-param name="value" select="$tabStops/style:tab-stop[last()]/@style:position"/> + </xsl:call-template> + </xsl:variable> + <!-- Heuristic: for every tab that is more than specified give a further 1 cm --> + <xsl:value-of select="$parentMarginLeft + $tabPositionTmp + count($tabStops/style:tab-stop) - $tabCount"/> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="$tabIndent"/> + </xsl:otherwise> + </xsl:choose> + <xsl:text>cm;</xsl:text> + <xsl:apply-templates select="$tabStops/style:tab-stop[$tabCount]/@style:type"/> + </xsl:template> + + <!-- OOo writes out empty paragraphs layouted behind an image, + those have to be neglected in HTML + This method checks if an empty paragraph is of that kind! --> + <xsl:template name="follows-empty-paragraphs-and-image"> + <xsl:param name="precedingElement" /> + <xsl:param name="elementToCheck" select="1"/> + <xsl:choose> + <!-- OOo writes out empty paragraphs layouted behind the image, + those have to be neglected in HTML + <xsl:when test="name() = 'text:p' and (normalize-space($childText) = '')"> --> + <!-- WorkAround: Test if the empty paragraph was added after an image, which OOO often does --> + <xsl:when test="(name($precedingElement) = 'text:p' and not($precedingElement/text()) and not($precedingElement/*))"> + <xsl:call-template name="follows-empty-paragraphs-and-image"> + <xsl:with-param name="precedingElement" select="preceding-sibling::*[$elementToCheck]"/> + <xsl:with-param name="elementToCheck" select="$elementToCheck +1"/> + </xsl:call-template> + </xsl:when> + <xsl:when test="$precedingElement/draw:frame">yes</xsl:when> + <xsl:otherwise>no</xsl:otherwise> + </xsl:choose> + </xsl:template> + + <xsl:template name="create-paragraph"> + <xsl:param name="globalData"/> + <!-- the footnote symbol is the prefix for a footnote in the footer --> + <xsl:param name="footnotePrefix"/> + + <!-- xhtml:p may only contain inline elements. + If there is one frame beyond, div must be used! --> + <xsl:variable name="elementName"> + <xsl:choose> + <xsl:when test="descendant::draw:frame[1] or descendant::text:p[1]">div</xsl:when> + <xsl:otherwise>p</xsl:otherwise> + </xsl:choose> + </xsl:variable> + + <xsl:element name="{$elementName}"> + <xsl:choose> + <!-- in ODF borders of paragraphs will be merged by default. Merging means the adjacent paragraphs are building a unit, + where only the first and the last will have a border to the surrounding (top / bottom border) + <xsl:variable name="precedingParagraphStyle" select="preceding-sibling::*[1][name() = 'text:p']/@text:style-name"/> + <xsl:variable name="followingParagraphStyle" select="following-sibling::*[1][name() = 'text:p']/@text:style-name"/> + --> + <xsl:when test="$globalData/all-styles/style[@style:name = current()/@text:style-name]/@mergedBorders"> + <xsl:variable name="precedingParagraphStyle" select="preceding-sibling::*[1][name() = 'text:p']/@text:style-name"/> + <xsl:variable name="followingParagraphStyle" select="following-sibling::*[1][name() = 'text:p']/@text:style-name"/> + <xsl:choose> + <xsl:when test="$precedingParagraphStyle or $followingParagraphStyle"> + <xsl:variable name="isPrecedingBorderParagraph" select="$globalData/all-styles/style[@style:name = $precedingParagraphStyle]/@mergedBorders"/> + <xsl:variable name="isFollowingBorderParagraph" select="$globalData/all-styles/style[@style:name = $followingParagraphStyle]/@mergedBorders"/> + <xsl:choose> + <xsl:when test="not($isPrecedingBorderParagraph) and $isFollowingBorderParagraph"> + <xsl:attribute name="class"> + <xsl:value-of select="concat(translate(@text:style-name, '.,;: %()[]/\+', '_____________'), '_borderStart')"/> + </xsl:attribute> + <xsl:apply-templates> + <xsl:with-param name="globalData" select="$globalData"/> + </xsl:apply-templates> + </xsl:when> + <xsl:when test="$isPrecedingBorderParagraph and not($isFollowingBorderParagraph)"> + <xsl:attribute name="class"> + <xsl:value-of select="concat(translate(@text:style-name, '.,;: %()[]/\+', '_____________'), '_borderEnd')"/> + </xsl:attribute> + <xsl:apply-templates> + <xsl:with-param name="globalData" select="$globalData"/> + </xsl:apply-templates> + </xsl:when> + <!-- inbetween paragraphs with border/margin --> + <xsl:when test="$isPrecedingBorderParagraph and $isFollowingBorderParagraph"> + <xsl:attribute name="class"> + <xsl:value-of select="concat(translate(@text:style-name, '.,;: %()[]/\+', '_____________'), '_borderSides')"/> + </xsl:attribute> + <xsl:apply-templates> + <xsl:with-param name="globalData" select="$globalData"/> + </xsl:apply-templates> + </xsl:when> + <xsl:otherwise> + <xsl:call-template name="write-paragraph"> + <xsl:with-param name="globalData" select="$globalData"/> + </xsl:call-template> + </xsl:otherwise> + </xsl:choose> + </xsl:when> + <xsl:otherwise> + <xsl:call-template name="write-paragraph"> + <xsl:with-param name="globalData" select="$globalData"/> + </xsl:call-template> + </xsl:otherwise> + </xsl:choose> + </xsl:when> + <xsl:otherwise> + <xsl:call-template name="write-paragraph"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="footnotePrefix" select="$footnotePrefix" /> + </xsl:call-template> + </xsl:otherwise> + </xsl:choose> + </xsl:element> + </xsl:template> + + <xsl:template name="write-paragraph"> + <xsl:param name="globalData"/> + <!-- the footnote symbol is the prefix for a footnote in the footer --> + <xsl:param name="footnotePrefix" /> + + <!-- empty paragraph tags does not provoke a carriage return, + therefore a non breakable space ( ) have been inserted.--> + <xsl:choose> + <xsl:when test="node()"> + <xsl:call-template name="apply-styles-and-content"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="footnotePrefix" select="$footnotePrefix" /> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:call-template name="apply-styles-and-content"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="footnotePrefix" select="$footnotePrefix" /> + </xsl:call-template> + <xsl:text> </xsl:text> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <xsl:template match="style:tab-stop/@style:type"> + <xsl:text>text-align:</xsl:text> + <xsl:choose> + <xsl:when test=". = 'left'">left</xsl:when> + <xsl:when test=". = 'right'">right</xsl:when> + <xsl:when test=". = 'center'">center</xsl:when> + <xsl:otherwise>justify</xsl:otherwise> + </xsl:choose> + <xsl:text>;</xsl:text> + </xsl:template> + + <!-- As soon a frame is within a paragraph (text:p) or page:frame, every child element is floating (CSS) and worked out in sequence. + Accumulating prior frame width and adding parent's left margin --> + <!-- Matching all elements and text beyond a paragraph/text:page which are sibling of a draw:frame --> + <xsl:template match="* | text()" mode="frameFloating"> + <xsl:param name="globalData"/> + <xsl:param name="previousFrameWidths" select="0"/> + <xsl:param name="previousFrameHeights" select="0" /> + <xsl:param name="leftPosition" select="0" /> + <xsl:param name="parentMarginLeft" /> + <xsl:param name="stopAtFirstFrame" select="false()" /> + <xsl:param name="tdf146264hack" select="false()" /> + + <xsl:choose> + <xsl:when test="name() = 'draw:frame' and not($stopAtFirstFrame)"> + + <!-- if the first node is a draw:frame create a div --> + <xsl:call-template name="createDrawFrame"> + <xsl:with-param name="globalData" select="$globalData"/> + <xsl:with-param name="previousFrameWidths" select="$previousFrameWidths"/> + <xsl:with-param name="previousFrameHeights" select="$previousFrameHeights"/> + <xsl:with-param name="parentMarginLeft" select="$parentMarginLeft"/> + </xsl:call-template> + <!-- next elements will be called after the creation with the new indent (plus width of frame) --> + </xsl:when> + <xsl:otherwise> + <xsl:variable name="nextSiblingIsFrame" select="name(following-sibling::node()[1]) = 'draw:frame'"/> + <xsl:choose> + <xsl:when test="normalize-space(.) != ''"> + <!-- every following frame sibling till the next draw:frame + have to be encapsulated within a div with left indent. + To be moved altogether according the indent (usually right) --> + <xsl:comment>Next 'div' added for floating.</xsl:comment> + <xsl:element name="div"> + <xsl:attribute name="style"> + <xsl:text>display:inline; position:relative; left:</xsl:text> + <xsl:value-of select="$leftPosition"/> + <xsl:text>cm;</xsl:text> + </xsl:attribute> + <!-- This xsl:if is the meat of the extremely ugly "fix" to tdf#146264. It probably has unintended + bad side-effects. + --> + <xsl:if test="not($tdf146264hack)"> + <xsl:apply-templates select="."> + <xsl:with-param name="globalData" select="$globalData"/> + </xsl:apply-templates> + </xsl:if> + <!-- if it is a frame sibling it will be NOT encapsulated within the div (as already within one) --> + <xsl:if test="not($nextSiblingIsFrame)"> + <xsl:apply-templates select="following-sibling::node()[1]" mode="frameFloating"> + <xsl:with-param name="globalData" select="$globalData"/> + <xsl:with-param name="previousFrameWidths" select="$previousFrameWidths"/> + <xsl:with-param name="previousFrameHeights" select="$previousFrameHeights"/> + <xsl:with-param name="parentMarginLeft" select="$parentMarginLeft"/> + <xsl:with-param name="leftPosition" select="$leftPosition"/> + <xsl:with-param name="stopAtFirstFrame" select="$stopAtFirstFrame" /> + </xsl:apply-templates> + </xsl:if> + </xsl:element> + + <!-- Other draw:frame will be created outside of the div element --> + <xsl:if test="nextSiblingIsFrame and not(stopAtFirstFrame)"> + <xsl:apply-templates select="following-sibling::draw:frame[1]" mode="frameFloating"> + <xsl:with-param name="globalData" select="$globalData"/> + <xsl:with-param name="previousFrameWidths" select="$previousFrameWidths"/> + <xsl:with-param name="previousFrameHeights" select="$previousFrameHeights"/> + <xsl:with-param name="parentMarginLeft" select="$parentMarginLeft"/> + <xsl:with-param name="leftPosition" select="$leftPosition"/> + <xsl:with-param name="stopAtFirstFrame" select="$stopAtFirstFrame" /> + </xsl:apply-templates> + </xsl:if> + </xsl:when> + <xsl:otherwise> + <xsl:apply-templates select="."> + <xsl:with-param name="globalData" select="$globalData"/> + </xsl:apply-templates> + <xsl:if test="not($nextSiblingIsFrame)"> + <xsl:apply-templates select="following-sibling::node()[1]" mode="frameFloating"> + <xsl:with-param name="globalData" select="$globalData"/> + <xsl:with-param name="previousFrameWidths" select="$previousFrameWidths"/> + <xsl:with-param name="previousFrameHeights" select="$previousFrameHeights"/> + <xsl:with-param name="parentMarginLeft" select="$parentMarginLeft"/> + <xsl:with-param name="leftPosition" select="$leftPosition"/> + <xsl:with-param name="stopAtFirstFrame" select="$stopAtFirstFrame" /> + </xsl:apply-templates> + </xsl:if> + </xsl:otherwise> + </xsl:choose> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <!-- A XML node other than text or element (e.g. comment) should not stop the recursion --> + <xsl:template match="comment()" mode="frameFloating"> + <xsl:param name="globalData"/> + <xsl:param name="previousFrameWidths" select="0"/> + <xsl:param name="previousFrameHeights" select="0" /> + <xsl:param name="leftPosition" /> + <xsl:param name="parentMarginLeft" /> + <xsl:param name="stopAtFirstFrame" select="false()" /> + + <xsl:apply-templates select="following-sibling::node()[1]" mode="frameFloating"> + <xsl:with-param name="globalData" select="$globalData"/> + <xsl:with-param name="previousFrameWidths" select="$previousFrameWidths"/> + <xsl:with-param name="parentMarginLeft" select="$parentMarginLeft"/> + <xsl:with-param name="leftPosition" select="$leftPosition"/> + <xsl:with-param name="stopAtFirstFrame" select="$stopAtFirstFrame" /> + </xsl:apply-templates> + </xsl:template> + + + + <!-- As draw:frame may occur within more elements than in text:p and draw:page --> + <xsl:template match="draw:frame"> + <xsl:param name="globalData"/> + <xsl:param name="previousFrameWidths" select="0"/> + <xsl:param name="previousFrameHeights" select="0" /> + <xsl:param name="tdf146264hack" select="false()" /> + + <xsl:call-template name="createDrawFrame"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="previousFrameWidths" select="$previousFrameWidths"/> + <xsl:with-param name="previousFrameHeights" select="$previousFrameHeights"/> + <xsl:with-param name="tdf146264hack" select="$tdf146264hack"/> + </xsl:call-template> + <!-- after the last draw:frame sibling the CSS float is disabled --> + <xsl:if test="@text:anchor-type!='as-char'"> + <div style="clear:both; line-height:0; width:0; height:0; margin:0; padding:0;"> </div> + </xsl:if> + </xsl:template> + + <xsl:template name="getPageMarginLeft"> + <!-- approximation to find the correct master page style (with page dimensions) --> + <xsl:variable name="masterPageNames"> + <!-- Loop over every style:style containing a @style:master-page-name attribute --> + <xsl:for-each select="key('masterPage','count')"> + <!-- Check if this style is being used in the body --> + <xsl:if test="key('elementUsingStyle', ../@style:name)"> + <!-- Check every master-page-name if it is not empty and return as ';' separated list --> + <xsl:if test="string-length(../@style:master-page-name) > 0"> + <xsl:value-of select="../@style:master-page-name"/>; + </xsl:if> + </xsl:if> + </xsl:for-each> + </xsl:variable> + <!-- Take the first of the masterpage list and get the according style:master-page element and find the @style:page-layout-name --> + <xsl:variable name="pageLayoutName" select="key('masterPageElements', substring-before($masterPageNames,';'))/@style:page-layout-name"/> + <!-- Find the according style:page-layout and store the properties in a variable --> + <xsl:variable name="pageMarginLeftAttr" select="key('pageLayoutElements', $pageLayoutName)/style:page-layout-properties/@fo:margin-left"/> + <xsl:choose> + <xsl:when test="$pageMarginLeftAttr"> + <xsl:call-template name="convert2cm"> + <xsl:with-param name="value" select="$pageMarginLeftAttr"/> + </xsl:call-template> + </xsl:when> + <xsl:otherwise>0</xsl:otherwise> + </xsl:choose> + </xsl:template> + + <!-- Elements and text aside of a draw:frame are floating, here a div is being created. + Either for a draw:frame or for text and other elements floating aside --> + <xsl:template name="createDrawFrame"> + <xsl:param name="globalData"/> + <xsl:param name="previousFrameWidths" select="0"/> + <xsl:param name="previousFrameHeights" select="0" /> + <xsl:param name="parentMarginLeft"/> + <xsl:param name="stopAtFirstFrame" select="false()" /> + <xsl:param name="tdf146264hack" select="false()" /> + + <xsl:variable name="parentMarginLeftNew"> + <xsl:choose> + <xsl:when test="string-length(normalize-space($parentMarginLeft)) < 1"> + <!-- Styles of first paragraph in list item, including ancestor styles (inheritance) --> + <xsl:variable name="paragraphName" select="parent::*/@text:style-name" /> + <xsl:variable name="imageParagraphStyle" select="$globalData/all-styles/style[@style:name = $paragraphName]/final-properties"/> + <!-- Only the left margin of the first paragraph of a list item will be added to the margin of the complete list (all levels)--> + <xsl:choose> + <xsl:when test="contains($imageParagraphStyle, 'margin-left:')"> + <xsl:call-template name="convert2cm"> + <xsl:with-param name="value" select="normalize-space(substring-before(substring-after($imageParagraphStyle, 'margin-left:'), ';'))"/> + </xsl:call-template> + </xsl:when> + <xsl:otherwise>0</xsl:otherwise> + </xsl:choose> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="normalize-space($parentMarginLeft)" /> + </xsl:otherwise> + </xsl:choose> + </xsl:variable> + <xsl:variable name="svgWidth"> + <xsl:choose> + <xsl:when test="@svg:width"> + <xsl:call-template name="convert2cm"> + <xsl:with-param name="value" select="@svg:width"/> + </xsl:call-template> + </xsl:when> + <xsl:otherwise>0</xsl:otherwise> + </xsl:choose> + </xsl:variable> + <xsl:variable name="svgX"> + <xsl:choose> + <xsl:when test="@svg:x"> + <xsl:call-template name="convert2cm"> + <xsl:with-param name="value" select="@svg:x"/> + </xsl:call-template> + </xsl:when> + <xsl:otherwise>0</xsl:otherwise> + </xsl:choose> + </xsl:variable> + <xsl:variable name="leftPosition" select="$svgX - $parentMarginLeftNew - $previousFrameWidths"/> + <xsl:variable name="svgY"> + <xsl:choose> + <xsl:when test="@svg:y"> + <xsl:call-template name="convert2cm"> + <xsl:with-param name="value" select="@svg:y"/> + </xsl:call-template> + </xsl:when> + <xsl:otherwise>0</xsl:otherwise> + </xsl:choose> + </xsl:variable> + <!-- if the frame is anchored on a paragraph --> + <xsl:if test="@text:anchor-type='paragraph'"> + <xsl:comment>Next 'div' is emulating the top height of a draw:frame.</xsl:comment> + <!-- When the svg:y is set relative to the paragraph content, the best way to emulate a positive height, + is to add an invisible division inbetween with a height. + Often text will flow into this 'gap', which is handled separately! + --> + <xsl:if test="$svgY > 0"> + <xsl:element name="div"> + <xsl:attribute name="style"> + <xsl:text>height:</xsl:text> + <xsl:value-of select="$svgY"/> + <xsl:text>cm;</xsl:text> + </xsl:attribute> + <xsl:text> </xsl:text> + </xsl:element> + </xsl:if> + </xsl:if> + <xsl:call-template name="createDrawFrame2"> + <xsl:with-param name="globalData" select="$globalData"/> + <xsl:with-param name="previousFrameWidths" select="$previousFrameWidths + $svgWidth"/> + <xsl:with-param name="parentMarginLeftNew" select="$parentMarginLeftNew"/> + <xsl:with-param name="leftPosition" select="$leftPosition"/> + <xsl:with-param name="svgY" select="$svgY"/> + </xsl:call-template> + <xsl:apply-templates select="following-sibling::node()[1]" mode="frameFloating"> + <xsl:with-param name="globalData" select="$globalData"/> + <xsl:with-param name="previousFrameWidths" select="$previousFrameWidths + $svgWidth"/> + <xsl:with-param name="parentMarginLeft" select="$parentMarginLeftNew"/> + <xsl:with-param name="leftPosition" select="$leftPosition"/> + <xsl:with-param name="stopAtFirstFrame" select="$stopAtFirstFrame" /> + <xsl:with-param name="tdf146264hack" select="$tdf146264hack" /> + </xsl:apply-templates> + </xsl:template> + + <xsl:template name="createDrawFrame2"> + <xsl:param name="globalData"/> + <xsl:param name="previousFrameWidths" /> + <xsl:param name="parentMarginLeftNew"/> + <xsl:param name="leftPosition" /> + <xsl:param name="svgY" /> + + <xsl:variable name="elem-name"> + <xsl:choose> + <xsl:when test="@text:anchor-type='as-char'">span</xsl:when> + <xsl:otherwise>div</xsl:otherwise> + </xsl:choose> + </xsl:variable> + <xsl:comment>Next ' + <xsl:value-of select="$elem-name"/>' is a draw:frame. + </xsl:comment> + <xsl:element name="{$elem-name}"> + <xsl:choose> + <xsl:when test="draw:object/math:math"> + <!-- draw:frame elements contain many data that are not + relevant for mathematical formulas and that may + cause incorrect rendering. Let's ignore the + replacement image and keep only the id attribute. + See fdo#66645 --> + <xsl:apply-templates select="@draw:name"/> + <xsl:apply-templates select="draw:object[1]"/><xsl:text> </xsl:text><!-- often trailing whitespace is missing --> + </xsl:when> + <xsl:otherwise> + <xsl:attribute name="style"> + <xsl:call-template name="widthAndHeight"/> + <xsl:text> padding:0; </xsl:text> + <xsl:if test="@text:anchor-type!='as-char'"> + <!-- all images float (CSS float relative) with a left position calculated by svg:x - parentMarginLeft - previousFrameWidths --> + <xsl:text> float:left; position:relative; left:</xsl:text> + <xsl:value-of select="$leftPosition"/> + <xsl:text>cm; </xsl:text> + <!-- if the frame is anchored on a char --> + <xsl:if test="@text:anchor-type='char'"> + <xsl:text>top:</xsl:text> + <xsl:value-of select="$svgY"/> + <xsl:text>cm; </xsl:text> + </xsl:if> + </xsl:if> + </xsl:attribute> + <xsl:apply-templates select="@*"> + <xsl:with-param name="globalData" select="$globalData"/> + </xsl:apply-templates> + <xsl:apply-templates select="node()"> + <xsl:with-param name="globalData" select="$globalData"/> + </xsl:apply-templates> + </xsl:otherwise> + </xsl:choose> + </xsl:element> + </xsl:template> + + <xsl:template match="svg:desc"/> + + <xsl:template name="widthAndHeight"> + <xsl:if test="@svg:height | @svg:width"> + <xsl:choose> + <xsl:when test="not(@svg:width)"> + <xsl:call-template name="svg:height"/> + </xsl:when> + <xsl:when test="not(@svg:height)"> + <xsl:call-template name="svg:width"/> + </xsl:when> + <xsl:otherwise> + <xsl:call-template name="svg:height"/> + <xsl:call-template name="svg:width"/> + </xsl:otherwise> + </xsl:choose> + </xsl:if> + </xsl:template> + + <!-- ***************** --> + <!-- *** Text Span *** --> + <!-- ***************** --> + + <xsl:template match="text:span"> + <xsl:param name="globalData"/> + + <xsl:choose> + <xsl:when test="draw:frame"> + <!-- sometimes an ODF image is anchored as character and the + image frame appears within a span (which is not valid for HTML) + Heuristic: Neglecting the span assuming no text content aside + of frame within span --> + <xsl:apply-templates> + <xsl:with-param name="globalData" select="$globalData"/> + </xsl:apply-templates> + </xsl:when> + <xsl:otherwise> + <xsl:element name="span"> + <xsl:call-template name="apply-styles-and-content"> + <xsl:with-param name="globalData" select="$globalData"/> + </xsl:call-template> + </xsl:element> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + + + <!-- **************** --> + <!-- *** Headings *** --> + <!-- **************** --> + + <xsl:template match="text:h"> + <xsl:param name="globalData"/> + + <!-- no creation of empty headings (without text content) --> + <xsl:if test="text() or descendant::text()"> + <!-- The URL linking of a table-of-content is due to a bug (cp. bug id# 102311) not mapped as URL in the XML. + Linking of the table-of-content can therefore only be achieved by a work-around in HTML --> + <xsl:call-template name="create-heading"> + <xsl:with-param name="globalData" select="$globalData"/> + </xsl:call-template> + </xsl:if> + </xsl:template> + + <!-- default matching for header elements --> + <xsl:template name="create-heading"> + <xsl:param name="globalData"/> + + <xsl:variable name="headingLevel"> + <xsl:choose> + <xsl:when test="@text:outline-level < 6"> + <xsl:value-of select="@text:outline-level"/> + </xsl:when> + <xsl:otherwise>6</xsl:otherwise> + </xsl:choose> + </xsl:variable> + <xsl:variable name="headertyp" select="concat('h', $headingLevel)"/> + <xsl:element name="{$headertyp}"> + <!-- outline style 'text:min-label-width' is interpreted as a CSS 'margin-right' attribute + NOTE: Should be handled as CSS style in style header --> + <xsl:variable name="min-label" select="$globalData/office:styles/text:outline-style/text:outline-level-style[@text:level = current()/@text:outline-level]/*/@text:min-label-width"/> + <xsl:attribute name="class"> + <xsl:value-of select="translate(@text:style-name, '.,;: %()[]/\+', '_____________')"/> + </xsl:attribute> + + <xsl:call-template name="create-heading-anchor"> + <xsl:with-param name="globalData" select="$globalData"/> + </xsl:call-template> + + <xsl:apply-templates> + <xsl:with-param name="globalData" select="$globalData"/> + </xsl:apply-templates> + </xsl:element> + + </xsl:template> + + <xsl:template name="create-heading-anchor"> + <xsl:param name="globalData"/> + + <!-- writing out a heading number if desired.--> + <!-- if a corresponding 'text:outline-style' exist or is not empty --> + <xsl:choose> + <xsl:when test="$globalData/office:styles/text:outline-style/text:outline-level-style[@text:level = current()/@text:outline-level]/@style:num-format != '' and not(@text:is-list-header='true')"> + + <!-- Every heading element will get a unique anchor for its file, from its hierarchy level and name: + For example: The heading title 'My favorite heading' might get <a name="1_2_2_My_favorite_heading" /> --> + <!-- creating an anchor for referencing the heading (e.g. from content table) --> + <xsl:variable name="headingNumber"> + <xsl:call-template name="get-heading-number"> + <xsl:with-param name="globalData" select="$globalData"/> + </xsl:call-template> + </xsl:variable> + <xsl:call-template name="create-heading-anchor2"> + <xsl:with-param name="globalData" select="$globalData"/> + <xsl:with-param name="headingNumber" select="$headingNumber"/> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:call-template name="create-heading-anchor2"> + <xsl:with-param name="globalData" select="$globalData"/> + </xsl:call-template> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + + <xsl:template name="get-heading-number"> + <xsl:param name="globalData"/> + + <!-- write number prefix --> + <xsl:value-of select="$globalData/office:styles/text:outline-style/text:outline-level-style[@text:level = current()/@text:outline-level]/@style:num-prefix"/> + <xsl:call-template name="write-heading-number"> + <xsl:with-param name="globalData" select="$globalData"/> + </xsl:call-template> + <!-- write number suffix --> + <xsl:value-of select="$globalData/office:styles/text:outline-style/text:outline-level-style[@text:level = current()/@text:outline-level]/@style:num-suffix"/> + </xsl:template> + + <!-- creating an anchor for referencing the heading --> + <xsl:template name="create-heading-anchor2"> + <xsl:param name="globalData"/> + <xsl:param name="headingNumber" /> + + <xsl:variable name="title"> + <xsl:apply-templates mode="concatenate"/> + </xsl:variable> + <!-- REFERENCE HANDLING - ANCHOR --> + <xsl:element namespace="{$namespace}" name="a"> + <xsl:attribute name="id"> + <xsl:value-of select="translate(concat('a_',normalize-space($headingNumber), '_', normalize-space($title)), '
&<>–.,;: %()[]/\+', '____________________________')" disable-output-escaping="yes"/> + </xsl:attribute> + + <xsl:element name="span"> + <!-- Convert the "label-followed-by" to margins. According to ODF, possible values are: 'listtab', 'space', and 'nothing'. + 'space' seems not to be written out by LO, and for 'nothing' we obviously need do nothing. + NOTE: Should be handled as CSS style in style header --> + <xsl:variable name="currentOutlineLevel" select="@text:outline-level"/> + <xsl:variable name="labelFollowedBy" select="$globalData//office:document/office:styles/text:outline-style/text:outline-level-style[@text:level = $currentOutlineLevel]/style:list-level-properties[@text:list-level-position-and-space-mode='label-alignment']/style:list-level-label-alignment/@text:label-followed-by"/> + + <!-- Add some margin, but only if there is a number preceding the heading. --> + <xsl:if test="$labelFollowedBy='listtab' and $headingNumber != ''"> + <xsl:attribute name="class"> + <xsl:text>heading_numbering</xsl:text> + </xsl:attribute> + </xsl:if> + <xsl:copy-of select="$headingNumber"/> + </xsl:element> + </xsl:element> + </xsl:template> + + <xsl:template name="write-heading-number"> + <xsl:param name="globalData"/> + + <!-- By default heading start with '1', the parameter 'textStartValue' will only be set, if the attribute @text:start-value exist --> + <xsl:choose> + <xsl:when test="$globalData/office:styles/text:outline-style/text:outline-level-style[@text:level = current()/@text:outline-level]/@text:start-value"> + <xsl:call-template name="calc-heading-number"> + <xsl:with-param name="globalData" select="$globalData"/> + <xsl:with-param name="outlineLevel" select="@text:outline-level"/> + <xsl:with-param name="textStartValue" select="$globalData/office:styles/text:outline-style/text:outline-level-style[@text:level = current()/@text:outline-level]/@text:start-value"/> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:call-template name="calc-heading-number"> + <xsl:with-param name="globalData" select="$globalData"/> + <xsl:with-param name="outlineLevel" select="@text:outline-level"/> + </xsl:call-template> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <!-- + Find the correct heading no., which is the sum of 'text:start-value' + and preceding siblings of 'text:h' with the same 'text:outline-level' (until a text:outline-level with lower value is found). + If the 'text:start-value is not set the default value of '1' has to be taken. + If a heading number is found (e.g. text:outline-level='3') all heading numbers + for the higher levels have to be written out --> + <xsl:template name="calc-heading-number"> + <xsl:param name="globalData"/> + <xsl:param name="outlineLevel"/><!-- text level of the heading --> + <xsl:param name="iOutlineLevel" select="1"/><!-- iterator, counts from 1 to the text level of the heading --> + <xsl:param name="textStartValue" select="1"/><!-- text level to start with, default is '1' --> + + <xsl:choose> + <!-- iText levels counts up from '1' to outlineLevel + Which means writing a heading number from left to right --> + <xsl:when test="$iOutlineLevel < $outlineLevel"> + + <!-- Write preceding heading numbers --> + <xsl:if test="$globalData/office:styles/text:outline-style/text:outline-level-style[@text:level = ($iOutlineLevel)]/@style:num-format != ''"> + <xsl:call-template name="writeNumber"> + <xsl:with-param name="numberDigit"> + <xsl:call-template name="calc-heading-digit"> + <xsl:with-param name="value" select="0"/> + <xsl:with-param name="currentoutlineLevel" select="$iOutlineLevel"/> + </xsl:call-template> + </xsl:with-param> + <xsl:with-param name="numberFormat" select="$globalData/office:styles/text:outline-style/text:outline-level-style[@text:level = ($iOutlineLevel)]/@style:num-format"/> + </xsl:call-template> + </xsl:if> + <xsl:choose> + <xsl:when test="$globalData/office:styles/text:outline-style/text:outline-level-style[@text:level = ($iOutlineLevel + 1)]/@text:start-value"> + <xsl:call-template name="calc-heading-number"> + <xsl:with-param name="globalData" select="$globalData"/> + <xsl:with-param name="outlineLevel" select="$outlineLevel"/> + <xsl:with-param name="iOutlineLevel" select="$iOutlineLevel + 1"/> + <xsl:with-param name="textStartValue" select="$globalData/office:styles/text:outline-style/text:outline-level-style[@text:level = ($iOutlineLevel + 1)]/@text:start-value"/> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:call-template name="calc-heading-number"> + <xsl:with-param name="globalData" select="$globalData"/> + <xsl:with-param name="outlineLevel" select="$outlineLevel"/> + <xsl:with-param name="iOutlineLevel" select="$iOutlineLevel + 1"/> + </xsl:call-template> + </xsl:otherwise> + </xsl:choose> + </xsl:when> + <xsl:otherwise> + <!-- Write preceding heading numbers --> + <xsl:call-template name="writeNumber"> + <xsl:with-param name="numberDigit"> + <xsl:call-template name="calc-heading-digit"> + <xsl:with-param name="value" select="$textStartValue"/> + <xsl:with-param name="currentoutlineLevel" select="$iOutlineLevel"/> + </xsl:call-template> + </xsl:with-param> + <xsl:with-param name="numberFormat" select="$globalData/office:styles/text:outline-style/text:outline-level-style[@text:level = $iOutlineLevel]/@style:num-format"/> + <xsl:with-param name="last" select="true()"/> + </xsl:call-template> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <xsl:template name="writeNumber"> + <xsl:param name="numberDigit"/> + <xsl:param name="numberFormat"/> + <xsl:param name="last"/> + + <xsl:choose> + <xsl:when test="not($numberFormat)"> + <xsl:number value="$numberDigit" format="1."/> + </xsl:when> + <xsl:otherwise> + <xsl:choose> + <xsl:when test="$last"> + <xsl:number value="$numberDigit" format="{$numberFormat}"/> + </xsl:when> + <xsl:otherwise> + <xsl:number value="$numberDigit" format="{$numberFormat}."/> + </xsl:otherwise> + </xsl:choose> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <xsl:template name="calc-heading-digit"> + <xsl:param name="value"/> + <xsl:param name="currentoutlineLevel"/> + <xsl:param name="i" select="1"/> + + <xsl:variable name="precedingHeading" select="preceding-sibling::text:h[@text:outline-level <= $currentoutlineLevel][$i]"/> + <xsl:variable name="precedingoutlineLevel" select="$precedingHeading/@text:outline-level"/> + <!-- tdf#107696: if text:h has attribute "is-list-header" with "true" value, it mustn't be counted for numbering --> + <xsl:variable name="precedingoutlineLevel-is-list-header" select="$precedingHeading[@text:is-list-header='true']/@text:outline-level"/> + <xsl:choose> + <xsl:when test="($currentoutlineLevel = $precedingoutlineLevel) and (not($precedingoutlineLevel-is-list-header)) "> + <xsl:call-template name="calc-heading-digit"> + <xsl:with-param name="value" select="$value + 1"/> + <xsl:with-param name="currentoutlineLevel" select="$currentoutlineLevel"/> + <xsl:with-param name="i" select="$i + 1"/> + </xsl:call-template> + </xsl:when> + <!-- tdf#107696: case text:h has attribute "is-list-header" with "true" value, we don't increment value --> + <xsl:when test="($currentoutlineLevel = $precedingoutlineLevel) and ($precedingoutlineLevel-is-list-header) "> + <xsl:call-template name="calc-heading-digit"> + <xsl:with-param name="value" select="$value"/> + <xsl:with-param name="currentoutlineLevel" select="$currentoutlineLevel"/> + <xsl:with-param name="i" select="$i + 1"/> + </xsl:call-template> + </xsl:when> + <xsl:when test="$currentoutlineLevel < $precedingoutlineLevel"> + <xsl:message terminate="yes">this should not happen</xsl:message> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="$value"/> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <!-- Neglect Annotations --> + <xsl:template match="office:annotation" mode="concatenate"/> + + <!-- Match text:placeholder child nodes (e.g. text) --> + <xsl:template match="text:placeholder"> + <xsl:param name="globalData"/> + + <xsl:call-template name="apply-styles-and-content"> + <xsl:with-param name="globalData" select="$globalData"/> + </xsl:call-template> + </xsl:template> + + <!-- ************* --> + <!-- *** Link *** --> + <!-- ************* --> + + <xsl:template match="text:a | draw:a"> + <xsl:param name="globalData"/> + + <xsl:call-template name="create-common-anchor-link"> + <xsl:with-param name="globalData" select="$globalData"/> + </xsl:call-template> + </xsl:template> + + + <xsl:template name="create-common-anchor-link"> + <xsl:param name="globalData"/> + + <xsl:element name="a"> + <xsl:attribute name="href"> + <xsl:call-template name="create-href"> + <xsl:with-param name="href" select="@xlink:href"/> + </xsl:call-template> + </xsl:attribute> + <xsl:call-template name="apply-styles-and-content"> + <xsl:with-param name="globalData" select="$globalData"/> + </xsl:call-template> + </xsl:element> + </xsl:template> + + + + <!-- ******************* --> + <!-- *** Image Link *** --> + <!-- ******************* --> + + <!-- currently suggesting that all draw:object-ole elements are images --> + <xsl:template match="draw:image | draw:object-ole"> + <xsl:param name="globalData"/> + + <!-- If there is a replacement graphic, we take it (only exception is if the main image is svg). + The replacement graphic is a png which browsers are more likely able to render than the + original graphic which might have arbitrary formats. --> + <xsl:if test="(@loext:mime-type = 'image/svg+xml') or + (@draw:mime-type = 'image/svg+xml') or + (not(following-sibling::draw:image) and + not((preceding-sibling::draw:image[1]/@loext:mime-type = 'image/svg+xml') + or + (preceding-sibling::draw:image[1]/@draw:mime-type = 'image/svg+xml')))"> + <xsl:choose> + <xsl:when test="ancestor::text:p or parent::text:span or parent::text:h or parent::draw:a or parent::text:a or text:ruby-base"> + <!-- XHTML does not allow the mapped elements to contain paragraphs --> + <xsl:call-template name="create-image-element"> + <xsl:with-param name="globalData" select="$globalData"/> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <!-- images are embedded in a paragraph, but are in CSS not able to express a horizontal alignment for themself. + A 'div' element taking over the image style would solve that problem, but is invalid as child of a paragraph --> + <xsl:element name="p"> + <xsl:apply-templates select="@draw:style-name"> + <xsl:with-param name="globalData" select="$globalData"/> + </xsl:apply-templates> + + <xsl:call-template name="create-image-element"> + <xsl:with-param name="globalData" select="$globalData"/> + </xsl:call-template> + </xsl:element> + </xsl:otherwise> + </xsl:choose> + </xsl:if> + </xsl:template> + + <xsl:template name="create-image-element"> + <xsl:param name="globalData"/> + + <xsl:element name="img"> + <xsl:if test="../@svg:width or ../@svg:height"> + <xsl:attribute name="style"> + <xsl:if test="../@svg:height"> + <xsl:text>height:</xsl:text> + <xsl:call-template name="convert2cm"> + <xsl:with-param name="value" select="../@svg:height"/> + </xsl:call-template> + <xsl:text>cm;</xsl:text> + </xsl:if> + <xsl:if test="../@svg:width"> + <xsl:text>width:</xsl:text> + <xsl:call-template name="convert2cm"> + <xsl:with-param name="value" select="../@svg:width"/> + </xsl:call-template> + <xsl:text>cm;</xsl:text> + </xsl:if> + </xsl:attribute> + </xsl:if> + <xsl:attribute name="alt"> + <xsl:choose> + <xsl:when test="../svg:title"> + <xsl:value-of select="../svg:title"/> + </xsl:when> + <xsl:otherwise> + <xsl:message> + Accessibility Warning: + No alternate text ('svg:title' element) set for + image ' + <xsl:value-of select="@xlink:href"/>'! + </xsl:message> + </xsl:otherwise> + </xsl:choose> + </xsl:attribute> + + <xsl:attribute name="src"> + <xsl:call-template name="create-href"> + <xsl:with-param name="href" select="@xlink:href"/> + <xsl:with-param name="mimetype"> + <xsl:choose> + <xsl:when test="@draw:mime-type"> + <xsl:value-of select="@draw:mime-type"/> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="@loext:mime-type"/> + </xsl:otherwise> + </xsl:choose> + </xsl:with-param> + </xsl:call-template> + </xsl:attribute> + + <!-- style interpretation only, as no subelements are allowed for img in XHTML --> + <xsl:apply-templates select="@draw:style-name"> + <xsl:with-param name="globalData" select="$globalData"/> + </xsl:apply-templates> + </xsl:element> + </xsl:template> + + <!-- ************ --> + <!-- *** list *** --> + <!-- ************ --> + <!-- + Due to the requirements below the ODF list functionality is not handled by CSS, but the list labels calculated and written by XSLT. + + REQUIREMENTS: + ============= + + A) + One significant difference between XHTML and Office List elements is that a list without text nodes but only further list children + would not show a list symbol in the Office, but in the browser from XHTML. + + B) + Since OASIS Open Document XML (implemented in OOo2.0) only one parent type exists for list items + the 'text:list' element. The XHTML element 'ol', 'ul' will be chosen upon the list style type. + + C) + An Office list may be spread over the whole document. Linked by their style and text:continue-numbering='true'. + + D) + An Office list can use characters or images as list label. + + E) + An Office list can have a prefix and suffix around the list label. + + F) + An Office list style may have the attribute consecutive numbering, which resolves in a list counting for all levels + + G) + An Office list may (re)start on any arbitrary value by using @text:start-value on the text:list-item + + INDENTATION: + ============ + + The indent of a list label is not only calculated by using the text:space-before of the list level (listLevelStyle), but + as well taking the left margin of the first paragraph (or heading) of the list into account as long it is not negative. + + | MARGIN LEFT | LABEL | CONTENT-PADDING + @text:space-before (1) | @text:min-label-width (1) | @text:min-label-distance (1) + | + @fo:left-margin (firstParagraph) | | + + + (1) all attributes belong to: text:list-style/$listLevelStyle/style:list-level-properties/@* + $listLevelStyle might be one of three choices: + 1) <text:list-level-style-number> + 2) <text:list-level-style-bullet> + 3) <text:list-level-style-image> + + For example: + <text:list-style style:name="Appendix"> + <text:list-level-style-number text:level="1" text:style-name="Zeichenformat" style:num-prefix="Appendix " style:num-suffix=". " style:num-format="A" style:num-letter-sync="true"> + <style:list-level-properties text:min-label-width="0.762cm" text:min-label-distance="0.127cm"/> + </text:list-level-style-number> + <text:list-level-style-number text:level="2" text:style-name="Zeichenformat" style:num-suffix="." style:num-format="1" text:display-levels="2"> + <style:list-level-properties text:min-label-width="1.016cm"/> + </text:list-level-style-number> + --> + <xsl:key name="listStyles" match=" /*/office:styles/text:list-style | /*/office:automatic-styles/text:list-style | /*/office:styles/style:graphic-properties/text:list-style | /*/office:automatic-styles/style:graphic-properties/text:list-style | /*/office:styles/text:list-style | /*/office:automatic-styles/text:list-style | /*/office:styles/style:graphic-properties/text:list-style | /*/office:automatic-styles/style:graphic-properties/text:list-style" use="@style:name"/> + + <!-- + A text list may only have text:list-item and text:list-header as children. + --> + <xsl:template match="text:list"> + <xsl:param name="globalData"/> + <xsl:param name="isListNumberingReset"/> + <xsl:param name="isNextLevelNumberingReset"/> + <xsl:param name="listLevel" select="count(ancestor::text:list) + 1"/> + <xsl:param name="listRestart" select="false()"/> + <xsl:param name="itemLabel" select="''"/> + <xsl:param name="listStyle"/> + <xsl:param name="listStyleName" select="@text:style-name"/> + + <!-- To choose list type - get the list style, with the same 'text:style-name' and same 'text:level' >--> + <xsl:variable name="listStyleRTF"> + <xsl:variable name="listStyleInContentFile" select="key('listStyles', $listStyleName)"/> + <xsl:choose> + <xsl:when test="$listStyleInContentFile"> + <xsl:copy-of select="$listStyleInContentFile"/> + </xsl:when> + <xsl:when test="$globalData/office:styles/text:list-style[@style:name = $listStyleName]"> + <xsl:copy-of select="$globalData/office:styles/text:list-style[@style:name = $listStyleName]"/> + </xsl:when> + <xsl:when test="$globalData/office:styles/style:graphic-properties/text:list-style[@style:name = $listStyleName]"> + <xsl:copy-of select="$globalData/office:styles/style:graphic-properties/text:list-style[@style:name = $listStyleName]"/> + </xsl:when> + </xsl:choose> + </xsl:variable> + + <xsl:choose> + <xsl:when test="function-available('common:node-set')"> + <xsl:call-template name="create-list-type"> + <xsl:with-param name="listStyle" select="common:node-set($listStyleRTF)" /> + <xsl:with-param name="globalData" select="$globalData"/> + <xsl:with-param name="isListNumberingReset" select="$isListNumberingReset"/> + <xsl:with-param name="isNextLevelNumberingReset" select="$isNextLevelNumberingReset"/> + <xsl:with-param name="listLevel" select="$listLevel"/> + <xsl:with-param name="listRestart" select="$listRestart"/> + <xsl:with-param name="itemLabel" select="$itemLabel"/> + <xsl:with-param name="listStyleName" select="$listStyleName" /> + </xsl:call-template> + </xsl:when> + <xsl:when test="function-available('xalan:nodeset')"> + <xsl:call-template name="create-list-type"> + <xsl:with-param name="listStyle" select="xalan:nodeset($listStyleRTF)" /> + <xsl:with-param name="globalData" select="$globalData"/> + <xsl:with-param name="isListNumberingReset" select="$isListNumberingReset"/> + <xsl:with-param name="isNextLevelNumberingReset" select="$isNextLevelNumberingReset"/> + <xsl:with-param name="listLevel" select="$listLevel"/> + <xsl:with-param name="listRestart" select="$listRestart"/> + <xsl:with-param name="itemLabel" select="$itemLabel"/> + <xsl:with-param name="listStyleName" select="$listStyleName" /> + </xsl:call-template> + </xsl:when> + <xsl:when test="function-available('xt:node-set')"> + <xsl:call-template name="create-list-type"> + <xsl:with-param name="listStyle" select="xt:node-set($listStyleRTF)" /> + <xsl:with-param name="globalData" select="$globalData"/> + <xsl:with-param name="isListNumberingReset" select="$isListNumberingReset"/> + <xsl:with-param name="isNextLevelNumberingReset" select="$isNextLevelNumberingReset"/> + <xsl:with-param name="listLevel" select="$listLevel"/> + <xsl:with-param name="listRestart" select="$listRestart"/> + <xsl:with-param name="itemLabel" select="$itemLabel"/> + <xsl:with-param name="listStyleName" select="$listStyleName" /> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:message terminate="yes">The required node-set function was not found!</xsl:message> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <xsl:template name="create-list-type"> + <xsl:param name="globalData"/> + <xsl:param name="isListNumberingReset"/> + <xsl:param name="isNextLevelNumberingReset"/> + <xsl:param name="listLevel" /> + <xsl:param name="listRestart" /> + <xsl:param name="itemLabel"/> + <xsl:param name="listStyle"/> + <xsl:param name="listStyleName" /> + + <!-- $globalData/styles-file/*/office:styles/ --> + <xsl:variable name="listLevelStyle" select="$listStyle/*/*[@text:level = number($listLevel)]"/> + <!-- TODO: Access new list styles + <xsl:variable name="listLevelLabelAlignment1" select="$listLevelStyle/style:list-level-properties/style:list-level-label-alignment"/>--> + <xsl:variable name="listIndent"> + <xsl:call-template name="getListIndent"> + <xsl:with-param name="globalData" select="$globalData"/> + <xsl:with-param name="listLevelStyle" select="$listLevelStyle"/> + <xsl:with-param name="firstPara" select="*[1]/*[name() = 'text:p' or name() = 'text:h'][1]"/> + </xsl:call-template> + </xsl:variable> + <xsl:variable name="isEmptyList" select="not(*[1]/*[name() = 'text:h' or name() = 'text:p' or name() = 'text:name'])"/> + <xsl:variable name="listType"> + <xsl:choose> + <!-- ordered list --> + <xsl:when test="name($listLevelStyle) = 'text:list-level-style-number'"> + <xsl:text>ol</xsl:text> + </xsl:when> + <!-- unordered list (bullet or image) --> + <xsl:otherwise> + <xsl:text>ul</xsl:text> + </xsl:otherwise> + </xsl:choose> + </xsl:variable> + + <xsl:element name="{$listType}"> + <xsl:apply-templates select="*[1]" mode="listItemSibling"> + <xsl:with-param name="globalData" select="$globalData"/> + <xsl:with-param name="isEmptyList" select="$isEmptyList"/> + <xsl:with-param name="isListNumberingReset" select="$isNextLevelNumberingReset"/> + <xsl:with-param name="isNextLevelNumberingReset"> + <xsl:choose> + <xsl:when test="$isListNumberingReset"> + <xsl:value-of select="true()"/> + </xsl:when> + <xsl:otherwise> + <!-- A list is empty if a text:list does not have a text:list-header or text:list-item (wildcard as only those can exist beyond a text:list), which contains a text:h or text:p --> + <xsl:value-of select="not($isEmptyList)"/> + </xsl:otherwise> + </xsl:choose> + </xsl:with-param> + <xsl:with-param name="itemLabel" select="$itemLabel"/> + <xsl:with-param name="listIndent" select="$listIndent"/> + <xsl:with-param name="listLevel" select="$listLevel"/> + <xsl:with-param name="listLevelStyle" select="$listLevelStyle"/> + <xsl:with-param name="listRestart"> + <xsl:choose> + <xsl:when test="$listRestart"> + <xsl:value-of select="$listRestart"/> + </xsl:when> + <xsl:otherwise> + <!-- descendants restart their list numbering, when an ancestor is not empty --> + <xsl:value-of select="not($isEmptyList)"/> + </xsl:otherwise> + </xsl:choose> + </xsl:with-param> + <xsl:with-param name="listStyle" select="$listStyle"/> + <xsl:with-param name="listStyleName" select="$listStyleName"/> + <xsl:with-param name="minLabelDist"> + <xsl:choose> + <xsl:when test="$listLevelStyle/*/@text:min-label-distance"> + <xsl:call-template name="convert2cm"> + <xsl:with-param name="value" select="$listLevelStyle/*/@text:min-label-distance"/> + </xsl:call-template> + </xsl:when> + <xsl:otherwise>0</xsl:otherwise> + </xsl:choose> + </xsl:with-param> + <xsl:with-param name="minLabelWidth"> + <xsl:choose> + <xsl:when test="$listLevelStyle/*/@text:min-label-width"> + <xsl:call-template name="convert2cm"> + <xsl:with-param name="value" select="$listLevelStyle/*/@text:min-label-width"/> + </xsl:call-template> + </xsl:when> + <xsl:otherwise>0</xsl:otherwise> + </xsl:choose> + </xsl:with-param> + </xsl:apply-templates> + </xsl:element> + </xsl:template> + + <!-- See comment before text:list template --> + <xsl:template name="getListIndent"> + <xsl:param name="globalData"/> + <xsl:param name="listLevelStyle"/> + <!-- The first paragraph of the list item (heading is special paragraph in ODF) --> + <xsl:param name="firstPara" /> + + <!-- Styles of first paragraph in list item, including ancestor styles (inheritance) --> + <xsl:variable name="firstParaStyles" select="$globalData/all-styles/style[@style:name = $firstPara/@text:style-name]/final-properties"/> + + <!-- Only the left margin of the first paragraph of a list item will be added to the margin of the complete list (all levels)--> + <xsl:variable name="firstParaLeftMargin"> + <xsl:choose> + <xsl:when test="contains($firstParaStyles, 'margin-left:')"> + <xsl:call-template name="convert2cm"> + <xsl:with-param name="value" select="normalize-space(substring-before(substring-after($firstParaStyles, 'margin-left:'), ';'))"/> + </xsl:call-template> + </xsl:when> + <xsl:otherwise>0</xsl:otherwise> + </xsl:choose> + </xsl:variable> + <xsl:variable name="spaceBefore"> + <xsl:choose> + <xsl:when test="$listLevelStyle/*/@text:space-before"> + <xsl:call-template name="convert2cm"> + <xsl:with-param name="value" select="$listLevelStyle/*/@text:space-before"/> + </xsl:call-template> + </xsl:when> + <xsl:otherwise>0</xsl:otherwise> + </xsl:choose> + </xsl:variable> + <!-- Only if the left-margin of the first paragraph is positive the sum + text:space-before and fo:left-margin is taken as list indent --> + <xsl:choose> + <xsl:when test="$firstParaLeftMargin > 0"> + <xsl:value-of select="$firstParaLeftMargin + $spaceBefore"/> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="$spaceBefore"/> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <!-- ****************** --> + <!-- *** list item *** --> + <!-- ****************** --> +<!-- + Left margin of the complete list: + The space between left page and the list symbol (left-margin) is in the Office implemented by + the sum of three values: + 1) 'text:space-before', which is part of the 'text:list-style' element. + 2) 'margin:left' from the style of the first child (e.g. paragraph). + 3) 'fo:text-indent' the indent of the first line of some child (e.g. paragraph) (applied by CSS class style) + + Possible list children: + <!ELEMENT text:list-item (text:p|text:h|text:list)+> + + In the Office the list label before the text depends on two attributes: + - 'text:min-label-width': the distance between list label and all text of the list item. + - 'text:min-label-distance': the distance between list label and text of the first line, + only used, when text does not fit in text:min-label-width (ignored) + +--> + <xsl:template match="text:list-item | text:list-header" mode="listItemSibling"> + <xsl:param name="globalData"/> + <xsl:param name="firstitemLabelWidth"/> + <xsl:param name="isEmptyList" select="not(*[name() = 'text:h' or name() = 'text:p' or name() = 'text:name'])"/> + <xsl:param name="isListNumberingReset"/> + <xsl:param name="isNextLevelNumberingReset"/> + <xsl:param name="itemNumber"/> + <xsl:param name="itemLabel"/> + <xsl:param name="listLevel"/> + <xsl:param name="listLevelStyle"/> + <xsl:param name="listRestart"/> + <xsl:param name="listStyle"/> + <xsl:param name="listStyleName"/> + <xsl:param name="minLabelDist"/> + <xsl:param name="minLabelWidth"/> + <xsl:param name="listIndent" /> + + <!-- The text:list-header shall not be labeled. According to ODF specification (sect. 4.3.2): + "The <text:list-header> element represents a list header and is a special kind of list item. It + contains one or more paragraphs that are displayed before a list. The paragraphs are formatted + like list items but they do not have a preceding number or bullet." --> + <xsl:variable name="isListHeader" select="boolean(self::text:list-header)"/> + + <xsl:variable name="listIndentNew"> + <xsl:choose> + <xsl:when test="$listIndent"> + <xsl:value-of select="$listIndent"/> + </xsl:when> + <xsl:otherwise> + <xsl:call-template name="getListIndent"> + <xsl:with-param name="globalData" select="$globalData"/> + <xsl:with-param name="listLevelStyle" select="$listLevelStyle"/> + <xsl:with-param name="firstPara" select="*[name() = 'text:p' or name() = 'text:h'][1]" /> + </xsl:call-template> + </xsl:otherwise> + </xsl:choose> + </xsl:variable> + <xsl:variable name="itemNumberNew"> + <xsl:if test="$listStyle/text:list-style/text:list-level-style-number"> + <xsl:choose> + <xsl:when test="$isListHeader">0</xsl:when> + <xsl:when test="$isEmptyList"> + <!-- An empty list item (no text:h/text:p as child), will not count as item and does not increment the count. --> + <xsl:variable name="tempItemNumber"> + <xsl:choose> + <!-- siblings will be incremented by one --> + <xsl:when test="$itemNumber"> + <xsl:if test="not($isListHeader)"> + <xsl:value-of select="$itemNumber + 1"/> + </xsl:if> + </xsl:when> + <!-- if a higher list level had content the numbering starts with 1 --> + <xsl:when test="$isListNumberingReset and $listLevel > 1"> + <xsl:value-of select="1"/> + </xsl:when> + <xsl:otherwise> + <xsl:call-template name="getItemNumber"> + <xsl:with-param name="listStyleName" select="$listStyleName"/> + <xsl:with-param name="listLevel" select="$listLevel"/> + <xsl:with-param name="listLevelStyle" select="$listLevelStyle"/> + <xsl:with-param name="listStyle" select="$listStyle"/> + </xsl:call-template> + </xsl:otherwise> + </xsl:choose> + </xsl:variable> + <xsl:choose> + <!-- in case the empty list-item is the first list-item in document --> + <xsl:when test="$tempItemNumber = 1"> + <xsl:value-of select="1"/> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="$tempItemNumber - 1"/> + </xsl:otherwise> + </xsl:choose> + </xsl:when> + <xsl:otherwise> + <xsl:choose> + <xsl:when test="@text:start-value"> + <xsl:value-of select="@text:start-value"/> + </xsl:when> + <!-- text:start-value from list level style will only be taken on the first list-item of a list --> + <xsl:when test="$listLevelStyle/@text:start-value and count(preceding-sibling::text:list-item) = 0"> + <xsl:value-of select="$listLevelStyle/@text:start-value"/> + </xsl:when> + <!-- siblings will be incremented by one --> + <xsl:when test="$itemNumber"> + <xsl:value-of select="$itemNumber + 1"/> + </xsl:when> + <!-- if a higher list level had content the numbering starts with 1 --> + <xsl:when test="$isListNumberingReset and $listLevel > 1"> + <xsl:value-of select="1"/> + </xsl:when> + <xsl:otherwise> + <xsl:call-template name="getItemNumber"> + <xsl:with-param name="listStyleName" select="$listStyleName"/> + <xsl:with-param name="listLevel" select="$listLevel"/> + <xsl:with-param name="listLevelStyle" select="$listLevelStyle"/> + <xsl:with-param name="listStyle" select="$listStyle"/> + </xsl:call-template> + </xsl:otherwise> + </xsl:choose> + </xsl:otherwise> + </xsl:choose> + </xsl:if> + </xsl:variable> + <xsl:variable name="itemLabelNew"> + <xsl:if test="$listStyle/text:list-style/text:list-level-style-number"> + <!-- + A numbered label (e.g. 2.C.III) is created for every text:list-item/header. + Above list levels are listed in the label, if the list-style requires this. Levels are separated by @style:num-suffix + Formatation is dependent for every list level depth. + The label is passed from ancestor text:list-item/header and if required truncated. + The prefix/suffix (as well list level dependent) comes before and after the complete label (after truncation) + --> + <!-- Numbered label will be generated --> + <xsl:call-template name="createItemLabel"> + <xsl:with-param name="itemNumber" select="$itemNumberNew"/> + <xsl:with-param name="itemLabel" select="$itemLabel"/> + <xsl:with-param name="listLevelsToDisplay"> + <xsl:variable name="display" select="$listLevelStyle/@text:display-levels"/> + <xsl:choose> + <xsl:when test="$display"> + <xsl:value-of select="$display"/> + </xsl:when> + <xsl:when test="$isListHeader">0</xsl:when> + <xsl:otherwise>1</xsl:otherwise> + </xsl:choose> + </xsl:with-param> + <xsl:with-param name="listLevel" select="$listLevel"/> + <xsl:with-param name="listLevelStyle" select="$listLevelStyle"/> + <xsl:with-param name="listStyleName" select="$listStyleName"/> + </xsl:call-template> + </xsl:if> + </xsl:variable> + <xsl:element name="li"> + <xsl:choose> + <xsl:when test="$isEmptyList or $isListHeader"> + <xsl:apply-templates> + <xsl:with-param name="globalData" select="$globalData"/> + <xsl:with-param name="itemLabel" select="$itemLabelNew"/> + <xsl:with-param name="listLevel" select="$listLevel + 1"/> + <xsl:with-param name="listStyleName" select="$listStyleName"/> + </xsl:apply-templates> + </xsl:when> + <xsl:otherwise> + <!-- Possible following children are text:h, text:p, list:text, text:soft-page-break --> + <xsl:apply-templates mode="list-item-children" select="*[1]"> + <xsl:with-param name="globalData" select="$globalData"/> + <xsl:with-param name="isEmptyList" select="$isEmptyList"/> + <xsl:with-param name="isNextLevelNumberingReset" select="$isListHeader or $isNextLevelNumberingReset"/> + <!-- The new created label is given to the children --> + <xsl:with-param name="itemLabel" select="$itemLabelNew"/> + <xsl:with-param name="listLabelElement"> + <xsl:choose> + <xsl:when test="name() = 'text:list-header'"/> + <xsl:otherwise> + <xsl:variable name="listLabelWidth"> + <xsl:choose> + <xsl:when test="$minLabelWidth"> + <xsl:value-of select="$minLabelWidth"/> + </xsl:when> + <xsl:otherwise> + <xsl:variable name="listLevelLabelAlignment" select="$listLevelStyle/style:list-level-properties/style:list-level-label-alignment"/> + <xsl:variable name="listLevelTextIndent"> + <xsl:call-template name="convert2cm"> + <xsl:with-param name="value" select="string($listLevelLabelAlignment/@fo:text-indent)"/> + </xsl:call-template> + </xsl:variable> + <!-- TODO: Access new ODF 1.2 list styles + <xsl:variable name="listLevelTextIndent"> + <xsl:call-template name="convert2cm"> + <xsl:with-param name="value" select="string($listLevelLabelAlignment/@text:list-tab-stop-position)"/> + </xsl:call-template> + </xsl:variable> --> + <xsl:value-of select="-$listLevelTextIndent"/> + </xsl:otherwise> + </xsl:choose> + </xsl:variable> + <!-- Numbering is being done by this transformation creating a HTML span representing the number label + The html:span represents the list item/header label (e.g. 1.A.III) + As the html:span is usually an inline element is formatted by CSS as block element to use width upon it, + to disable the carriage return float:left is used and later neglected --> + <xsl:element name="span"> + <xsl:if test="$listLevelStyle/@text:style-name"> + <xsl:attribute name="class"> + <xsl:value-of select="$listLevelStyle/@text:style-name"/> + </xsl:attribute> + </xsl:if> + <xsl:attribute name="style"> + <xsl:text>display:block;float:</xsl:text> + <!-- TODO: Svante - copy this functionality for other used margin:left (in western country 'left') --> + <xsl:call-template name="getOppositeWritingDirection"> + <xsl:with-param name="globalData" select="$globalData"/> + <xsl:with-param name="paraStyleName" select="descendant-or-self::*/@text:style-name"/> + </xsl:call-template> + <xsl:text>;min-width:</xsl:text> + <xsl:choose> + <xsl:when test="$listLabelWidth and not($listLabelWidth='') and not($listLabelWidth='NaN')"> + <xsl:value-of select="translate($listLabelWidth,',','.')"/> + </xsl:when> + <xsl:otherwise>0</xsl:otherwise> + </xsl:choose> + <xsl:text>cm;</xsl:text> + <xsl:if test="$minLabelDist > 0"> + <xsl:text>padding-right:</xsl:text><xsl:value-of select="$minLabelDist"/><xsl:text>cm;</xsl:text> + </xsl:if> + </xsl:attribute> + <xsl:variable name="labelContent"> + <xsl:choose> + <xsl:when test="text:number"> + <xsl:apply-templates select="text:number" mode="listnumber"/> + </xsl:when> + <xsl:when test="name($listLevelStyle) = 'text:list-level-style-bullet'"> + <xsl:value-of select="$listLevelStyle/@style:num-prefix"/> + <xsl:value-of select="$listLevelStyle/@text:bullet-char"/> + <xsl:value-of select="$listLevelStyle/@style:num-suffix"/> + </xsl:when> + <xsl:when test="name($listLevelStyle) = 'text:list-level-style-number'"> + <xsl:value-of select="$listLevelStyle/@style:num-prefix"/> + <xsl:value-of select="$itemLabelNew"/> + <xsl:value-of select="$listLevelStyle/@style:num-suffix"/> + </xsl:when> + <xsl:otherwise> + <!-- Listing with image as bullets, taken from the list style's href --> + <xsl:value-of select="$listLevelStyle/@xlink:href"/> + </xsl:otherwise> + </xsl:choose> + </xsl:variable> + <!-- Some browsers have problem with stand-alone elements (e.g. <span/>) + Therefore a comment is being inserted into an empty label --> + <xsl:choose> + <xsl:when test="$labelContent != ''"> + <xsl:value-of select="$labelContent"/> + </xsl:when> + <xsl:otherwise> + <xsl:comment> </xsl:comment> + </xsl:otherwise> + </xsl:choose> + </xsl:element> + </xsl:otherwise> + </xsl:choose> + </xsl:with-param> + <xsl:with-param name="listLabelEmptyElement"> + <xsl:element name="span"> + <xsl:if test="$listLevelStyle/@text:style-name"> + <xsl:attribute name="class"> + <xsl:value-of select="$listLevelStyle/@text:style-name"/> + </xsl:attribute> + </xsl:if> + <xsl:attribute name="style"> + <xsl:text>display:block;float:</xsl:text> + <xsl:call-template name="getOppositeWritingDirection"> + <xsl:with-param name="globalData" select="$globalData"/> + <xsl:with-param name="paraStyleName" select="descendant-or-self::*/@text:style-name"/> + </xsl:call-template> + <xsl:text>;min-width:</xsl:text> + <xsl:choose> + <xsl:when test="$minLabelWidth and not($minLabelWidth='') and not($minLabelWidth='NaN')"> + <xsl:value-of select="translate($minLabelWidth,',','.')"/> + </xsl:when> + <xsl:otherwise>0</xsl:otherwise> + </xsl:choose> + <xsl:text>cm</xsl:text> + <xsl:if test="$minLabelDist > 0"> + <xsl:text>padding-right:</xsl:text><xsl:value-of select="$minLabelDist"/><xsl:text>cm;</xsl:text> + </xsl:if> + </xsl:attribute> + <xsl:comment> </xsl:comment> + </xsl:element> + </xsl:with-param> + <xsl:with-param name="listLevel" select="$listLevel + 1"/> + <xsl:with-param name="listLevelStyle" select="$listLevelStyle"/> + <xsl:with-param name="listRestart" select="$listRestart"/> + <xsl:with-param name="listStyle" select="$listStyle"/> + <xsl:with-param name="listStyleName" select="$listStyleName"/> + <xsl:with-param name="listIndent" select="$listIndentNew"/> + <xsl:with-param name="minLabelWidth" select="$minLabelWidth"/> + </xsl:apply-templates> + </xsl:otherwise> + </xsl:choose> + </xsl:element> + <xsl:apply-templates select="following-sibling::*[1]" mode="listItemSibling"> + <xsl:with-param name="globalData" select="$globalData"/> + <xsl:with-param name="isListNumberingReset" select="$isListNumberingReset"/> + <xsl:with-param name="isNextLevelNumberingReset" select="$isNextLevelNumberingReset"/> + <xsl:with-param name="itemNumber" select="$itemNumberNew"/> + <xsl:with-param name="listIndent"> + <xsl:choose> + <xsl:when test="not($isEmptyList)"> + <xsl:value-of select="$listIndentNew"/> + </xsl:when> + </xsl:choose> + </xsl:with-param> + <!-- Receives the same parent label --> + <xsl:with-param name="itemLabel" select="$itemLabel"/> + <xsl:with-param name="listLevel" select="$listLevel"/> + <xsl:with-param name="listLevelStyle" select="$listLevelStyle"/> + <xsl:with-param name="listStyle" select="$listStyle"/> + <xsl:with-param name="listStyleName" select="$listStyleName"/> + <xsl:with-param name="minLabelDist" select="$minLabelDist"/> + <xsl:with-param name="minLabelWidth" select="$minLabelWidth"/> + </xsl:apply-templates> + </xsl:template> + + <xsl:template name="getOppositeWritingDirection"> + <xsl:param name="globalData"/> + <xsl:param name="paraStyleName"/> + + <xsl:variable name="imageParagraphStyle" select="$globalData/all-styles/style[@style:name = $paraStyleName]/final-properties"/> + + <xsl:choose> + <xsl:when test="contains($imageParagraphStyle, 'writing-mode:')"> + <xsl:choose> + <xsl:when test="contains(substring-before(substring-after($imageParagraphStyle, 'writing-mode:'), ';'), 'rl')">right</xsl:when> + <xsl:otherwise>left</xsl:otherwise> + </xsl:choose> + </xsl:when> + <xsl:otherwise>left</xsl:otherwise> + </xsl:choose> + </xsl:template> + + <xsl:template match="text:number" mode="listnumber"> + <xsl:apply-templates/> + </xsl:template> + + <xsl:template match="text:number" mode="list-item-children"> + <xsl:param name="globalData"/> + <xsl:param name="listLabelElement"/> + <xsl:param name="listLabelEmptyElement"/> + <xsl:param name="isEmptyList"/> + <xsl:param name="isListNumberingReset"/> + <xsl:param name="isNextLevelNumberingReset"/> + <xsl:param name="itemLabel"/> + <xsl:param name="itemNumber"/> + <xsl:param name="listIndent"/> + <xsl:param name="listLevel"/> + <xsl:param name="listLevelStyle" /> + <xsl:param name="listRestart"/> + <xsl:param name="listStyle"/> + <xsl:param name="listStyleName"/> + <xsl:param name="minLabelWidth"/> + <xsl:param name="minLabelDist"/> + + <xsl:apply-templates mode="list-item-children" select="following-sibling::*[1]"> + <xsl:with-param name="globalData" select="$globalData"/> + <xsl:with-param name="isEmptyList" select="$isEmptyList"/> + <xsl:with-param name="isNextLevelNumberingReset" select="$isNextLevelNumberingReset"/> + <xsl:with-param name="itemLabel" select="$itemLabel"/> + <xsl:with-param name="listLabelElement" select="$listLabelElement"/> + <xsl:with-param name="listLabelEmptyElement" select="$listLabelEmptyElement"/> + <xsl:with-param name="listLevel" select="$listLevel"/> + <xsl:with-param name="listLevelStyle" select="$listLevelStyle"/> + <xsl:with-param name="listRestart" select="$listRestart"/> + <xsl:with-param name="listStyle" select="$listStyle"/> + <xsl:with-param name="listStyleName" select="$listStyleName"/> + <xsl:with-param name="listIndent" select="$listIndent"/> + <xsl:with-param name="minLabelWidth" select="$minLabelWidth"/> + <xsl:with-param name="minLabelDist" select="$minLabelDist"/> + </xsl:apply-templates> + </xsl:template> + + <!-- Each key element holds the set of all text:list-item/text:list-header of a certain level and a certain style --> + <xsl:key name="getListItemsByLevelAndStyle" use="concat(count(ancestor::text:list), ancestor::text:list/@text:style-name)" match="text:list-item | text:list-header"/> + <!-- Each key element holds the set of all text:list-item/text:list-header of a certain style --> + <xsl:key name="getListItemsByStyle" use="ancestor::text:list/@text:style-name" match="text:list-item | text:list-header"/> + + + <!-- The Numbering start value (or offset from regular counteing) is used at the first item of offset, + but have to be reused on following items with no text:start-value --> + <xsl:template name="getItemNumber"> + <xsl:param name="listLevel"/> + <xsl:param name="listLevelStyle"/> + <xsl:param name="listStyleName"/> + <xsl:param name="listStyle"/> + + <xsl:call-template name="countListItemTillStartValue"> + <xsl:with-param name="listLevel" select="$listLevel"/> + <xsl:with-param name="listLevelStyle" select="$listLevelStyle"/> + <xsl:with-param name="listStyleName" select="$listStyleName"/> + <xsl:with-param name="listStyle" select="$listStyle"/> + <xsl:with-param name="precedingListItemsOfSameLevelAndStyle" select="preceding::text:list-item[generate-id(key('getListItemsByLevelAndStyle', concat($listLevel, $listStyleName))) = generate-id(key('getListItemsByLevelAndStyle', concat(count(ancestor::text:list), ancestor::text:list/@text:style-name)))]"/> + + <xsl:with-param name="precedingListItemsOfSameStyle" select="preceding::text:list-item[generate-id(key('getListItemsByStyle', $listStyleName)) = generate-id(key('getListItemsByStyle', ancestor::text:list/@text:style-name))]"/> + </xsl:call-template> + </xsl:template> + + <!-- When there is a text:start-value the last have to be found and added to the number --> + <xsl:template name="countListItemTillStartValue"> + <xsl:param name="IteratorSameLevelAndStyle" select="1"/> + <xsl:param name="IteratorSameStyle" select="1"/> + <xsl:param name="itemNumber" select="1"/> + <xsl:param name="listLevel"/> + <xsl:param name="listLevelStyle"/> + <xsl:param name="listStyle"/> + <xsl:param name="listStyleName"/> + <xsl:param name="precedingListItemsOfSameLevelAndStyle" /> + <xsl:param name="precedingListItemsOfSameLevelAndStyleCount" select="count($precedingListItemsOfSameLevelAndStyle)"/> + <xsl:param name="precedingListItemsOfSameStyle" /> + <xsl:param name="precedingListItemsOfSameStyleCount" select="count($precedingListItemsOfSameStyle)"/> + <!-- E.g.: If a list level 2 number is searched, a level 3 with content found with only a level 1 parent with content, + the level 3 gets a 'pseudoLevel' --> + <xsl:param name="pseudoLevel" select="0" /> + + <xsl:variable name="isListHeader" select="boolean(self::text:list-header)"/> + <xsl:variable name="isEmptyList" select="not(*[name() = 'text:h' or name() = 'text:p'])"/> + + <!-- set the next of preceding list items. Starting from the current to the next previous text:list-item --> + <xsl:variable name="precedingListItemOfSameLevelAndStyle" select="$precedingListItemsOfSameLevelAndStyle[$precedingListItemsOfSameLevelAndStyleCount - $IteratorSameLevelAndStyle + 1]"/> + <xsl:variable name="precedingListItemOfSameStyle" select="$precedingListItemsOfSameStyle[$precedingListItemsOfSameStyleCount - $IteratorSameStyle + 1]"/> + <xsl:choose> + <xsl:when test="($precedingListItemOfSameStyle and $precedingListItemOfSameLevelAndStyle) or ($precedingListItemOfSameStyle and $listStyle/text:list-style/@text:consecutive-numbering)"> + <xsl:for-each select="$precedingListItemOfSameStyle"> + <xsl:choose> + <!-- if it is a higher list level element --> + <xsl:when test="$listStyle/text:list-style/@text:consecutive-numbering"> + + <xsl:call-template name="countListItem"> + <xsl:with-param name="IteratorSameLevelAndStyle" select="$IteratorSameLevelAndStyle" /> + <xsl:with-param name="IteratorSameStyle" select="$IteratorSameStyle"/> + <xsl:with-param name="itemNumber" select="$itemNumber"/> + <xsl:with-param name="listLevel" select="$listLevel"/> + <xsl:with-param name="listLevelStyle" select="$listLevelStyle"/> + <xsl:with-param name="listStyle" select="$listStyle"/> + <xsl:with-param name="precedingListItemsOfSameLevelAndStyle" select="$precedingListItemsOfSameLevelAndStyle"/> + <xsl:with-param name="precedingListItemsOfSameLevelAndStyleCount" select="$precedingListItemsOfSameLevelAndStyleCount"/> + <xsl:with-param name="precedingListItemsOfSameStyle" select="$precedingListItemsOfSameStyle"/> + <xsl:with-param name="precedingListItemsOfSameStyleCount" select="$precedingListItemsOfSameStyleCount"/> + <xsl:with-param name="pseudoLevel" select="$pseudoLevel" /> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <!-- NOT CONSECUTIVE NUMBERING --> + <xsl:variable name="currentListLevel" select="count(ancestor::text:list)"/> + <xsl:choose> + <!-- IF IT IS A HIGHER LIST LEVEL ELEMENT --> + <xsl:when test="$currentListLevel < $listLevel"> + <xsl:choose> + <!-- if it has content the counting is ended --> + <xsl:when test="*[name() = 'text:h' or name() = 'text:p'] or $isListHeader"> + <!-- TODO: Perhaps the children still have to be processed --> + <xsl:value-of select="$itemNumber + $pseudoLevel"/> + </xsl:when> + <xsl:otherwise> + <!-- if it is empty the counting continues --> + <xsl:call-template name="countListItemTillStartValue"> + <xsl:with-param name="IteratorSameLevelAndStyle" select="$IteratorSameLevelAndStyle" /> + <xsl:with-param name="IteratorSameStyle" select="$IteratorSameStyle + 1"/> + <xsl:with-param name="itemNumber" select="$itemNumber"/> + <xsl:with-param name="listLevel" select="$listLevel"/> + <xsl:with-param name="listLevelStyle" select="$listLevelStyle"/> + <xsl:with-param name="listStyle" select="$listStyle"/> + <xsl:with-param name="precedingListItemsOfSameLevelAndStyle" select="$precedingListItemsOfSameLevelAndStyle"/> + <xsl:with-param name="precedingListItemsOfSameLevelAndStyleCount" select="$precedingListItemsOfSameLevelAndStyleCount"/> + <xsl:with-param name="precedingListItemsOfSameStyle" select="$precedingListItemsOfSameStyle"/> + <xsl:with-param name="precedingListItemsOfSameStyleCount" select="$precedingListItemsOfSameStyleCount"/> + <xsl:with-param name="pseudoLevel" select="$pseudoLevel" /> + </xsl:call-template> + </xsl:otherwise> + </xsl:choose> + </xsl:when> + <!-- IF IT IS A LIST LEVEL ELEMENT OF THE COUNTING LEVEL --> + <xsl:when test="$currentListLevel = $listLevel"> + <xsl:call-template name="countListItem"> + <xsl:with-param name="IteratorSameLevelAndStyle" select="$IteratorSameLevelAndStyle" /> + <xsl:with-param name="IteratorSameStyle" select="$IteratorSameStyle"/> + <xsl:with-param name="itemNumber" select="$itemNumber"/> + <xsl:with-param name="listLevel" select="$listLevel"/> + <xsl:with-param name="listLevelStyle" select="$listLevelStyle"/> + <xsl:with-param name="listStyle" select="$listStyle"/> + <xsl:with-param name="precedingListItemsOfSameLevelAndStyle" select="$precedingListItemsOfSameLevelAndStyle"/> + <xsl:with-param name="precedingListItemsOfSameLevelAndStyleCount" select="$precedingListItemsOfSameLevelAndStyleCount"/> + <xsl:with-param name="precedingListItemsOfSameStyle" select="$precedingListItemsOfSameStyle"/> + <xsl:with-param name="precedingListItemsOfSameStyleCount" select="$precedingListItemsOfSameStyleCount"/> + <xsl:with-param name="pseudoLevel" select="$pseudoLevel" /> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <!-- list item below the current level does not count --> + <xsl:call-template name="countListItemTillStartValue"> + <xsl:with-param name="IteratorSameLevelAndStyle" select="$IteratorSameLevelAndStyle" /> + <xsl:with-param name="IteratorSameStyle" select="$IteratorSameStyle + 1"/> + <xsl:with-param name="itemNumber" select="$itemNumber"/> + <xsl:with-param name="listLevel" select="$listLevel"/> + <xsl:with-param name="listLevelStyle" select="$listLevelStyle"/> + <xsl:with-param name="listStyle" select="$listStyle"/> + <xsl:with-param name="listStyleName" select="$listStyleName"/> + <xsl:with-param name="precedingListItemsOfSameLevelAndStyle" select="$precedingListItemsOfSameLevelAndStyle"/> + <xsl:with-param name="precedingListItemsOfSameLevelAndStyleCount" select="$precedingListItemsOfSameLevelAndStyleCount"/> + <xsl:with-param name="precedingListItemsOfSameStyle" select="$precedingListItemsOfSameStyle"/> + <xsl:with-param name="precedingListItemsOfSameStyleCount" select="$precedingListItemsOfSameStyleCount"/> + <xsl:with-param name="pseudoLevel"> + <xsl:choose> + <!-- empty list item does not count --> + <xsl:when test="not(*[name() = 'text:h' or name() = 'text:p']) or $isListHeader"> + <xsl:value-of select="$pseudoLevel"/> + </xsl:when> + <xsl:otherwise>1</xsl:otherwise> + </xsl:choose> + </xsl:with-param> + </xsl:call-template> + </xsl:otherwise> + </xsl:choose> + </xsl:otherwise> + </xsl:choose> + </xsl:for-each> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="$itemNumber"/> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <xsl:template name="countListItem"> + <xsl:param name="IteratorSameLevelAndStyle"/> + <xsl:param name="IteratorSameStyle"/> + <xsl:param name="itemNumber"/> + <xsl:param name="listLevel"/> + <xsl:param name="listLevelStyle"/> + <xsl:param name="listStyle"/> + <xsl:param name="listStyleName"/> + <xsl:param name="precedingListItemsOfSameLevelAndStyle"/> + <xsl:param name="precedingListItemsOfSameLevelAndStyleCount"/> + <xsl:param name="precedingListItemsOfSameStyle"/> + <xsl:param name="precedingListItemsOfSameStyleCount"/> + <xsl:param name="pseudoLevel" /> + + <xsl:variable name="isListHeader" select="boolean(self::text:list-header)"/> + <xsl:variable name="isEmptyList" select="not(*[name() = 'text:h' or name() = 'text:p'])"/> + + <xsl:choose> + <xsl:when test="@text:start-value"> + <xsl:choose> + <xsl:when test="$isEmptyList or $isListHeader"> + <!-- empty list item does not count. neither does list header --> + <xsl:call-template name="countListItemTillStartValue"> + <xsl:with-param name="IteratorSameLevelAndStyle" select="$IteratorSameLevelAndStyle + 1" /> + <xsl:with-param name="IteratorSameStyle" select="$IteratorSameStyle + 1"/> + <xsl:with-param name="itemNumber" select="$itemNumber"/> + <xsl:with-param name="listLevel" select="$listLevel"/> + <xsl:with-param name="listLevelStyle" select="$listLevelStyle"/> + <xsl:with-param name="listStyle" select="$listStyle"/> + <xsl:with-param name="precedingListItemsOfSameLevelAndStyle" select="$precedingListItemsOfSameLevelAndStyle"/> + <xsl:with-param name="precedingListItemsOfSameLevelAndStyleCount" select="$precedingListItemsOfSameLevelAndStyleCount"/> + <xsl:with-param name="precedingListItemsOfSameStyle" select="$precedingListItemsOfSameStyle"/> + <xsl:with-param name="precedingListItemsOfSameStyleCount" select="$precedingListItemsOfSameStyleCount"/> + <xsl:with-param name="pseudoLevel" select="$pseudoLevel" /> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="$itemNumber + @text:start-value"/> + </xsl:otherwise> + </xsl:choose> + </xsl:when> + <xsl:when test="$listLevelStyle/@text:start-value"> + <xsl:choose> + <xsl:when test="$isEmptyList or $isListHeader"> + <!-- empty list item does not count. neither does list header --> + <xsl:call-template name="countListItemTillStartValue"> + <xsl:with-param name="IteratorSameLevelAndStyle" select="$IteratorSameLevelAndStyle + 1" /> + <xsl:with-param name="IteratorSameStyle" select="$IteratorSameStyle + 1"/> + <xsl:with-param name="itemNumber" select="$itemNumber"/> + <xsl:with-param name="listLevel" select="$listLevel"/> + <xsl:with-param name="listLevelStyle" select="$listLevelStyle"/> + <xsl:with-param name="listStyle" select="$listStyle"/> + <xsl:with-param name="precedingListItemsOfSameLevelAndStyle" select="$precedingListItemsOfSameLevelAndStyle"/> + <xsl:with-param name="precedingListItemsOfSameLevelAndStyleCount" select="$precedingListItemsOfSameLevelAndStyleCount"/> + <xsl:with-param name="precedingListItemsOfSameStyle" select="$precedingListItemsOfSameStyle"/> + <xsl:with-param name="precedingListItemsOfSameStyleCount" select="$precedingListItemsOfSameStyleCount"/> + <xsl:with-param name="pseudoLevel" select="$pseudoLevel" /> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="$itemNumber + $listLevelStyle/@text:start-value"/> + </xsl:otherwise> + </xsl:choose> + </xsl:when> + <xsl:otherwise> + <xsl:choose> + <xsl:when test="$isEmptyList or $isListHeader"> + <!-- empty list item does not count. neither does list header --> + <xsl:call-template name="countListItemTillStartValue"> + <xsl:with-param name="IteratorSameLevelAndStyle" select="$IteratorSameLevelAndStyle + 1" /> + <xsl:with-param name="IteratorSameStyle" select="$IteratorSameStyle + 1"/> + <xsl:with-param name="itemNumber" select="$itemNumber"/> + <xsl:with-param name="listLevel" select="$listLevel"/> + <xsl:with-param name="listLevelStyle" select="$listLevelStyle"/> + <xsl:with-param name="listStyle" select="$listStyle"/> + <xsl:with-param name="precedingListItemsOfSameLevelAndStyle" select="$precedingListItemsOfSameLevelAndStyle"/> + <xsl:with-param name="precedingListItemsOfSameLevelAndStyleCount" select="$precedingListItemsOfSameLevelAndStyleCount"/> + <xsl:with-param name="precedingListItemsOfSameStyle" select="$precedingListItemsOfSameStyle"/> + <xsl:with-param name="precedingListItemsOfSameStyleCount" select="$precedingListItemsOfSameStyleCount"/> + <xsl:with-param name="pseudoLevel" select="$pseudoLevel" /> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <!-- count on till you find a start-value or the end is reached --> + <xsl:call-template name="countListItemTillStartValue"> + <xsl:with-param name="IteratorSameLevelAndStyle" select="$IteratorSameLevelAndStyle + 1" /> + <xsl:with-param name="IteratorSameStyle" select="$IteratorSameStyle + 1"/> + <xsl:with-param name="itemNumber" select="$itemNumber + 1"/> + <xsl:with-param name="listLevel" select="$listLevel"/> + <xsl:with-param name="listLevelStyle" select="$listLevelStyle"/> + <xsl:with-param name="listStyle" select="$listStyle"/> + <xsl:with-param name="precedingListItemsOfSameLevelAndStyle" select="$precedingListItemsOfSameLevelAndStyle"/> + <xsl:with-param name="precedingListItemsOfSameLevelAndStyleCount" select="$precedingListItemsOfSameLevelAndStyleCount"/> + <xsl:with-param name="precedingListItemsOfSameStyle" select="$precedingListItemsOfSameStyle"/> + <xsl:with-param name="precedingListItemsOfSameStyleCount" select="$precedingListItemsOfSameStyleCount"/> + <xsl:with-param name="pseudoLevel" select="0" /> + </xsl:call-template> + </xsl:otherwise> + </xsl:choose> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + + <!-- Creates the list label containing the number, which is separated by '.' between the levels. + Depending on the levels to display (listLevelsToDisplay) --> + <xsl:template name="createItemLabel"> + <xsl:param name="itemLabel" select="''"/> + <xsl:param name="itemNumber" /> + <xsl:param name="listLevel" /> + <xsl:param name="listLevelStyle" /> + <xsl:param name="listLevelsToDisplay" /> + + <xsl:choose> + <xsl:when test="$listLevelsToDisplay < $listLevel"> + <xsl:call-template name="truncLabel"> + <xsl:with-param name="itemLabel" select="$itemLabel"/> + <xsl:with-param name="itemNumber" select="$itemNumber" /> + <xsl:with-param name="listLevel" select="$listLevel"/> + <xsl:with-param name="listLevelStyle" select="$listLevelStyle" /> + <xsl:with-param name="listLevelsToDisplay" select="$listLevelsToDisplay"/> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:variable name="numberedSymbol"> + <!-- only give out a number when number format is not empty --> + <xsl:if test="$listLevelStyle/@style:num-format != ''"> + <xsl:number value="$itemNumber" format="{$listLevelStyle/@style:num-format}"/> + </xsl:if> + </xsl:variable> + <xsl:choose> + <xsl:when test="$listLevelsToDisplay != 1"> + <xsl:value-of select="concat($itemLabel, $listLevelStyle/@style:num-prefix , $numberedSymbol, $listLevelStyle/@style:num-suffix)"/> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="concat($listLevelStyle/@style:num-prefix , $numberedSymbol, $listLevelStyle/@style:num-suffix)"/> + </xsl:otherwise> + </xsl:choose> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <xsl:template name="truncLabel"> + <xsl:param name="itemLabel" /> + <xsl:param name="itemNumber" /> + <xsl:param name="listLevel" /> + <xsl:param name="listLevelStyle" /> + <xsl:param name="listLevelsToDisplay" /> + <xsl:param name="listStyle" /> + <xsl:param name="listStyleName" /> + + <xsl:call-template name="createItemLabel"> + <xsl:with-param name="itemLabel"> + <xsl:if test="contains($itemLabel, '.')"> + <xsl:value-of select="substring-after($itemLabel, '.')"/> + </xsl:if> + </xsl:with-param> + <xsl:with-param name="itemNumber" select="$itemNumber"/> + <xsl:with-param name="listLevel" select="$listLevel - 1"/> + <xsl:with-param name="listLevelStyle" select="$listLevelStyle"/> + <xsl:with-param name="listLevelsToDisplay" select="$listLevelsToDisplay"/> + </xsl:call-template> + </xsl:template> + + + <xsl:template match="text:p" mode="list-item-children"> + <xsl:param name="globalData"/> + <xsl:param name="listLabelElement"/> + <xsl:param name="listLabelEmptyElement"/> + <xsl:param name="isEmptyList"/> + <xsl:param name="isListNumberingReset"/> + <xsl:param name="isNextLevelNumberingReset"/> + <xsl:param name="itemLabel"/> + <xsl:param name="itemNumber"/> + <xsl:param name="listIndent"/> + <xsl:param name="listLevel"/> + <xsl:param name="listRestart"/> + <xsl:param name="listStyle"/> + <xsl:param name="listStyleName"/> + <xsl:param name="minLabelDist"/> + <xsl:param name="minLabelWidth"/> + + <!-- TODO page alignment fix - PART1 --> + + <!-- xhtml:p may only contain inline elements. + If there is one frame beyond, div must be used! --> + <xsl:variable name="elementName"> + <xsl:choose> + <xsl:when test="descendant::draw:frame[1] or descendant::text:p[1]">div</xsl:when> + <xsl:otherwise>p</xsl:otherwise> + </xsl:choose> + </xsl:variable> + <xsl:element name="{$elementName}"> + <xsl:call-template name="create-list-style"> + <xsl:with-param name="globalData" select="$globalData"/> + <xsl:with-param name="listIndent" select="$listIndent"/> + <xsl:with-param name="styleName" select="@text:style-name"/> + </xsl:call-template> + <xsl:choose> + <xsl:when test="$listLabelElement"> + <xsl:copy-of select="$listLabelElement"/> + </xsl:when> + <xsl:otherwise> + <xsl:copy-of select="$listLabelEmptyElement"/> + </xsl:otherwise> + </xsl:choose> + <xsl:apply-templates> + <xsl:with-param name="globalData" select="$globalData"/> + <xsl:with-param name="listIndent" select="$minLabelWidth"/> + <xsl:with-param name="tdf146264hack" select="true()"/> + </xsl:apply-templates> + <!-- this span disables the float necessary to bring two block elements on one line. It contains a space as IE6 bug workaround --> + <span class="odfLiEnd"></span> + <xsl:text> </xsl:text> + </xsl:element> + + <xsl:apply-templates mode="list-item-children" select="following-sibling::*[1]"> + <xsl:with-param name="globalData" select="$globalData"/> + <xsl:with-param name="isEmptyList" select="$isEmptyList"/> + <xsl:with-param name="isListNumberingReset" select="$isListNumberingReset"/> + <xsl:with-param name="isNextLevelNumberingReset" select="$isNextLevelNumberingReset"/> + <xsl:with-param name="itemLabel" select="$itemLabel"/> + <xsl:with-param name="itemNumber" select="$itemNumber"/> + <xsl:with-param name="listLabelEmptyElement" select="$listLabelEmptyElement"/> + <xsl:with-param name="listLevel" select="$listLevel"/> + <xsl:with-param name="listRestart" select="$listRestart"/> + <xsl:with-param name="listStyle" select="$listStyle"/> + <xsl:with-param name="listStyleName" select="$listStyleName"/> + <xsl:with-param name="listIndent" select="$listIndent"/> + <xsl:with-param name="minLabelDist" select="$minLabelDist"/> + <xsl:with-param name="minLabelWidth" select="$minLabelWidth"/> + </xsl:apply-templates> + </xsl:template> + + + <!-- Neglecting the left margin behavior for headings for now --> + <xsl:template match="text:h" mode="list-item-children"> + <xsl:param name="globalData"/> + <xsl:param name="listLabelElement"/> + <xsl:param name="listLabelEmptyElement"/> + <xsl:param name="isEmptyList"/> + <xsl:param name="isListNumberingReset"/> + <xsl:param name="isNextLevelNumberingReset"/> + <xsl:param name="itemLabel"/> + <xsl:param name="itemNumber"/> + <xsl:param name="listIndent"/> + <xsl:param name="listLevel"/> + <xsl:param name="listRestart"/> + <xsl:param name="listStyle"/> + <xsl:param name="listStyleName"/> + <xsl:param name="minLabelWidth"/> + + <xsl:variable name="headingName" select="concat('h', $listLevel - 1)"/> + <xsl:element name="{$headingName}"> + <xsl:call-template name="create-list-style"> + <xsl:with-param name="globalData" select="$globalData"/> + <xsl:with-param name="listIndent" select="$listIndent"/> + <xsl:with-param name="styleName" select="@text:style-name"/> + </xsl:call-template> + <xsl:variable name="title"> + <xsl:apply-templates mode="concatenate"/> + </xsl:variable> + <xsl:choose> + <xsl:when test="$listLabelElement"> + <xsl:copy-of select="$listLabelElement"/> + </xsl:when> + <xsl:otherwise> + <xsl:copy-of select="$listLabelEmptyElement"/> + </xsl:otherwise> + </xsl:choose> + + <!-- REFERENCE HANDLING - ANCHOR --> + <xsl:element namespace="{$namespace}" name="a"> + <xsl:attribute name="id"> + <xsl:value-of select="translate(concat('a_',$listLabelElement, '_', normalize-space($title)), '
&<>.,;: %()[]/\+', '___________________________')"/> + </xsl:attribute> + <xsl:apply-templates> + <xsl:with-param name="globalData" select="$globalData"/> + <xsl:with-param name="listIndent" select="$minLabelWidth"/> + </xsl:apply-templates> + </xsl:element> + + <!-- this span disables the float necessary to bring two block elements on one line. It contains a space as IE6 bug workaround --> + <span class="odfLiEnd"></span> + <xsl:text> </xsl:text> + </xsl:element> + + <xsl:apply-templates mode="list-item-children" select="following-sibling::*[1]"> + <xsl:with-param name="globalData" select="$globalData"/> + <xsl:with-param name="isEmptyList" select="$isEmptyList"/> + <xsl:with-param name="isListNumberingReset" select="$isListNumberingReset"/> + <xsl:with-param name="isNextLevelNumberingReset" select="$isNextLevelNumberingReset"/> + <xsl:with-param name="itemLabel" select="$itemLabel"/> + <xsl:with-param name="itemNumber" select="$itemNumber"/> + <xsl:with-param name="listLabelEmptyElement" select="$listLabelEmptyElement"/> + <xsl:with-param name="listLevel" select="$listLevel"/> + <xsl:with-param name="listRestart" select="$listRestart"/> + <xsl:with-param name="listStyle" select="$listStyle"/> + <xsl:with-param name="listStyleName" select="$listStyleName"/> + <xsl:with-param name="listIndent" select="$listIndent"/> + <xsl:with-param name="minLabelWidth" select="$minLabelWidth"/> + </xsl:apply-templates> + </xsl:template> + + + <xsl:template match="*" mode="list-item-children"> + <xsl:param name="globalData"/> + <xsl:param name="isEmptyList"/> + <xsl:param name="listLabelEmptyElement"/> + <xsl:param name="isListNumberingReset"/> + <xsl:param name="isNextLevelNumberingReset"/> + <xsl:param name="itemLabel"/> + <xsl:param name="itemNumber"/> + <xsl:param name="listIndent"/> + <xsl:param name="listLevel"/> + <xsl:param name="listRestart"/> + <xsl:param name="listStyle"/> + <xsl:param name="listStyleName"/> + <xsl:param name="minLabelWidth"/> + + <xsl:apply-templates select="self::*"> + <xsl:with-param name="globalData" select="$globalData"/> + <xsl:with-param name="isEmptyList" select="$isEmptyList"/> + <xsl:with-param name="isListNumberingReset" select="$isListNumberingReset"/> + <xsl:with-param name="isNextLevelNumberingReset" select="$isNextLevelNumberingReset"/> + <xsl:with-param name="listLabelEmptyElement" select="$listLabelEmptyElement"/> + <xsl:with-param name="itemLabel" select="$itemLabel"/> + <xsl:with-param name="itemNumber" select="$itemNumber"/> + <xsl:with-param name="listIndent" select="$listIndent"/> + <xsl:with-param name="listLevel" select="$listLevel"/> + <xsl:with-param name="listRestart" select="$listRestart"/> + <xsl:with-param name="listStyle" select="$listStyle"/> + <xsl:with-param name="listStyleName" select="$listStyleName"/> + </xsl:apply-templates> + + <xsl:apply-templates mode="list-item-children" select="following-sibling::*[1]"> + <xsl:with-param name="globalData" select="$globalData"/> + <xsl:with-param name="isEmptyList" select="$isEmptyList"/> + <xsl:with-param name="isListNumberingReset" select="$isListNumberingReset"/> + <xsl:with-param name="isNextLevelNumberingReset" select="$isNextLevelNumberingReset"/> + <xsl:with-param name="itemLabel" select="$itemLabel"/> + <xsl:with-param name="itemNumber" select="$itemNumber"/> + <xsl:with-param name="listLabelEmptyElement" select="$listLabelEmptyElement"/> + <xsl:with-param name="listLevel" select="$listLevel"/> + <xsl:with-param name="listRestart" select="$listRestart"/> + <xsl:with-param name="listStyle" select="$listStyle"/> + <xsl:with-param name="listStyleName" select="$listStyleName"/> + <xsl:with-param name="listIndent" select="$listIndent"/> + <xsl:with-param name="minLabelWidth" select="$minLabelWidth"/> + </xsl:apply-templates> + </xsl:template> + + <xsl:template match="*" mode="listItemSibling"> + <xsl:param name="globalData"/> + <xsl:param name="isEmptyList"/> + <xsl:param name="isListNumberingReset"/> + <xsl:param name="isNextLevelNumberingReset"/> + <xsl:param name="itemLabel"/> + <xsl:param name="itemNumber"/> + <xsl:param name="listIndent"/> + <xsl:param name="listLevel"/> + <xsl:param name="listRestart"/> + <xsl:param name="listStyle"/> + <xsl:param name="listLevelStyle"/> + <xsl:param name="listStyleName"/> + + <xsl:apply-templates select="self::*"> + <xsl:with-param name="globalData" select="$globalData"/> + <xsl:with-param name="isEmptyList" select="$isEmptyList"/> + <xsl:with-param name="isListNumberingReset" select="$isListNumberingReset"/> + <xsl:with-param name="isNextLevelNumberingReset" select="$isNextLevelNumberingReset"/> + <xsl:with-param name="itemNumber" select="$itemNumber"/> + <xsl:with-param name="listIndent" select="$listIndent"/> + <!-- receives the same parent label, only with a different itemNumber --> + <xsl:with-param name="itemLabel" select="$itemLabel"/> + <xsl:with-param name="listLevel" select="$listLevel"/> + <xsl:with-param name="listStyle" select="$listStyle"/> + <xsl:with-param name="listStyleName" select="$listStyleName"/> + </xsl:apply-templates> + <xsl:apply-templates select="following-sibling::*[1]" mode="listItemSibling"> + <xsl:with-param name="globalData" select="$globalData"/> + <xsl:with-param name="isEmptyList" select="$isEmptyList"/> + <xsl:with-param name="isListNumberingReset" select="$isListNumberingReset"/> + <xsl:with-param name="isNextLevelNumberingReset" select="$isNextLevelNumberingReset"/> + <xsl:with-param name="itemNumber" select="$itemNumber"/> + <xsl:with-param name="listIndent" select="$listIndent"/> + <!-- receives the same parent label, only with a different itemNumber --> + <xsl:with-param name="itemLabel" select="$itemLabel"/> + <xsl:with-param name="listLevel" select="$listLevel"/> + <xsl:with-param name="listStyle" select="$listStyle"/> + <xsl:with-param name="listStyleName" select="$listStyleName"/> + </xsl:apply-templates> + </xsl:template> + + <xsl:template match="text()" mode="list-item-children"> + <xsl:value-of select="."/> + </xsl:template> + + + <xsl:template name="create-list-style"> + <xsl:param name="globalData"/> + <xsl:param name="listIndent" select="0"/> + <xsl:param name="styleName"/> + + <xsl:if test="$styleName"> + <xsl:attribute name="class"> + <xsl:value-of select="translate($styleName, '.,;: %()[]/\+', '_____________')"/> + </xsl:attribute> + </xsl:if> + <xsl:attribute name="style"> + <xsl:text>margin-</xsl:text> + <xsl:call-template name="getOppositeWritingDirection"> + <xsl:with-param name="globalData" select="$globalData"/> + <xsl:with-param name="paraStyleName" select="descendant-or-self::*/@text:style-name"/> + </xsl:call-template> + <xsl:text>:</xsl:text> + <xsl:value-of select="$listIndent"/> + <xsl:text>cm;</xsl:text> + </xsl:attribute> + </xsl:template> + + + <!-- ********************************************** --> + <!-- *** Text Section (contains: draw:text-box) *** --> + <!-- ********************************************** --> + + <xsl:template match="text:section"> + <xsl:param name="globalData"/> + + <xsl:if test="not(contains(@text:display, 'none'))"> + <xsl:comment>Next 'div' was a 'text:section'.</xsl:comment> + <xsl:element name="div"> + <xsl:call-template name="apply-styles-and-content"> + <xsl:with-param name="globalData" select="$globalData"/> + </xsl:call-template> + </xsl:element> + </xsl:if> + </xsl:template> + + + <!-- Hidden text dependent on Office variables: + The text is not shown, if condition is 'true'. + Implemented solely for conditions as '<VARIABLE>==0' or '<VARIABLE>==1' + --> + <xsl:key match="text:variable-set" name="varSet" use="@text:name"/> + <xsl:template match="text:hidden-text"> + <xsl:param name="globalData"/> + + <xsl:variable name="varName" select="substring-before(@text:condition, '==')"/> + <xsl:variable name="varValue" select="substring-after(@text:condition, '==')"/> + <xsl:choose> + <xsl:when test="key('varSet', $varName)/@text:value != $varValue"> + <xsl:value-of select="@text:string-value"/> + </xsl:when> + <xsl:otherwise> + <xsl:comment> + <xsl:value-of select="$varName"/> + <xsl:value-of select="@text:string-value"/> + <xsl:value-of select="$varName"/> + </xsl:comment> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <xsl:template match="@text:style-name | @draw:style-name | @draw:text-style-name | @table:style-name"><!-- | @presentation:style-name--> + <xsl:param name="globalData"/> + + <xsl:attribute name="class"> + <xsl:value-of select="translate(., '.,;: %()[]/\+', '_____________')"/> + </xsl:attribute> + </xsl:template> + + + <!-- ***************** --> + <!-- *** Footnotes *** --> + <!-- ***************** --> + + <xsl:template match="text:note"> + <xsl:param name="globalData"/> + + <!-- get style configuration --> + <xsl:variable name="footnoteConfig" select="$globalData/office:styles/text:notes-configuration[@text:note-class=current()/@text:note-class]" /> + + <xsl:variable name="titlePrefix"> + <xsl:choose> + <xsl:when test="@text:note-class = 'footnote'"> + <xsl:text>Footnote: </xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:text>Endnote: </xsl:text> + </xsl:otherwise> + </xsl:choose> + </xsl:variable> + + <!-- write anchor --> + <xsl:element name="span"> + <xsl:attribute name="class"> + <xsl:value-of select="$footnoteConfig/@text:citation-body-style-name"/> + </xsl:attribute> + <xsl:attribute name="title"> + <xsl:value-of select="$titlePrefix"/> + <xsl:apply-templates mode="textOnly" select="text:note-body"/> + </xsl:attribute> + <xsl:element name="a"> + <xsl:attribute name="href"> + <xsl:value-of select="concat('#', @text:id)"/> + </xsl:attribute> + <xsl:attribute name="id"> + <xsl:value-of select="concat('body_', @text:id)"/> + </xsl:attribute> + <xsl:apply-templates mode="textOnly" select="text:note-citation"/> + </xsl:element> + </xsl:element> + </xsl:template> + + <xsl:template match="*" mode="textOnly"> + <xsl:apply-templates select="* | text()" mode="textOnly" /> + </xsl:template> + + <xsl:template match="text()" mode="textOnly"> + <xsl:value-of select="."/> + </xsl:template> + + <!-- Useful in case of 'style:map', conditional formatting, where a style references to another --> + <xsl:key name="textNotes" match="text:note" use="@text:note-class"/> + + <!-- writing the footer- and endnotes beyond the body --> + <xsl:template name="write-text-nodes"> + <xsl:param name="globalData"/> + + <!-- write footnote body --> + <xsl:for-each select="key('textNotes', 'footnote')"> + <xsl:call-template name="write-text-node"> + <xsl:with-param name="globalData" select="$globalData"/> + <xsl:with-param name="footnoteConfig" select="$globalData/office:styles/text:notes-configuration[@text:note-class=current()/@text:note-class]" /> + </xsl:call-template> + </xsl:for-each> + + <!-- write endnote body --> + <xsl:for-each select="key('textNotes', 'endnote')"> + <xsl:call-template name="write-text-node"> + + <xsl:with-param name="globalData" select="$globalData"/> + <xsl:with-param name="footnoteConfig" select="$globalData/office:styles/text:notes-configuration[@text:note-class=current()/@text:note-class]" /> + </xsl:call-template> + </xsl:for-each> + </xsl:template> + + <xsl:template name="write-text-node"> + <xsl:param name="globalData"/> + <xsl:param name="footnoteConfig"/> + + <xsl:apply-templates select="text:note-body/*[1]"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="footnotePrefix"> + <xsl:element name="span"> + <xsl:attribute name="class">footnodeNumber</xsl:attribute> + <xsl:element name="a"> + <xsl:attribute name="class"> + <xsl:value-of select="$footnoteConfig/@text:citation-style-name"/> + </xsl:attribute> + <xsl:attribute name="id"> + <xsl:value-of select="@text:id"/> + </xsl:attribute> + <xsl:attribute name="href"> + <xsl:value-of select="concat('#body_', @text:id)"/> + </xsl:attribute> + <xsl:apply-templates mode="textOnly" select="text:note-citation"/> + </xsl:element> + </xsl:element> + </xsl:with-param> + </xsl:apply-templates> + <xsl:apply-templates select="text:note-body/*[position()>1]"> + <xsl:with-param name="globalData" select="$globalData" /> + </xsl:apply-templates> + </xsl:template> + + <!-- ***************** --> + <!-- *** Bookmarks *** --> + <!-- ***************** --> + + <xsl:template match="text:bookmark|text:bookmark-start"> + <xsl:element name="a"> + <xsl:attribute name="id"> + <xsl:value-of select="@text:name"/> + </xsl:attribute> + </xsl:element> + </xsl:template> + + <xsl:template match="text:bookmark-end"/> + + <!-- DISABLING this tab handling as the tab width is only relative + <xsl:template match="text:tab"> + <xsl:param name="globalData"/> + + <xsl:variable name="tabNo"> + <xsl:choose> + <xsl:when test="preceding-sibling::text:line-break"> + <xsl:call-template name="countTextTab"/> + </xsl:when> + <xsl:when test="preceding-sibling::text:tab"> + <xsl:value-of select="count(preceding-sibling::text:tab)"/> + </xsl:when> + <xsl:otherwise>1</xsl:otherwise> + </xsl:choose> + </xsl:variable> + + <xsl:element name="span"> + <xsl:attribute name="style">margin-left:<xsl:value-of select="$globalData/all-doc-styles/style[@style:name = current()/parent::*/@text:style-name]/*/style:tab-stops/style:tab-stop[$tabNo]/@style:position"/>;</xsl:attribute> + </xsl:element> + </xsl:template> + + <xsl:template name="countTextTab"> + <xsl:param name="tabCount" select="1"/> + <xsl:param name="context" select="."/> + + <xsl:choose> + <xsl:when test="preceding-sibling::*[1]"> + <xsl:for-each select="preceding-sibling::*[1]"> + <xsl:call-template name="countTextTab"> + <xsl:with-param name="tabCout"> + <xsl:choose> + <xsl:when test="name(.) = 'text:tab'"> + <xsl:value-of select="$tabCount + 1"/> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="$tabCount"/> + </xsl:otherwise> + </xsl:choose> + </xsl:with-param> + <xsl:with-param name="context" select="preceding-sibling::*[1]" /> + </xsl:call-template> + </xsl:for-each> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="$tabCount"/> + </xsl:otherwise> + </xsl:choose> + </xsl:template> +--> + <!-- MathML --> + <xsl:template match="draw:object[math:math]"> + <xsl:apply-templates select="math:math" mode="math"/> + </xsl:template> + + <xsl:template match="*" mode="math"> + <xsl:element name="{local-name()}" namespace="http://www.w3.org/1998/Math/MathML"> + <xsl:apply-templates select="@*|node()" mode="math"/> + </xsl:element> + </xsl:template> + + <xsl:template match="@*" mode="math"> + <xsl:attribute name="{local-name()}"> + <xsl:value-of select="."/> + </xsl:attribute> + </xsl:template> + + <!-- our mathml should always be inline the text flow --> + <xsl:template match="@display" mode="math"> + <xsl:attribute name="{local-name()}">inline</xsl:attribute> + </xsl:template> + + <!-- Ignore semantic annotations --> + <xsl:template match="math:semantics" mode="math"> + <xsl:apply-templates select="*[1]" mode="math"/> + </xsl:template> + +</xsl:stylesheet> diff --git a/filter/source/xslt/odf2xhtml/export/xhtml/header.xsl b/filter/source/xslt/odf2xhtml/export/xhtml/header.xsl new file mode 100644 index 000000000..2bd07d8d2 --- /dev/null +++ b/filter/source/xslt/odf2xhtml/export/xhtml/header.xsl @@ -0,0 +1,480 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . +--> +<!-- + For further documentation and updates visit http://xml.openoffice.org/odf2xhtml +--> +<xsl:stylesheet version="1.0" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" + xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:dom="http://www.w3.org/2001/xml-events" + xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" + xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" + xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" + xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" + xmlns:math="http://www.w3.org/1998/Math/MathML" + xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" + xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" + xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" + xmlns:ooo="http://openoffice.org/2004/office" + xmlns:oooc="http://openoffice.org/2004/calc" + xmlns:ooow="http://openoffice.org/2004/writer" + xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" + xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" + xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" + xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" + xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" + xmlns:xforms="http://www.w3.org/2002/xforms" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + exclude-result-prefixes="chart config dc dom dr3d draw fo form math meta number office ooo oooc ooow script style svg table text xforms xlink xsd xsi xforms xsd xsi" + xmlns="http://www.w3.org/1999/xhtml"> + + <!-- ************** --> + <!-- *** header *** --> + <!-- ************** --> + + <xsl:template name="create-header"> + <xsl:param name="globalData" /> + + <xsl:element name="head"> + <xsl:attribute name="profile">http://dublincore.org/documents/dcmi-terms/</xsl:attribute> + <xsl:if test="$debugEnabled"><xsl:message>CSS helper variable will be created...</xsl:message></xsl:if> + <xsl:call-template name='xhtml-header-properties'> + <xsl:with-param name="globalData" select="$globalData" /> + </xsl:call-template> + + <xsl:if test="$debugEnabled"><xsl:message>CSS variable ready, header will be created...</xsl:message></xsl:if> + <!-- constructing the css header simulating inheritance of style-families by style order --> + <xsl:call-template name='create-css-styleheader'> + <xsl:with-param name="globalData" select="$globalData" /> + </xsl:call-template> + <xsl:if test="$debugEnabled"><xsl:message>CSS header creation finished!</xsl:message></xsl:if> + </xsl:element> + + </xsl:template> + + <!-- Creating a CSS style header from the collected styles of the 'globalData' parameter --> + <xsl:template name='create-css-styleheader'> + <xsl:param name="globalData" /> + + <xsl:element name="style"> + <!-- https://validator.w3.org/unicorn: + The “type” attribute for the “style” element is not needed and should be omitted. + <xsl:attribute name="type">text/css</xsl:attribute> --> +<xsl:text> + </xsl:text> + <xsl:call-template name='create-page-layout'> + <xsl:with-param name="globalData" select="$globalData" /> + </xsl:call-template> +<xsl:text>table { border-collapse:collapse; border-spacing:0; empty-cells:show } + </xsl:text> + <xsl:choose> + <xsl:when test="/*/office:body/office:spreadsheet"><xsl:text>td, th { vertical-align:top; font-size:10pt;} + </xsl:text></xsl:when> + <xsl:otherwise><xsl:text>td, th { vertical-align:top; font-size:12pt;} + </xsl:text></xsl:otherwise> + </xsl:choose> +<xsl:text>h1, h2, h3, h4, h5, h6 { clear:both;} + </xsl:text> +<xsl:choose> + <xsl:when test="/*/office:body/office:spreadsheet"> + <xsl:text>p { white-space: nowrap; } + </xsl:text> + </xsl:when> +</xsl:choose> +<xsl:text>ol, ul { margin:0; padding:0;} + </xsl:text> +<xsl:text>li { list-style: none; margin:0; padding:0;} + </xsl:text> +<xsl:text>span.footnodeNumber { padding-right:1em; } + </xsl:text> +<xsl:text>span.annotation_style_by_filter { font-size:95%; font-family:Arial; background-color:#fff000; margin:0; border:0; padding:0; } + </xsl:text> +<!-- Simulate tabs. They are around 0.64cm in LO, we convert that to 0.8rem. --> +<xsl:text>span.heading_numbering { margin-right: 0.8rem; }</xsl:text> +<xsl:text>* { margin:0;} + </xsl:text> + <xsl:call-template name="write-mapped-CSS-styles"> + <xsl:with-param name="globalData" select="$globalData" /> + </xsl:call-template> + </xsl:element> + </xsl:template> + + <xsl:template name="write-mapped-CSS-styles"> + <xsl:param name="globalData" /> + <xsl:param name="emptyStyles"/> + + <xsl:for-each select="$globalData/all-styles/style"> + <xsl:if test="final-properties != ''"> + <!-- NOTE: easy process, as only the style family in conjunction with the style name, makes the style unambiguous --> + <xsl:text>.</xsl:text><!--<xsl:value-of select="@style:family" /><xsl:text>:</xsl:text>--><xsl:value-of select="translate(@style:name, '.,;: %()[]/\+', '_____________')"/><xsl:text> { </xsl:text> <xsl:value-of select="final-properties" /><xsl:text>} + </xsl:text> + </xsl:if> + + </xsl:for-each> + <!-- Otherwise all styles have been processed and the empty styles have to be given out --> + <xsl:text>/* ODF styles with no properties representable as CSS: + </xsl:text><xsl:for-each select="$globalData/all-styles/style[final-properties = '']"><xsl:value-of select="concat('.', @style:name, ' ')"/></xsl:for-each><xsl:text> { } */ +</xsl:text> + </xsl:template> + + <!-- Creating CSS page layout based on first office master style --> + <xsl:template name='create-page-layout'> + <xsl:param name="globalData" /> + + <!-- approximation to find the correct master page style (with page dimensions) --> + <xsl:variable name="masterPageNames"> + <!-- set context to styles.xml --> + <xsl:for-each select="$globalData/all-doc-styles/style"> + <!-- Loop over every style:style containing a @style:master-page-name attribute --> + <xsl:for-each select="key('masterPage','count')"> + <!-- set context to styles.xml --> + <xsl:for-each select="/*/office:body"> + <!-- Check if this style is being used in the body --> + <xsl:if test="key('elementUsingStyle', ../@style:name)"> + <!-- Check every master-page-name if it is not empty and return as ';' separated list --> + <xsl:if test="string-length(../@style:master-page-name) > 0"><xsl:value-of select="../@style:master-page-name"/>;</xsl:if> + </xsl:if> + </xsl:for-each> + </xsl:for-each> + </xsl:for-each> + </xsl:variable> + <!-- Take the first of the masterpage list and get the according style:master-page element and find the @style:page-layout-name --> + <xsl:variable name="pageLayoutName" select="key('masterPageElements', substring-before($masterPageNames,';'))/@style:page-layout-name"/> + <!-- Find the according style:page-layout and store the properties in a variable --> + <xsl:variable name="pageProperties" select="key('pageLayoutElements', $pageLayoutName)/style:page-layout-properties"/> + + <xsl:variable name="pageSize"> + <xsl:call-template name="page-size"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="pageProperties" select="$pageProperties" /> + </xsl:call-template> + <xsl:call-template name="page-margin"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="pageProperties" select="$pageProperties" /> + </xsl:call-template> + </xsl:variable> + + <xsl:if test="$pageSize and $pageSize!=''"> +<xsl:text>@page { </xsl:text> +<xsl:value-of select="$pageSize"/> +<xsl:text> } + </xsl:text> + </xsl:if> + </xsl:template> + + + <xsl:template name="page-size"> + <xsl:param name="globalData" /> + <xsl:param name="pageProperties" /> + + <xsl:variable name="printOrientation" select="$pageProperties/@style:print-orientation" /> + <xsl:variable name="pageWidth" select="$pageProperties/@fo:page-width" /> + <xsl:variable name="pageHeight" select="$pageProperties/@fo:page-height" /> + <xsl:choose> + <xsl:when test="$pageWidth and $pageHeight"> + <xsl:text>size: </xsl:text> + <xsl:value-of select="$pageWidth" /> + <xsl:text> </xsl:text> + <xsl:value-of select="$pageHeight" /> + <xsl:text>; </xsl:text> + </xsl:when> + <xsl:when test="$printOrientation"> + <xsl:text>size: </xsl:text> + <xsl:value-of select="$printOrientation" /> + <xsl:text>; </xsl:text> + </xsl:when> + </xsl:choose> + </xsl:template> + + <xsl:template name="page-margin"> + <xsl:param name="globalData" /> + <xsl:param name="pageProperties" /> + + <xsl:variable name="marginTop" select="$pageProperties/@fo:margin-top" /> + <xsl:if test="$marginTop"> + <xsl:text>margin-top: </xsl:text> + <xsl:value-of select="$marginTop" /> + <xsl:text>; </xsl:text> + </xsl:if> + <xsl:variable name="marginBottom" select="$pageProperties/@fo:margin-bottom" /> + <xsl:if test="$marginBottom"> + <xsl:text>margin-bottom: </xsl:text> + <xsl:value-of select="$marginBottom" /> + <xsl:text>; </xsl:text> + </xsl:if> + <xsl:variable name="marginLeft" select="$pageProperties/@fo:margin-left" /> + <xsl:if test="$marginLeft"> + <xsl:text>margin-left: </xsl:text> + <xsl:value-of select="$marginLeft" /> + <xsl:text>; </xsl:text> + </xsl:if> + <xsl:variable name="marginRight" select="$pageProperties/@fo:margin-right" /> + <xsl:if test="$marginRight"> + <xsl:text>margin-right: </xsl:text> + <xsl:value-of select="$marginRight" /> + </xsl:if> + </xsl:template> + + <!-- *************************** --> + <!-- *** Common XHTML header *** --> + <!-- *************************** --> + + <xsl:template name='xhtml-header-properties'> + <xsl:param name="globalData" /> + + <xsl:variable name="netloc"> + <xsl:for-each select="$globalData/meta-file/*/office:meta/meta:user-defined"> + <xsl:if test="./@meta:name='ODF.base'"> + <xsl:value-of select="." /> + </xsl:if> + </xsl:for-each> + <xsl:for-each select="$globalData/meta-file/*/office:meta/meta:user-defined"> + <xsl:if test="./@meta:name='ODF.filename'"> + <xsl:value-of select="." /> + </xsl:if> + </xsl:for-each> + </xsl:variable> + + <xsl:variable name="lang"> + <xsl:choose> + <xsl:when test="$globalData/meta-file/*/office:meta/dc:language"> + <xsl:value-of select="$globalData/meta-file/*/office:meta/dc:language" /> + </xsl:when> + <xsl:otherwise>en-US</xsl:otherwise> + </xsl:choose> + </xsl:variable> + + <xsl:variable name="prov"> + <xsl:choose> + <xsl:when test="$globalData/meta-file/*/office:meta/meta:printed-by"> + <xsl:value-of select="concat('Printed by "',$globalData/meta-file/*/office:meta/meta:printed-by,'"[dc:publisher] on "',$globalData/meta-file/*/office:meta/meta:print-date,'"[dc:date] in "',$lang,'"[dc:language]')" /> + </xsl:when> + <xsl:otherwise /> + </xsl:choose> + </xsl:variable> + + <xsl:variable name="keywords"> + <xsl:for-each select="$globalData/meta-file/*/office:meta/meta:keyword"> + <xsl:value-of select="." /> + <xsl:if test="position() != last()"> + <xsl:text>, </xsl:text> + </xsl:if> + </xsl:for-each> + </xsl:variable> + + <!-- explicit output content-type for low-tech browser (e.g. IE6) --> + <xsl:element name="meta"> + <xsl:attribute name="http-equiv">Content-Type</xsl:attribute> + <xsl:attribute name="content">application/xhtml+xml; charset=utf-8</xsl:attribute> + </xsl:element> + + <!-- title of document for browser frame title --> + <xsl:element name="title"> + <xsl:attribute name="xml:lang"> + <xsl:value-of select="$lang" /> + </xsl:attribute> + + <xsl:choose> + <xsl:when test="$globalData/meta-file/*/office:meta/dc:title"> + <xsl:value-of select="$globalData/meta-file/*/office:meta/dc:title" /> + </xsl:when> + <!-- providing the mandatory title is a workaround for an IE bug--> + <xsl:otherwise> + <xsl:text>- no title specified</xsl:text> + </xsl:otherwise> + </xsl:choose> + </xsl:element> + + <!-- title, in DC syntax --> + <xsl:element name="meta"> + <xsl:attribute name="name">DCTERMS.title</xsl:attribute> + <xsl:attribute name="content"> + <xsl:value-of select="$globalData/meta-file/*/office:meta/dc:title" /> + </xsl:attribute> + <xsl:attribute name="xml:lang"> + <xsl:value-of select="$lang" /> + </xsl:attribute> + </xsl:element> + + <!-- the identifier for source (identifier) --> + <xsl:call-template name="add-meta-tag"> + <xsl:with-param name="meta-name" select="'DCTERMS.identifier'" /> + <xsl:with-param name="meta-data" select="translate($netloc, ' ','')" /> + <xsl:with-param name="meta-enc" select="'DCTERMS.URI'" /> + </xsl:call-template> + + <!-- the language for source (language) --> + <xsl:call-template name="add-meta-tag"> + <xsl:with-param name="meta-name" select="'DCTERMS.language'" /> + <xsl:with-param name="meta-data" select="$lang" /> + <xsl:with-param name="meta-enc" select="'DCTERMS.RFC4646'" /> + </xsl:call-template> + + <!-- a bit commercial (generator) --> + <xsl:element name="meta"> + <xsl:attribute name="name">DCTERMS.source</xsl:attribute> + <xsl:attribute name="content">http://xml.openoffice.org/odf2xhtml</xsl:attribute> + </xsl:element> + + <!-- the author of the input source (author) --> + <xsl:call-template name="add-meta-tag"> + <xsl:with-param name="meta-name" select="'DCTERMS.creator'" /> + <xsl:with-param name="meta-data" select="$globalData/meta-file/*/office:meta/meta:initial-creator" /> + </xsl:call-template> + + <!-- creation-date of the input source (issued) --> + <xsl:call-template name="add-meta-tag"> + <xsl:with-param name="meta-name" select="'DCTERMS.issued'" /> + <xsl:with-param name="meta-data" select="$globalData/meta-file/*/office:meta/meta:creation-date" /> + <xsl:with-param name="meta-enc" select="'DCTERMS.W3CDTF'" /> + </xsl:call-template> + + <!-- name of last changing person of the input source (changedby) --> + <xsl:call-template name="add-meta-tag"> + <xsl:with-param name="meta-name" select="'DCTERMS.contributor'" /> + <xsl:with-param name="meta-data" select="$globalData/meta-file/*/office:meta/dc:creator" /> + </xsl:call-template> + + <!-- last changing date of the input source (changed) --> + <xsl:call-template name="add-meta-tag"> + <xsl:with-param name="meta-name" select="'DCTERMS.modified'" /> + <xsl:with-param name="meta-data" select="$globalData/meta-file/*/office:meta/dc:date" /> + <xsl:with-param name="meta-enc" select="'DCTERMS.W3CDTF'" /> + </xsl:call-template> + + <!-- Last print, as provenance --> + <xsl:if test="$prov"> + <xsl:call-template name="add-meta-tag"> + <xsl:with-param name="meta-name" select="'DCTERMS.provenance'" /> + <xsl:with-param name="meta-data" select="$prov" /> + <xsl:with-param name="meta-lang" select="$lang" /> + </xsl:call-template> + </xsl:if> + + <!-- keywords about the input source (keywords) --> + <xsl:if test="($globalData/meta-file/*/office:meta/dc:subject != '') or ($keywords != '')"> + <xsl:choose> + <xsl:when test="($globalData/meta-file/*/office:meta/dc:subject != '') and ($keywords != '')"> + <xsl:call-template name="add-meta-tag"> + <xsl:with-param name="meta-name" select="'DCTERMS.subject'" /> + <xsl:with-param name="meta-data" select="normalize-space(concat($globalData/meta-file/*/office:meta/dc:subject,', ',$keywords))" /> + <xsl:with-param name="meta-lang" select="$lang" /> + </xsl:call-template> + </xsl:when> + <xsl:when test="($globalData/meta-file/*/office:meta/dc:subject != '')"> + <xsl:call-template name="add-meta-tag"> + <xsl:with-param name="meta-name" select="'DCTERMS.subject'" /> + <xsl:with-param name="meta-data" select="normalize-space($globalData/meta-file/*/office:meta/dc:subject)" /> + <xsl:with-param name="meta-lang" select="$lang" /> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:call-template name="add-meta-tag"> + <xsl:with-param name="meta-name" select="'DCTERMS.subject'" /> + <xsl:with-param name="meta-data" select="normalize-space($keywords)" /> + <xsl:with-param name="meta-lang" select="$lang" /> + </xsl:call-template> + </xsl:otherwise> + </xsl:choose> + </xsl:if> + + <!-- detailed description about the input source (description) --> + <xsl:call-template name="add-meta-tag"> + <xsl:with-param name="meta-name" select="'DCTERMS.description'" /> + <xsl:with-param name="meta-data" select="$globalData/meta-file/*/office:meta/dc:description" /> + <xsl:with-param name="meta-lang" select="$lang" /> + </xsl:call-template> + + + <!-- user defined use of DCTERM tags --> + <xsl:for-each select="$globalData/meta-file/*/office:meta/meta:user-defined[starts-with(@meta:name,'DCTERMS.')][not(.='')]"> + <xsl:call-template name="add-meta-tag"> + <xsl:with-param name="meta-name" select="@meta:name" /> + <xsl:with-param name="meta-data" select="." /> + <!-- <xsl:with-param name="meta-lang" select="$lang" /> --> + </xsl:call-template> + </xsl:for-each> + <!-- user defined use of DC tags (legacy) --> + <xsl:for-each select="$globalData/meta-file/*/office:meta/meta:user-defined[starts-with(@meta:name,'DC.')][not(.='')]"> + <xsl:call-template name="add-meta-tag"> + <xsl:with-param name="meta-name" select="@meta:name" /> + <xsl:with-param name="meta-data" select="." /> + <!-- <xsl:with-param name="meta-lang" select="$lang" /> --> + </xsl:call-template> + </xsl:for-each> + <xsl:call-template name="add-meta-tag"> + <xsl:with-param name="meta-name" select="'xsl:vendor'" /> + <xsl:with-param name="meta-data" select="system-property('xsl:vendor')" /> + </xsl:call-template> + + <link rel="schema.DC" href="http://purl.org/dc/elements/1.1/" hreflang="en" /> + <link rel="schema.DCTERMS" href="http://purl.org/dc/terms/" hreflang="en" /> + <link rel="schema.DCTYPE" href="http://purl.org/dc/dcmitype/" hreflang="en" /> + <link rel="schema.DCAM" href="http://purl.org/dc/dcam/" hreflang="en" /> + <!-- W3C GRDDL Profile --> + <!-- + <link rel="transformation" href="http://xml.openoffice.org/odf2xhtml/rdf-extract.xsl" /> + --> + + <!-- base URL of document for resolving relative links + NOTE: CHROME has a problem, with relative references as from content table, referencing to root directory instead of document + <xsl:element name="base"> + <xsl:attribute name="href">--> + <!-- earlier 'targetURL' was used for an absolute reference of base provided by the Office (file URL) + <xsl:value-of select="$targetURL" /> + now '.' let relative links work, even if document has been moved --> + <!--<xsl:text>.</xsl:text> + </xsl:attribute> + </xsl:element>--> + </xsl:template> + + <!-- generic template for adding common meta tags --> + <xsl:template name="add-meta-tag"> + <xsl:param name="meta-name" /> + <xsl:param name="meta-data" /> + <xsl:param name="meta-enc" /> + <xsl:param name="meta-lang" /> + + <xsl:if test="$meta-data and $meta-data != ''"> + <xsl:element name="meta"> + <xsl:attribute name="name"> + <xsl:value-of select="$meta-name" /> + </xsl:attribute> + <xsl:attribute name="content"> + <xsl:value-of select="$meta-data" /> + </xsl:attribute> + <xsl:if test="$meta-enc"> + <xsl:attribute name="scheme"> + <xsl:value-of select="$meta-enc" /> + </xsl:attribute> + </xsl:if> + <xsl:if test="$meta-lang"> + <xsl:attribute name="xml:lang"> + <xsl:value-of select="$meta-lang" /> + </xsl:attribute> + </xsl:if> + </xsl:element> + </xsl:if> + </xsl:template> + +</xsl:stylesheet> diff --git a/filter/source/xslt/odf2xhtml/export/xhtml/opendoc2xhtml.xsl b/filter/source/xslt/odf2xhtml/export/xhtml/opendoc2xhtml.xsl new file mode 100644 index 000000000..196b85eae --- /dev/null +++ b/filter/source/xslt/odf2xhtml/export/xhtml/opendoc2xhtml.xsl @@ -0,0 +1,186 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . +--> +<!-- + For further documentation and updates visit http://xml.openoffice.org/odf2xhtml +--> +<xsl:stylesheet version="1.0" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" + xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:dom="http://www.w3.org/2001/xml-events" + xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" + xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" + xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" + xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" + xmlns:math="http://www.w3.org/1998/Math/MathML" + xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" + xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" + xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" + xmlns:ooo="http://openoffice.org/2004/office" + xmlns:oooc="http://openoffice.org/2004/calc" + xmlns:ooow="http://openoffice.org/2004/writer" + xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" + xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" + xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" + xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" + xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" + xmlns:xforms="http://www.w3.org/2002/xforms" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + exclude-result-prefixes="chart config dc dom dr3d draw fo form math meta number office ooo oooc ooow script style svg table text xforms xlink xsd xsi xforms xsd xsi" + xmlns="http://www.w3.org/1999/xhtml"> + + + <!--+++++ INCLUDED XSL MODULES +++++--> + + <!-- inheritance of office style properties is resolved into absolute styles. Office properties gathered as elements --> + <xsl:include href="../common/styles/style_collector.xsl" /> + + <!-- mapping rules of office style properties to CSS/HTML properties --> + <xsl:include href="../common/styles/style_mapping_css.xsl" /> + + <!-- office header element handling especially for XHTML --> + <xsl:include href="header.xsl" /> + + <!-- office body element handling especially for XHTML --> + <xsl:include href="body.xsl" /> + + + <xsl:output method = "xml" + encoding = "UTF-8" + media-type = "application/xhtml+xml" + indent = "no" + omit-xml-declaration = "no" + doctype-public = "-//W3C//DTD XHTML 1.1 plus MathML 2.0//EN" + doctype-system = "http://www.w3.org/Math/DTD/mathml2/xhtml-math11-f.dtd" /> + + + + <xsl:variable name="namespace" select="'http://www.w3.org/1999/xhtml'" /> + + <!--+++++ PARAMETER SECTION +++++--> + + <!-- OPTIONAL: if the document content is provided in a directory structure. Opposite to a single flat XML stream --> + <xsl:param name="isPackageFormat" /> + + <!-- OPTIONAL: (MANDATORY: for all input document with relative external links): parameter is an absolute file URL to the target directory. + Relative links from the office document (e.g. to external graphics) will get this parameter as a prefix --> + <xsl:param name="targetBaseURL" select="'./'" /> + + <!-- OPTIONAL: (MANDATORY: for all input document with content table) : parameter is an absolute file URL to the target document. + Relative links to this office document (e.g. to internal anchor) will get this parameter as a prefix --> + <xsl:param name="targetURL" select="'./'" /> + + <!-- OPTIONAL: (MANDATORY: for input document with relative internal links) + To access contents of an office file (content like the meta.xml, styles.xml file or graphics) a URL could be chosen. + This could be even a JAR URL. The sourceBase of the content URL "jar:file:/C:/temp/Test.sxw!/content.xml" would be + "jar:file:/C:/temp/Test.sxw!/" for example. + When working with OpenOffice API a Package-URL encoded over HTTP can be used to access the jared contents of the jared document. --> + <xsl:param name="sourceBaseURL" select="'./'" /> + + <!-- OPTIONAL: (MANDATORY: for session management by URL rewriting) + Useful for WebApplications: if a HTTP session is not cookie based, URL rewriting is being used (the session is appended to the URL). + This URL session is used for example when links to graphics are created by XSLT. Otherwise the user have to log again in for every graphic he likes to see. --> + <xsl:param name="optionalURLSuffix" /> + + <!-- OPTIONAL: URL to office meta file (flat xml use the URL to the input file) --> + <xsl:param name="metaFileURL" /> + + <!-- OPTIONAL: URL to office meta file (flat xml use the URL to the input file) --> + <xsl:param name="stylesFileURL" /> + + <!-- OPTIONAL: DPI (dots per inch) the standard resolution of given pictures (necessary for the conversion of 'cm' into 'pixel')--> + <!-- Although many pictures have a 96 dpi resolution, a higher resolution give better results for common browsers --> + <!-- Cp. measure_conversion.xsl: + <xsl:param name="dpi" select="111" /> --> + + + <!-- OPTIONAL: in case of using a different processor than a JAVA XSLT, you can unable the Java functionality + (e.g. encoding chapter names for the content-table as href and anchors ) --> + <xsl:param name="java" select="true()" /> + <xsl:param name="javaEnabled" select="boolean($java)" /> + + <!-- OPTIONAL: for activating the debug mode set the variable here to 'true()' or give any value from outside --> + <xsl:param name="debug" select="false()" /> + <xsl:param name="debugEnabled" select="boolean($debug)" /> + <xsl:param name="onlyStyleOutput" select="false()" /> + <xsl:param name="onlyStyleOutputEnabled" select="boolean($onlyStyleOutput)" /> + + <!-- *************************************** --> + <!-- *** build the appropriate HTML file *** --> + <!-- *************************************** --> + <xsl:template match="/"> + <!-- debug output of parameter value set --> + <xsl:if test="$debugEnabled"> + <xsl:call-template name="debug-check-parameter" /> + </xsl:if> + <xsl:message>XSL Vendor: '<xsl:value-of select="system-property('xsl:vendor')"/>'</xsl:message> + <!-- gathers style properties and + returns them as globalData parameter to the 'start-main' template --> + <xsl:call-template name="collect-global-odf-properties" /> + </xsl:template> + + + <!-- *************************** --> + <!-- *** Built up XHTML file *** --> + <!-- *************************** --> + <xsl:template name="start-main"> + <xsl:param name="globalData" /> + + <xsl:variable name="lang"> + <xsl:choose> + <xsl:when test="$globalData/meta-file/*/office:meta/dc:language"> + <xsl:value-of select="$globalData/meta-file/*/office:meta/dc:language" /> + </xsl:when> + <xsl:otherwise>en-US</xsl:otherwise> + </xsl:choose> + </xsl:variable> + + <xsl:element name="html"> + + <xsl:attribute name="lang"><xsl:value-of select="$lang"/></xsl:attribute> + <xsl:comment>This file was converted to xhtml by LibreOffice - see https://cgit.freedesktop.org/libreoffice/core/tree/filter/source/xslt for the code.</xsl:comment> + <xsl:call-template name='create-header'> + <xsl:with-param name="globalData" select="$globalData" /> + </xsl:call-template> + + <xsl:call-template name='create-body'> + <xsl:with-param name="globalData" select="$globalData" /> + </xsl:call-template> + </xsl:element> + </xsl:template> + + + <!-- debug purpose only: + verbose checking of the parameters of this template--> + <xsl:template name="debug-check-parameter"> + <xsl:message>Parameter dpi: <xsl:value-of select="$dpi" /></xsl:message> + <xsl:message>Parameter metaFileURL: <xsl:value-of select="$metaFileURL" /></xsl:message> + <xsl:message>Parameter stylesFileURL: <xsl:value-of select="$stylesFileURL" /></xsl:message> + <xsl:message>Parameter sourceBaseURL: <xsl:value-of select="$sourceBaseURL" /></xsl:message> + <xsl:message>Parameter targetBaseURL: <xsl:value-of select="$targetBaseURL" /></xsl:message> + <xsl:message>Parameter onlyStyleOutputEnabled: <xsl:value-of select="$onlyStyleOutputEnabled" /></xsl:message> + <xsl:message>Parameter debugEnabled: <xsl:value-of select="$debugEnabled" /></xsl:message> + <xsl:message>Parameter java: <xsl:value-of select="$java" /></xsl:message> + <xsl:message>Parameter javaEnabled: <xsl:value-of select="$javaEnabled" /></xsl:message> + </xsl:template> + +</xsl:stylesheet> diff --git a/filter/source/xslt/odf2xhtml/export/xhtml/table.xsl b/filter/source/xslt/odf2xhtml/export/xhtml/table.xsl new file mode 100644 index 000000000..8448665d2 --- /dev/null +++ b/filter/source/xslt/odf2xhtml/export/xhtml/table.xsl @@ -0,0 +1,213 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + --> +<!-- + For further documentation and updates visit http://xml.openoffice.org/odf2xhtml +--> +<xsl:stylesheet version="1.0" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" + xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:dom="http://www.w3.org/2001/xml-events" + xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" + xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" + xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" + xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" + xmlns:math="http://www.w3.org/1998/Math/MathML" + xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" + xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" + xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" + xmlns:ooo="http://openoffice.org/2004/office" + xmlns:oooc="http://openoffice.org/2004/calc" + xmlns:ooow="http://openoffice.org/2004/writer" + xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" + xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" + xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" + xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" + xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" + xmlns:xforms="http://www.w3.org/2002/xforms" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + exclude-result-prefixes="chart config dc dom dr3d draw fo form math meta number office ooo oooc ooow script style svg table text xforms xlink xsd xsi" + xmlns="http://www.w3.org/1999/xhtml"> + + + + <!-- current node is a table:table --> + <xsl:template name="create-table-children"> + <xsl:param name="globalData" /> + <xsl:param name="allVisibleTableRows" /> + <xsl:param name="allTableColumns" /> + + <xsl:element name="colgroup"> + <xsl:for-each select="$allTableColumns/table:table-column"> + <xsl:if test="not(@table:visibility = 'collapse' or @table:visibility = 'filter')"> + <xsl:element name="col"> + <xsl:variable name="value" select="$globalData/all-doc-styles/style[@style:name = current()/@table:style-name]/*/@style:column-width" /> + <xsl:if test="$value"> + <xsl:attribute name="width"> + <!-- using the absolute width, problems with the relative in browser (in OOo style:rel-column-width) --> + <xsl:call-template name="convert2px"> + <xsl:with-param name="value" select="$globalData/all-doc-styles/style[@style:name = current()/@table:style-name]/*/@style:column-width" /> + </xsl:call-template> + </xsl:attribute> + </xsl:if> + </xsl:element> + <!-- *** the column-style *** + <xsl:attribute name="width"> + <xsl:variable name="currentColumnStyleName" select="$allTableColumns/table:table-column[position() = $columnPosition]/@table:style-name" /> + <xsl:value-of select="$globalData/all-doc-styles/style[@style:name = $currentColumnStyleName]/*/@style:column-width" /> + </xsl:attribute>--> + </xsl:if> + </xsl:for-each> + </xsl:element> + + <xsl:call-template name="create-table-rows"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="allVisibleTableRows" select="$allVisibleTableRows" /> + <xsl:with-param name="allTableColumns" select="$allTableColumns" /> + </xsl:call-template> + </xsl:template> + + + + <!-- Creating the content of a table content using CSS styles --> + <xsl:template name="create-table-cell-content"> + <xsl:param name="tableDataType" /> + <xsl:param name="globalData" /> + <xsl:param name="allTableColumns" /> + <xsl:param name="columnPosition" /> + <xsl:param name="currentTableColumn" /> + + <xsl:element name="{$tableDataType}"> + + <!-- if parser reads DTD the default is set to '1' --> + <xsl:if test="@table:number-columns-spanned and @table:number-columns-spanned > 1"> + <xsl:attribute name="colspan"> + <xsl:value-of select="@table:number-columns-spanned" /> + </xsl:attribute> + </xsl:if> + <!-- if parser reads DTD the default is set to '1' --> + <xsl:if test="@table:number-rows-spanned and @table:number-rows-spanned > 1"> + <xsl:attribute name="rowspan"> + <xsl:value-of select="@table:number-rows-spanned" /> + </xsl:attribute> + </xsl:if> + + + <!-- *** the cell-style *** --> + <!-- The cell style has no conclusion with the column style, so we switch the order/priorities due to browser issues + + The cell-style depends on two attributes: + + 1) table:style-name - the style properties of cell. When they exist, a default alignment (cp. below) will be added for the + case of no alignment in the style exist. + + 2) office:value-type - the value type of the table-cell giving the default alignments. + By default a string value is left aligned, all other are aligned:right. + --> + <xsl:choose> + <xsl:when test="@table:style-name"> + <xsl:call-template name="set-styles"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="styleName" select="@table:style-name" /> + <xsl:with-param name="currentTableColumn" select="$currentTableColumn" /> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <!-- Cells without a style use the 'table:default-cell-style-name' + when there is no default cell style specified for the current column. --> + <xsl:variable name="defaultCellStyleName" select="$currentTableColumn/@table:default-cell-style-name" /> + <xsl:choose> + <xsl:when test="$defaultCellStyleName"> + <xsl:call-template name="set-styles"> + <xsl:with-param name="globalData" select="$globalData" /> + <xsl:with-param name="styleName" select="$defaultCellStyleName" /> + <xsl:with-param name="currentTableColumn" select="$currentTableColumn" /> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <!-- No cell style exists, nor a default table cell style for the column --> + <xsl:attribute name="style"> + <!-- sets cell alignment dependent of cell value type --> + <xsl:call-template name="set-cell-alignment" /> + </xsl:attribute> + </xsl:otherwise> + </xsl:choose> + </xsl:otherwise> + </xsl:choose> + + <xsl:if test="$debugEnabled"> + <xsl:message>A table cell '<xsl:value-of select="$tableDataType" />' element has been added!</xsl:message> + </xsl:if> + + <!-- empty cell tags produce problems with width CSS style on itself other table cells as well + therefore a non breakable space ( / ) have been inserted.--> + <xsl:choose> + <xsl:when test="node()"> + <xsl:call-template name="apply-styles-and-content"> + <xsl:with-param name="globalData" select="$globalData" /> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:call-template name="apply-styles-and-content"> + <xsl:with-param name="globalData" select="$globalData" /> + </xsl:call-template> + <xsl:text> </xsl:text> + </xsl:otherwise> + </xsl:choose> + + </xsl:element> + </xsl:template> + + + <!-- Sets the cell alignment by the 'office:value-type' of the 'table:table-cell'. + Strings have a left alignment, other values right --> + <xsl:template name="set-cell-alignment"> + <xsl:choose> + <xsl:when test="@office:value-type and not(@office:value-type = 'string')">text-align:right; </xsl:when> + <xsl:otherwise>text-align:left;</xsl:otherwise> + </xsl:choose> + </xsl:template> + + + + <!-- Sets styles of a cell --> + <xsl:template name="set-styles"> + <xsl:param name="globalData" /> + <xsl:param name="styleName" /> + <xsl:param name="currentTableColumn" /> + + <xsl:attribute name="style"> + <!-- sets cell alignment dependent of cell value type --> + <xsl:call-template name="set-cell-alignment" /> + + <!-- set column style (disjunct of cell style) --> + <xsl:value-of select="$globalData/all-styles/style[@style:name = $currentTableColumn/@table:style-name]/final-properties" /> + + </xsl:attribute> + + <!-- cell style header --> + <xsl:attribute name="class"> + <xsl:value-of select="translate($styleName, '.,;: %()[]/\+', '_____________')"/> + </xsl:attribute> + </xsl:template> +</xsl:stylesheet> + |