sw/qa/extras/ooxmlexport/data/tdf169274.docx    |binary
 sw/qa/extras/ooxmlexport/ooxmlexport25.cxx      |   13 +++++++++
 sw/source/writerfilter/dmapper/DomainMapper.cxx |   34 +++++++++++++-----------
 3 files changed, 32 insertions(+), 15 deletions(-)

New commits:
commit e30ba5582ff40c016978b40318ed861d075f7b6f
Author:     Karthik Godha <[email protected]>
AuthorDate: Wed Nov 5 20:45:26 2025 +0530
Commit:     Michael Stahl <[email protected]>
CommitDate: Mon Dec 15 14:29:05 2025 +0100

    tdf#169274: Fix export of SDTs with DataBindings
    
    Run-level SDTs containing DataBinding properties are exported twice
    which results in corrupted XML
    
    Change-Id: I24bcdf76a5cac850257b36f5a042d5b61a74118d
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/193467
    Tested-by: Jenkins CollaboraOffice <[email protected]>
    Reviewed-by: Michael Stahl <[email protected]>
    (cherry picked from commit d2b7ec90d4d8a85091dc985092ba000b0acad540)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/195635
    Tested-by: Michael Stahl <[email protected]>

diff --git a/sw/qa/extras/ooxmlexport/data/tdf169274.docx 
b/sw/qa/extras/ooxmlexport/data/tdf169274.docx
new file mode 100644
index 000000000000..f9ce604adf58
Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/tdf169274.docx differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport25.cxx 
b/sw/qa/extras/ooxmlexport/ooxmlexport25.cxx
index 1b0f0d794b09..c49120ac2834 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport25.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport25.cxx
@@ -196,6 +196,19 @@ CPPUNIT_TEST_FIXTURE(Test, testWNumDuplication)
     CPPUNIT_ASSERT_EQUAL(10, countXPathNodes(pXmlNum, "//w:numbering/w:num"));
 }
 
+CPPUNIT_TEST_FIXTURE(Test, testTdf169274)
+{
+    loadAndSave("tdf169274.docx");
+
+    xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr);
+    const OString sPath = "//w:body/w:tbl/w:tr/w:tc/w:p/w:sdt/"_ostr;
+
+    // Verify SDT exists with dataBinding property
+    assertXPath(pXmlDoc, sPath + "w:sdtPr/w:dataBinding", 1);
+    // Verify there are no nested SDTs
+    assertXPath(pXmlDoc, sPath + "w:sdtContent/w:sdt", 0);
+}
+
 } // end of anonymous namespace
 CPPUNIT_PLUGIN_IMPLEMENT();
 
diff --git a/sw/source/writerfilter/dmapper/DomainMapper.cxx 
b/sw/source/writerfilter/dmapper/DomainMapper.cxx
index e85eaa77ac96..721a7b6a0a55 100644
--- a/sw/source/writerfilter/dmapper/DomainMapper.cxx
+++ b/sw/source/writerfilter/dmapper/DomainMapper.cxx
@@ -4463,12 +4463,21 @@ void DomainMapper::lcl_utext(const sal_Unicode *const 
data_, size_t len)
             m_pImpl->m_pSdtHelper->getInteropGrabBagAndClear();
             return;
         }
-        
if((m_pImpl->m_pSdtHelper->containedInInteropGrabBag(u"ooxml:CT_SdtPr_checkbox"_ustr)
 ||
-                
m_pImpl->m_pSdtHelper->containedInInteropGrabBag(u"ooxml:CT_SdtPr_text"_ustr) ||
-                
m_pImpl->m_pSdtHelper->containedInInteropGrabBag(u"ooxml:CT_SdtPr_dataBinding"_ustr)
 ||
-                
m_pImpl->m_pSdtHelper->containedInInteropGrabBag(u"ooxml:CT_SdtPr_citation"_ustr)
 ||
-                
(m_pImpl->m_pSdtHelper->containedInInteropGrabBag(u"ooxml:CT_SdtPr_id"_ustr) &&
-                        m_pImpl->m_pSdtHelper->getInteropGrabBagSize() == 1)) 
&& !m_pImpl->m_pSdtHelper->isOutsideAParagraph())
+        const SdtControlType aControlType = 
m_pImpl->m_pSdtHelper->getControlType();
+        if (aControlType != SdtControlType::unsupported && aControlType != 
SdtControlType::unknown
+            && m_pImpl->m_pSdtHelper->GetSdtType() == 
NS_ooxml::LN_CT_SdtRun_sdtContent)
+        {
+            m_pImpl->m_pSdtHelper->getInteropGrabBagAndClear();
+        }
+        else if 
((m_pImpl->m_pSdtHelper->containedInInteropGrabBag(u"ooxml:CT_SdtPr_checkbox"_ustr)
+                  || 
m_pImpl->m_pSdtHelper->containedInInteropGrabBag(u"ooxml:CT_SdtPr_text"_ustr)
+                  || m_pImpl->m_pSdtHelper->containedInInteropGrabBag(
+                      u"ooxml:CT_SdtPr_dataBinding"_ustr)
+                  || m_pImpl->m_pSdtHelper->containedInInteropGrabBag(
+                      u"ooxml:CT_SdtPr_citation"_ustr)
+                  || 
(m_pImpl->m_pSdtHelper->containedInInteropGrabBag(u"ooxml:CT_SdtPr_id"_ustr)
+                      && m_pImpl->m_pSdtHelper->getInteropGrabBagSize() == 1))
+                 && !m_pImpl->m_pSdtHelper->isOutsideAParagraph())
         {
             PropertyMapPtr pContext = 
m_pImpl->GetTopContextOfType(CONTEXT_CHARACTER);
 
@@ -4477,20 +4486,15 @@ void DomainMapper::lcl_utext(const sal_Unicode *const 
data_, size_t len)
                 pContext = m_pImpl->GetTopFieldContext()->getProperties();
 
             uno::Sequence<beans::PropertyValue> aGrabBag = 
m_pImpl->m_pSdtHelper->getInteropGrabBagAndClear();
-            if (m_pImpl->GetSdtStarts().empty()
-                || (m_pImpl->m_pSdtHelper->getControlType() != 
SdtControlType::dropDown
-                    && m_pImpl->m_pSdtHelper->getControlType() != 
SdtControlType::comboBox))
-            {
-                pContext->Insert(PROP_SDTPR, uno::Any(aGrabBag), true, 
CHAR_GRAB_BAG);
-            }
+            pContext->Insert(PROP_SDTPR, uno::Any(aGrabBag), true, 
CHAR_GRAB_BAG);
         }
         else
         {
             uno::Sequence<beans::PropertyValue> aGrabBag = 
m_pImpl->m_pSdtHelper->getInteropGrabBagAndClear();
             if (m_pImpl->GetSdtStarts().empty()
-                || (m_pImpl->m_pSdtHelper->getControlType() != 
SdtControlType::dropDown
-                    && m_pImpl->m_pSdtHelper->getControlType() != 
SdtControlType::comboBox
-                    && m_pImpl->m_pSdtHelper->getControlType() != 
SdtControlType::richText))
+                || (aControlType != SdtControlType::dropDown
+                    && aControlType != SdtControlType::comboBox
+                    && aControlType != SdtControlType::richText))
             {
                 
m_pImpl->GetTopContextOfType(CONTEXT_PARAGRAPH)->Insert(PROP_SDTPR,
                         uno::Any(aGrabBag), true, PARA_GRAB_BAG);

Reply via email to