tdf#170438 docx export: never export listItem with empty displayText

MS Word was reporting a document as corrupt
after LO round-tripped it with an empty displayText.
However, an empty w:value is not a 'corrupt' result.

Note that this situation was possible also while importing DOCX.
We don't always import SDTs as content controls (e.g. in tables).
In that case, only the 'values' are considered,
so an empty entry is created in the dropdown field,
which then got exported as an empty displayText.

make CppunitTest_sw_ooxmlexport25 \
    CPPUNIT_TEST_NAME=testTdf170438_dropdown

ooxmlexport13's tdf119809.docx is a VML shape
that is called a combobox, and it exported
with WritePostponedFormControl.
It sounds like it can only have 'values' when added by a VBA macro,
so likely these will almost never output a displayText.

Change-Id: Ib306eda90b4179e10402c276e7c47a3bfdd83cfb
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/197867
Reviewed-by: Justin Luth <jluth@mail.com>
Tested-by: Jenkins
This commit is contained in:
Justin Luth
2026-01-23 19:16:46 +01:00
parent 2dabcfc3f3
commit 270fe90efb
3 changed files with 16 additions and 2 deletions
Binary file not shown.
@@ -150,6 +150,18 @@ DECLARE_OOXMLEXPORT_TEST(testTdf165478_bottomAligned, "tdf165478_bottomAligned.d
CPPUNIT_ASSERT_EQUAL(sal_Int32(1887), nFlyTop);
}
CPPUNIT_TEST_FIXTURE(Test, testTdf170438_dropdown)
{
createSwDoc("tdf170438_dropdown.odt");
saveAndReload(TestFilter::DOCX);
xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr);
// MS Word reports document as corrupt if displayText is empty
assertXPath(pXmlDoc, "//w:listItem[1]", "displayText", u" ");
assertXPath(pXmlDoc, "//w:listItem[1]", "value", u""); // value may be empty
}
CPPUNIT_TEST_FIXTURE(Test, testTdf170389_manyTabstops)
{
createSwDoc("tdf170389_manyTabstops.odt");
+4 -2
View File
@@ -2882,9 +2882,10 @@ void DocxAttributeOutput::WriteSdtDropDownStart(
for (auto const& rItem : rListItems)
{
auto const item(OUStringToOString(rItem, RTL_TEXTENCODING_UTF8));
OString sDisplayText = item.isEmpty() ? " "_ostr : item; // displayText must not be empty
m_pSerializer->singleElementNS(XML_w, XML_listItem,
FSNS(XML_w, XML_value), item,
FSNS(XML_w, XML_displayText), item);
FSNS(XML_w, XML_displayText), sDisplayText);
}
m_pSerializer->endElementNS(XML_w, XML_dropDownList);
@@ -5894,8 +5895,9 @@ void DocxAttributeOutput::WritePostponedFormControl(const SdrObject* pObject)
for (const auto& rItem : aItems)
{
OUString sDisplayText = rItem.isEmpty() ? " " : rItem; // displayText must not be empty
m_pSerializer->singleElementNS(XML_w, XML_listItem,
FSNS(XML_w, XML_displayText), rItem,
FSNS(XML_w, XML_displayText), sDisplayText,
FSNS(XML_w, XML_value), rItem);
}