filter/source/xslt/odf2xhtml/export/common/body.xsl                     |    2 
 filter/source/xslt/odf2xhtml/export/common/styles/style_mapping_css.xsl |    2 
 filter/source/xslt/odf2xhtml/export/xhtml/body.xsl                      |  118 
++++++----
 sd/qa/unit/HtmlExportTest.cxx                                           |   30 
++
 sd/qa/unit/data/tdf154989.odg                                           |binary
 sw/qa/extras/htmlexport/xhtmlexport.cxx                                 |   10 
 6 files changed, 110 insertions(+), 52 deletions(-)

New commits:
commit cb27c6c1b82272e8812bcb446e7179cc4f32bf34
Author:     Svante Schubert <svante.schub...@gmail.com>
AuthorDate: Fri May 5 12:26:53 2023 +0200
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Mon May 8 17:21:42 2023 +0200

    tdf#154989 filter: XHTML export: avoid duplicated frames
    
    Various updates on XSLT ODF2HTML triggered by TDF issue 154989 - esp. 
image/frame positioning by CSS position
    
    (regression from commit f680b6d74209fd78c547201b2f14c6547e55c81b)
    
    Change-Id: I4d08a67ebca7ae3808db07c828488bb9284623a3
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/151094
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
    (cherry picked from commit b70e2ee3ec5bfd21f27597195b745171932032e8)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/151510

diff --git a/filter/source/xslt/odf2xhtml/export/common/body.xsl 
b/filter/source/xslt/odf2xhtml/export/common/body.xsl
index bcad3abd9ab3..8dfb78222186 100644
--- a/filter/source/xslt/odf2xhtml/export/common/body.xsl
+++ b/filter/source/xslt/odf2xhtml/export/common/body.xsl
@@ -81,7 +81,7 @@
     <!-- *************** -->
 
     <!-- ID / NAME of text-box -->
-    <xsl:template match="@draw:name">
+    <xsl:template match="@draw:name | @text:id | @xml:id">
         <xsl:attribute name="id">
             <xsl:choose>
                 <xsl:when test="number(substring(.,1,1))">
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
index c81cc9a1e0be..06e22d7e2fed 100644
--- a/filter/source/xslt/odf2xhtml/export/common/styles/style_mapping_css.xsl
+++ b/filter/source/xslt/odf2xhtml/export/common/styles/style_mapping_css.xsl
@@ -23,7 +23,7 @@
 
 
     <!-- *** Properties with a 'fo:' prefix *** -->
-    <xsl:template match="@fo:background-color">
+    <xsl:template match="@fo:background-color | @draw:fill-color">
         <xsl:text>background-color:</xsl:text>
         <xsl:value-of select="."/>
         <xsl:text>; </xsl:text>
diff --git a/filter/source/xslt/odf2xhtml/export/xhtml/body.xsl 
b/filter/source/xslt/odf2xhtml/export/xhtml/body.xsl
index ca7a6906b82c..6f64b5a83d82 100644
--- a/filter/source/xslt/odf2xhtml/export/xhtml/body.xsl
+++ b/filter/source/xslt/odf2xhtml/export/xhtml/body.xsl
@@ -141,15 +141,21 @@
             </xsl:choose>
             <!-- adapt page size -->
             <xsl:variable name="pageWidth" 
select="$pageProperties/style:page-layout-properties/@fo:page-width"/>
+            <xsl:variable name="pageHeight" 
select="$pageProperties/style:page-layout-properties/@fo:height"/>
 
             <!-- 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:if test="$pageWidth or $pageHeight 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:value-of select="$pageWidth" />
+                        <xsl:text>;</xsl:text>
+                    </xsl:if>
+                    <xsl:if test="$pageHeight">
+                        <xsl:text>max-height:</xsl:text>
+                        <xsl:value-of select="$pageHeight" />
                         <xsl:text>;</xsl:text>
                     </xsl:if>
                     <xsl:if 
test="$pageProperties/style:page-layout-properties/@fo:* or 
$backgroundImage/@xlink:href">
@@ -251,20 +257,20 @@
         <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: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:if test="normalize-space($dimension)!=''">
                 <xsl:attribute name="style">
-                    <xsl:value-of select="$dimension"/>
+                    <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="@xml:id">
+                <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>
@@ -359,11 +365,12 @@
                     <xsl:call-template name="create-paragraph">
                         <xsl:with-param name="globalData" select="$globalData" 
/>
                         <xsl:with-param name="footnotePrefix" 
select="$footnotePrefix" />
+                        <xsl:with-param name="frameFloating" select="true()"/>
                     </xsl:call-template>
                 </xsl:if>
 
             </xsl:when>
-            <xsl:when test="draw:frame and ((normalize-space($childText) != 
'')  or (((count(*) - count(text:soft-page-break)) &gt; 1)))">
+            <xsl:when test="name() = 'draw:frame' and 
((normalize-space($childText) != '')  or (((count(*) - 
count(text:soft-page-break)) &gt; 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) -->
 
@@ -415,7 +422,7 @@
                     &#160; 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;">&#160;</div>
             </xsl:when>
-            <xsl:when test="text:tab and not(ancestor::text:index-body)">
+            <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.
@@ -434,7 +441,7 @@
                             <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 -->
+                            <!-- TODO: left-margin in order with bidirectional 
-->
                             <xsl:choose>
                                 <xsl:when test="contains($imageParagraphStyle, 
'margin-left:')">
                                     <xsl:call-template name="convert2cm">
@@ -689,6 +696,7 @@
         <xsl:param name="globalData"/>
         <!-- the footnote symbol is the prefix for a footnote in the footer -->
         <xsl:param name="footnotePrefix"/>
+        <xsl:param name="frameFloating"/>
 
         <!-- xhtml:p may only contain inline elements.
              If there is one frame beyond, div must be used! -->
@@ -698,7 +706,10 @@
                 <xsl:otherwise>p</xsl:otherwise>
             </xsl:choose>
         </xsl:variable>
-
+        <xsl:if test="name() = 'text:p' and $elementName = 'div'">
+            <xsl:comment>Next 'div' was a 'text:p'.</xsl:comment>
+            <xsl:text>&#xa;</xsl:text>
+        </xsl:if>
         <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,
@@ -798,7 +809,7 @@
         <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.
+    <!-- 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">
@@ -808,17 +819,17 @@
         <xsl:param name="leftPosition" select="0" />
         <xsl:param name="parentMarginLeft" />
         <xsl:param name="stopAtFirstFrame" select="false()" />
-        <xsl:param name="tdf146264hack" select="false()" />
+        <xsl:param name="frameFloating" 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:with-param name="frameFloating" select="true()"/>
                 </xsl:call-template>
                 <!-- next elements will be called after the creation with the 
new indent (plus width of frame) -->
             </xsl:when>
@@ -839,7 +850,7 @@
                             <!-- 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:if test="not($frameFloating)">
                                 <xsl:apply-templates select=".">
                                     <xsl:with-param name="globalData" 
select="$globalData"/>
                                 </xsl:apply-templates>
@@ -914,13 +925,13 @@
         <xsl:param name="globalData"/>
         <xsl:param name="previousFrameWidths" select="0"/>
         <xsl:param name="previousFrameHeights" select="0" />
-        <xsl:param name="tdf146264hack" select="false()" />
+        <xsl:param name="frameFloating" 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:with-param name="frameFloating" select="$frameFloating"/>
         </xsl:call-template>
         <!-- after the last draw:frame sibling the CSS float is disabled -->
         <xsl:if test="@text:anchor-type!='as-char'">
@@ -964,7 +975,7 @@
         <xsl:param name="previousFrameHeights" select="0" />
         <xsl:param name="parentMarginLeft"/>
         <xsl:param name="stopAtFirstFrame" select="false()" />
-        <xsl:param name="tdf146264hack" select="false()" />
+        <xsl:param name="frameFloating" select="false()" />
 
         <xsl:variable name="parentMarginLeftNew">
             <xsl:choose>
@@ -1042,15 +1053,8 @@
             <xsl:with-param name="parentMarginLeftNew" 
select="$parentMarginLeftNew"/>
             <xsl:with-param name="leftPosition" select="$leftPosition"/>
             <xsl:with-param name="svgY" select="$svgY"/>
+            <xsl:with-param name="frameFloating" select="$frameFloating"/>
         </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">
@@ -1084,18 +1088,33 @@
                     <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:choose>
+                        <xsl:when test="@text:anchor-type='as-char'">
+                            <!-- images being used as character are not 
floating and ar not positioned (CSS position:static being the default)-->
+                            <!--<xsl:text> position:static;</xsl:text>-->
+                        </xsl:when>
+                        <xsl:when 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:when>
+                        <!-- @text:anchor-type='' -->
+                        <xsl:otherwise>
+                                <xsl:text> position:absolute; left:</xsl:text>
+                                    <xsl:value-of select="$leftPosition" />
+                            <xsl:text>cm; </xsl:text>
                             <xsl:text>top:</xsl:text>
-                            <xsl:value-of select="$svgY"/>
+                                    <xsl:value-of select="$svgY" />
                             <xsl:text>cm; </xsl:text>
-                        </xsl:if>
-                    </xsl:if>
+                        </xsl:otherwise>
+                    </xsl:choose>
                 </xsl:attribute>
                 <xsl:apply-templates select="@*">
                     <xsl:with-param name="globalData" select="$globalData"/>
@@ -2572,7 +2591,7 @@
             <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:with-param name="frameFloating" 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>
@@ -2831,7 +2850,22 @@
         <xsl:param name="globalData"/>
 
         <xsl:attribute name="class">
-            <xsl:value-of select="translate(., '.,;: %()[]/\+', 
'_____________')"/>
+               <xsl:choose>
+                       <xsl:when test="name() = 'draw:text-style-name' or 
name() = 'draw:style-name'">
+                    <xsl:choose>
+                        <xsl:when test="parent::*/@draw:text-style-name and 
parent::*/@draw:style-name">
+                            <xsl:value-of 
select="translate(parent::*/@draw:style-name, '.,;: %()[]/\+', 
'_____________')" /><xsl:text> </xsl:text>
+                            <xsl:value-of 
select="translate(parent::*/@draw:text-style-name, '.,;: %()[]/\+', 
'_____________')" />
+                        </xsl:when>
+                        <xsl:otherwise>
+                            <xsl:value-of select="translate(., '.,;: 
%()[]/\+', '_____________')" />
+                        </xsl:otherwise>
+                    </xsl:choose>
+                </xsl:when>
+                <xsl:otherwise>
+                    <xsl:value-of select="translate(., '.,;: %()[]/\+', 
'_____________')"/>
+                </xsl:otherwise>                   
+               </xsl:choose>    
         </xsl:attribute>
     </xsl:template>
 
diff --git a/sd/qa/unit/HtmlExportTest.cxx b/sd/qa/unit/HtmlExportTest.cxx
index 812757bc1761..a1afe6906ff4 100644
--- a/sd/qa/unit/HtmlExportTest.cxx
+++ b/sd/qa/unit/HtmlExportTest.cxx
@@ -20,6 +20,12 @@ public:
     {
     }
 
+    virtual void registerNamespaces(xmlXPathContextPtr& pXmlXPathCtx) override
+    {
+        xmlXPathRegisterNs(pXmlXPathCtx, BAD_CAST("xhtml"),
+                           BAD_CAST("http://www.w3.org/1999/xhtml";));
+    }
+
     void testHTMLExport()
     {
         loadFromURL(u"HtmlExportTestDocument.odp");
@@ -40,8 +46,32 @@ public:
         assertXPath(htmlDoc, "/html/head/meta[3]", "content", 
"2014-04-09T17:05:41.987922038");
     }
 
+    void testTdf154989()
+    {
+        loadFromURL(u"tdf154989.odg");
+        save("XHTML Draw File");
+        xmlDocUniquePtr pXmlDoc = parseXml(maTempFile);
+
+        assertXPath(pXmlDoc, "/xhtml:html", 1);
+        // 1 page
+        assertXPath(pXmlDoc, "/xhtml:html/xhtml:body/xhtml:div", 1);
+        // 4 shapes
+        assertXPath(pXmlDoc, "/xhtml:html/xhtml:body/xhtml:div[1]/xhtml:div", 
4);
+        // 3 of them are text boxes
+        assertXPath(pXmlDoc, 
"/xhtml:html/xhtml:body/xhtml:div[1]/xhtml:div/xhtml:div", 3);
+        // not sure if the order of these is stable?
+        assertXPathContent(pXmlDoc,
+                           
"/xhtml:html/xhtml:body/xhtml:div[1]/xhtml:div[2]/xhtml:div/xhtml:p",
+                           "before");
+        assertXPathContent(
+            pXmlDoc, 
"/xhtml:html/xhtml:body/xhtml:div[1]/xhtml:div[3]/xhtml:div/xhtml:p", "above");
+        assertXPathContent(
+            pXmlDoc, 
"/xhtml:html/xhtml:body/xhtml:div[1]/xhtml:div[4]/xhtml:div/xhtml:p", "below");
+    }
+
     CPPUNIT_TEST_SUITE(SdHTMLFilterTest);
     CPPUNIT_TEST(testHTMLExport);
+    CPPUNIT_TEST(testTdf154989);
     CPPUNIT_TEST_SUITE_END();
 };
 
diff --git a/sd/qa/unit/data/tdf154989.odg b/sd/qa/unit/data/tdf154989.odg
new file mode 100644
index 000000000000..5bc7e83042dd
Binary files /dev/null and b/sd/qa/unit/data/tdf154989.odg differ
diff --git a/sw/qa/extras/htmlexport/xhtmlexport.cxx 
b/sw/qa/extras/htmlexport/xhtmlexport.cxx
index 9f5b26745f5b..923c3fecda8a 100644
--- a/sw/qa/extras/htmlexport/xhtmlexport.cxx
+++ b/sw/qa/extras/htmlexport/xhtmlexport.cxx
@@ -76,14 +76,8 @@ DECLARE_HTMLEXPORT_TEST(testTdf118637, "tdf118637.odt")
     CPPUNIT_ASSERT(pStream);
     sal_uInt64 nLength = pStream->TellEnd();
     OString aStream(read_uInt8s_ToOString(*pStream, nLength));
-    CPPUNIT_ASSERT(
-        aStream.indexOf(
-            "<div style=\"display:inline; position:relative; left:0cm;\">The 
formula  </div>")
-        != -1);
-    CPPUNIT_ASSERT(
-        aStream.indexOf(
-            "<div style=\"display:inline; position:relative; 
left:0cm;\">should be inline.</div>")
-        != -1);
+    CPPUNIT_ASSERT(aStream.indexOf("The formula  ") != -1);
+    CPPUNIT_ASSERT(aStream.indexOf("should be inline.</div>") != -1);
 }
 
 DECLARE_HTMLEXPORT_TEST(testTdf145361, "tdf145361.odt")

Reply via email to