From 5248afb9b630b5902936ea8a2f5c87248cb36dd3 Mon Sep 17 00:00:00 2001 From: Miklos Vajna Date: Fri, 12 Sep 2025 08:38:32 +0200 Subject: [PATCH] tdf#168321 sw format redline, direct: fix ODF strict export Save the bugdoc in strict ODF, the exporter crashes due to an assertion failure. What happens is that strict ODF doesn't add the loext namespace alias to the alias list, so we crash when we would write an loext attribute. Fix the problem by simply throwing away the direct format of a format redline when saving to strict ODF, just to please the validator. If we're at it, also don't register the direct format of the format redline in the autostyle pool in that case, since it would be unreferenced anyway. Change-Id: I0de9ee114be9ef67f97716cf5fd9aaa9f8757683 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/190851 Reviewed-by: Miklos Vajna Tested-by: Jenkins --- xmloff/qa/unit/text.cxx | 20 ++++++++ xmloff/source/text/XMLRedlineExport.cxx | 66 ++++++++++++++----------- 2 files changed, 57 insertions(+), 29 deletions(-) diff --git a/xmloff/qa/unit/text.cxx b/xmloff/qa/unit/text.cxx index a82e62ac6e30..f6f4821cb97e 100644 --- a/xmloff/qa/unit/text.cxx +++ b/xmloff/qa/unit/text.cxx @@ -29,6 +29,8 @@ #include #include #include +#include +#include using namespace ::com::sun::star; @@ -1373,6 +1375,24 @@ CPPUNIT_TEST_FIXTURE(XmloffStyleTest, testRedlineFormatCharStyleExport) CPPUNIT_ASSERT_EQUAL(u"Strong_20_Emphasis"_ustr, aStyleName); } +CPPUNIT_TEST_FIXTURE(XmloffStyleTest, testRedlineFormatCharPropsStrictExport) +{ + // Given a document with a format redline, the redline contains the old char props: + SetODFDefaultVersion(SvtSaveOptions::ODFDefaultVersion::ODFVER_014); + comphelper::ScopeGuard g([] { SetODFDefaultVersion(SvtSaveOptions::ODFVER_LATEST); }); + loadFromFile(u"redline-format-char-props.docx"); + + // When exporting the document to ODT strict: + save(u"writer8"_ustr); + + // Then make sure no loext attribute is written: + xmlDocUniquePtr pXmlDoc = parseExport(u"content.xml"_ustr); + // Without the accompanying fix in place, this test would have failed in an assertion in + // SvXMLNamespaceMap::GetQNameByKey(). + assertXPathNoAttribute(pXmlDoc, "//text:tracked-changes/text:changed-region/text:format-change", + "style-name"); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmloff/source/text/XMLRedlineExport.cxx b/xmloff/source/text/XMLRedlineExport.cxx index f85d9671878b..3fdec09b8610 100644 --- a/xmloff/source/text/XMLRedlineExport.cxx +++ b/xmloff/source/text/XMLRedlineExport.cxx @@ -262,17 +262,21 @@ void XMLRedlineExport::ExportChangeAutoStyle( rExport.GetTextParagraphExport()->collectTextAutoStyles(xText); } - // See if the format redline has an autostyle for old direct formatting: if so, export that as - // an autostyle. - aAny = rPropSet->getPropertyValue(u"RedlineAutoFormat"_ustr); - uno::Reference xAutoFormat; - aAny >>= xAutoFormat; - if (xAutoFormat.is()) + SvtSaveOptions::ODFSaneDefaultVersion eVersion = rExport.getSaneDefaultVersion(); + if (eVersion & SvtSaveOptions::ODFSVER_EXTENDED) { - // Check for parent style when declaring the automatic style. - rExport.GetTextParagraphExport()->Add(XmlStyleFamily::TEXT_TEXT, xAutoFormat, - /*aAddStates=*/{}, - /*bCheckParent=*/true); + // See if the format redline has an autostyle for old direct formatting: if so, export that as + // an autostyle. + aAny = rPropSet->getPropertyValue(u"RedlineAutoFormat"_ustr); + uno::Reference xAutoFormat; + aAny >>= xAutoFormat; + if (xAutoFormat.is()) + { + // Check for parent style when declaring the automatic style. + rExport.GetTextParagraphExport()->Add(XmlStyleFamily::TEXT_TEXT, xAutoFormat, + /*aAddStates=*/{}, + /*bCheckParent=*/true); + } } } @@ -367,27 +371,31 @@ void XMLRedlineExport::ExportChangedRegion( OUString sType; aAny >>= sType; - // See if the format redline has an autostyle for old direct formatting: if so, refer to the - // already exported autostyle. - aAny = rPropSet->getPropertyValue(u"RedlineAutoFormat"_ustr); - uno::Reference xAutoStyle; - aAny >>= xAutoStyle; - if (xAutoStyle.is()) + SvtSaveOptions::ODFSaneDefaultVersion eVersion = rExport.getSaneDefaultVersion(); + if (eVersion & SvtSaveOptions::ODFSVER_EXTENDED) { - bool bIsUICharStyle; - bool bHasAutoStyle; - OUString aParentName; - uno::Reference xPropSetInfo = xAutoStyle->getPropertySetInfo(); - if (xPropSetInfo->hasPropertyByName("CharStyleName")) + // See if the format redline has an autostyle for old direct formatting: if so, refer to the + // already exported autostyle. + aAny = rPropSet->getPropertyValue(u"RedlineAutoFormat"_ustr); + uno::Reference xAutoStyle; + aAny >>= xAutoStyle; + if (xAutoStyle.is()) { - // Consider parent style when referring to the declared automatic style. - xAutoStyle->getPropertyValue("CharStyleName") >>= aParentName; - } - OUString sStyle = rExport.GetTextParagraphExport()->FindTextStyle( - xAutoStyle, bIsUICharStyle, bHasAutoStyle, /*pAddState=*/nullptr, &aParentName); - if (!sStyle.isEmpty()) - { - rExport.AddAttribute(XML_NAMESPACE_LO_EXT, XML_STYLE_NAME, rExport.EncodeStyleName(sStyle)); + bool bIsUICharStyle; + bool bHasAutoStyle; + OUString aParentName; + uno::Reference xPropSetInfo = xAutoStyle->getPropertySetInfo(); + if (xPropSetInfo->hasPropertyByName("CharStyleName")) + { + // Consider parent style when referring to the declared automatic style. + xAutoStyle->getPropertyValue("CharStyleName") >>= aParentName; + } + OUString sStyle = rExport.GetTextParagraphExport()->FindTextStyle( + xAutoStyle, bIsUICharStyle, bHasAutoStyle, /*pAddState=*/nullptr, &aParentName); + if (!sStyle.isEmpty()) + { + rExport.AddAttribute(XML_NAMESPACE_LO_EXT, XML_STYLE_NAME, rExport.EncodeStyleName(sStyle)); + } } }