diff --git a/xmloff/CppunitTest_xmloff_text.mk b/xmloff/CppunitTest_xmloff_text.mk index 14640cf8d7d7..ad6711a89101 100644 --- a/xmloff/CppunitTest_xmloff_text.mk +++ b/xmloff/CppunitTest_xmloff_text.mk @@ -13,6 +13,7 @@ $(eval $(call gb_CppunitTest_CppunitTest,xmloff_text)) $(eval $(call gb_CppunitTest_use_externals,xmloff_text,\ boost_headers \ + libxml2 \ )) $(eval $(call gb_CppunitTest_add_exception_objects,xmloff_text, \ diff --git a/xmloff/qa/unit/data/para-style-list-level.fodt b/xmloff/qa/unit/data/para-style-list-level.fodt index 88f96e349ee2..3cf0fd6f5315 100644 --- a/xmloff/qa/unit/data/para-style-list-level.fodt +++ b/xmloff/qa/unit/data/para-style-list-level.fodt @@ -1,7 +1,7 @@ - + diff --git a/xmloff/qa/unit/text.cxx b/xmloff/qa/unit/text.cxx index 79acb8cb08bf..78ebaf75e1bc 100644 --- a/xmloff/qa/unit/text.cxx +++ b/xmloff/qa/unit/text.cxx @@ -9,6 +9,7 @@ #include #include +#include #include #include @@ -16,18 +17,22 @@ #include #include #include +#include #include #include #include #include +#include using namespace ::com::sun::star; constexpr OUStringLiteral DATA_DIRECTORY = u"/xmloff/qa/unit/data/"; /// Covers xmloff/source/text/ fixes. -class XmloffStyleTest : public test::BootstrapFixture, public unotest::MacrosTest +class XmloffStyleTest : public test::BootstrapFixture, + public unotest::MacrosTest, + public XmlTestTools { private: uno::Reference mxComponent; @@ -35,9 +40,15 @@ private: public: void setUp() override; void tearDown() override; + void registerNamespaces(xmlXPathContextPtr& pXmlXpathCtx) override; uno::Reference& getComponent() { return mxComponent; } }; +void XmloffStyleTest::registerNamespaces(xmlXPathContextPtr& pXmlXpathCtx) +{ + XmlTestTools::registerODFNamespaces(pXmlXpathCtx); +} + void XmloffStyleTest::setUp() { test::BootstrapFixture::setUp(); @@ -181,6 +192,32 @@ CPPUNIT_TEST_FIXTURE(XmloffStyleTest, testParaStyleListLevel) sal_Int16 nNumberingLevel{}; CPPUNIT_ASSERT(xStyle->getPropertyValue("NumberingLevel") >>= nNumberingLevel); CPPUNIT_ASSERT_EQUAL(static_cast(2), nNumberingLevel); + + // Test the export as well: + + // Given a doc model that has a para style with NumberingLevel=2: + uno::Reference xStorable(getComponent(), uno::UNO_QUERY); + + // When exporting that to ODT: + uno::Sequence aStoreProps = comphelper::InitPropertySequence({ + { "FilterName", uno::makeAny(OUString("writer8")) }, + }); + utl::TempFile aTempFile; + aTempFile.EnableKillingFile(); + xStorable->storeToURL(aTempFile.GetURL(), aStoreProps); + + // Then make sure we save the style's numbering level: + uno::Reference xNameAccess + = packages::zip::ZipFileAccess::createWithURL(mxComponentContext, aTempFile.GetURL()); + uno::Reference xInputStream(xNameAccess->getByName("styles.xml"), + uno::UNO_QUERY); + std::unique_ptr pStream(utl::UcbStreamHelper::CreateStream(xInputStream, true)); + xmlDocUniquePtr pXmlDoc = parseXmlStream(pStream.get()); + // Without the accompanying fix in place, this failed with: + // - XPath '/office:document-styles/office:styles/style:style[@style:name='mystyle']' no attribute 'list-level' exist + // i.e. a custom NumberingLevel was lost on save. + assertXPath(pXmlDoc, "/office:document-styles/office:styles/style:style[@style:name='mystyle']", + "list-level", "2"); } CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/xmloff/source/style/styleexp.cxx b/xmloff/source/style/styleexp.cxx index 159d5b50e02e..2c628ffbda4d 100644 --- a/xmloff/source/style/styleexp.cxx +++ b/xmloff/source/style/styleexp.cxx @@ -41,6 +41,7 @@ #include #include #include +#include using namespace ::com::sun::star; using namespace ::com::sun::star::uno; @@ -122,6 +123,34 @@ void XMLStyleExport::exportStyleContent( const Reference< XStyle >& rStyle ) } } +namespace +{ +/// Writes for Writer paragraph styles. +void ExportStyleListlevel(const uno::Reference& xPropSetInfo, + const uno::Reference& xPropState, + const uno::Reference& xPropSet, SvXMLExport& rExport) +{ + if (!xPropSetInfo->hasPropertyByName("NumberingLevel")) + { + SAL_WARN("xmloff", "ExportStyleListlevel: no NumberingLevel for a Writer paragraph style"); + return; + } + + if (xPropState->getPropertyState("NumberingLevel") != beans::PropertyState_DIRECT_VALUE) + { + return; + } + + sal_Int16 nNumberingLevel{}; + if (!(xPropSet->getPropertyValue("NumberingLevel") >>= nNumberingLevel)) + { + return; + } + + rExport.AddAttribute(XML_NAMESPACE_STYLE, XML_LIST_LEVEL, OUString::number(nNumberingLevel)); +} +} + bool XMLStyleExport::exportStyle( const Reference< XStyle >& rStyle, const OUString& rXMLFamily, @@ -302,6 +331,8 @@ bool XMLStyleExport::exportStyle( GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_LIST_STYLE_NAME, GetExport().EncodeStyleName( sListName ) ); + + ExportStyleListlevel(xPropSetInfo, xPropState, xPropSet, GetExport()); } } }