From 0cf6f241e40b8be3c9d809c528b367df32f3f2ee Mon Sep 17 00:00:00 2001 From: Miklos Vajna Date: Mon, 24 Feb 2014 09:03:22 +0100 Subject: [PATCH] abi#11739 DOCX export: fix validation error, wrong order of some elements Change-Id: Ic1c0174718ba6853fcc8795324a99b2a332b865e --- sw/qa/extras/ooxmlexport/data/abi11739.docx | Bin 0 -> 11635 bytes sw/qa/extras/ooxmlexport/ooxmlexport.cxx | 36 ++++++++++++++++++ sw/source/filter/ww8/docxattributeoutput.cxx | 24 ++++++------ sw/source/filter/ww8/docxtablestyleexport.cxx | 4 +- 4 files changed, 50 insertions(+), 14 deletions(-) create mode 100755 sw/qa/extras/ooxmlexport/data/abi11739.docx diff --git a/sw/qa/extras/ooxmlexport/data/abi11739.docx b/sw/qa/extras/ooxmlexport/data/abi11739.docx new file mode 100755 index 0000000000000000000000000000000000000000..8eb6999da28d160206fdbca2f6f25075caed943f GIT binary patch literal 11635 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 M*k}f5zyJ4t0P3A+X#fBK literal 0 HcmV?d00001 diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport.cxx index 850c11141f42..c1d81ca39c24 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport.cxx @@ -96,6 +96,12 @@ protected: */ void assertXPathChildren(xmlDocPtr pXmlDoc, const OString& rXPath, int nNumberOfChildNodes); + /** + * Get the position of the child named rName of the parent node specified by rXPath. + * Useful for checking relative order of elements. + */ + int getXPathPosition(xmlDocPtr pXmlDoc, const OString& rXPath, const OUString& rName); + /** * Same as the assertXPath(), but don't assert: return the string instead. */ @@ -189,6 +195,23 @@ void Test::assertXPathChildren(xmlDocPtr pXmlDoc, const OString& rXPath, int nNu nNumberOfChildNodes, (int)xmlChildElementCount(pXmlNode)); } +int Test::getXPathPosition(xmlDocPtr pXmlDoc, const OString& rXPath, const OUString& rChildName) +{ + xmlNodeSetPtr pXmlNodes = getXPathNode(pXmlDoc, rXPath); + CPPUNIT_ASSERT_EQUAL_MESSAGE(OString("XPath '" + rXPath + "' number of nodes is incorrect").getStr(), + 1, + xmlXPathNodeSetGetLength(pXmlNodes)); + xmlNodePtr pXmlNode = pXmlNodes->nodeTab[0]; + int nRet = 0; + for (xmlNodePtr pChild = pXmlNode->children; pChild; pChild = pChild->next) + { + if (OUString::createFromAscii((const char*)pChild->name) == rChildName) + break; + ++nRet; + } + return nRet; +} + OUString Test::getXPath(xmlDocPtr pXmlDoc, const OString& rXPath, const OString& rAttribute) { xmlNodeSetPtr pXmlNodes = getXPathNode(pXmlDoc, rXPath); @@ -3431,6 +3454,19 @@ DECLARE_OOXMLEXPORT_TEST(testW14TextEffects, "TextEffects.docx") CPPUNIT_ASSERT(getXPath(pXmlDoc, "/w:document/w:body/w:p/w:r[2]/w:rPr/w14:glow", "rad").match("228600")); } +DECLARE_OOXMLEXPORT_TEST(testAbi11739, "abi11739.docx") +{ + // Validation test: order of elements were wrong. + xmlDocPtr pXmlDoc = parseExport("word/styles.xml"); + if (!pXmlDoc) + return; + // Order was: uiPriority, link, basedOn. + CPPUNIT_ASSERT(getXPathPosition(pXmlDoc, "/w:styles/w:style[3]", "basedOn") < getXPathPosition(pXmlDoc, "/w:styles/w:style[3]", "link")); + CPPUNIT_ASSERT(getXPathPosition(pXmlDoc, "/w:styles/w:style[3]", "link") < getXPathPosition(pXmlDoc, "/w:styles/w:style[3]", "uiPriority")); + // Order was: qFormat, unhideWhenUsed. + CPPUNIT_ASSERT(getXPathPosition(pXmlDoc, "/w:styles/w:style[11]", "unhideWhenUsed") < getXPathPosition(pXmlDoc, "/w:styles/w:style[11]", "qFormat")); +} + #endif CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx index d37fe60a4ec3..9dd8cd52706b 100644 --- a/sw/source/filter/ww8/docxattributeoutput.cxx +++ b/sw/source/filter/ww8/docxattributeoutput.cxx @@ -3739,7 +3739,18 @@ void DocxAttributeOutput::StartStyle( const OUString& rName, StyleType eType, FSNS( XML_w, XML_val ), OUStringToOString( OUString( rName ), RTL_TEXTENCODING_UTF8 ).getStr(), FSEND ); - // Output properties from grab-bag. + if ( nBase != 0x0FFF && eType != STYLE_TYPE_LIST) + { + m_pSerializer->singleElementNS( XML_w, XML_basedOn, + FSNS( XML_w, XML_val ), m_rExport.pStyles->GetStyleId(nBase).getStr(), + FSEND ); + } + + if (!aLink.isEmpty()) + m_pSerializer->singleElementNS(XML_w, XML_link, + FSNS(XML_w, XML_val), OUStringToOString(aLink, RTL_TEXTENCODING_UTF8).getStr(), + FSEND); + if (!aUiPriority.isEmpty()) m_pSerializer->singleElementNS(XML_w, XML_uiPriority, FSNS(XML_w, XML_val), OUStringToOString(aUiPriority, RTL_TEXTENCODING_UTF8).getStr(), @@ -3750,10 +3761,6 @@ void DocxAttributeOutput::StartStyle( const OUString& rName, StyleType eType, m_pSerializer->singleElementNS(XML_w, XML_semiHidden, FSEND); if (bUnhideWhenUsed) m_pSerializer->singleElementNS(XML_w, XML_unhideWhenUsed, FSEND); - if (!aLink.isEmpty()) - m_pSerializer->singleElementNS(XML_w, XML_link, - FSNS(XML_w, XML_val), OUStringToOString(aLink, RTL_TEXTENCODING_UTF8).getStr(), - FSEND); if (bLocked) m_pSerializer->singleElementNS(XML_w, XML_locked, FSEND); if (!aRsid.isEmpty()) @@ -3761,13 +3768,6 @@ void DocxAttributeOutput::StartStyle( const OUString& rName, StyleType eType, FSNS(XML_w, XML_val), OUStringToOString(aRsid, RTL_TEXTENCODING_UTF8).getStr(), FSEND); - if ( nBase != 0x0FFF && eType != STYLE_TYPE_LIST) - { - m_pSerializer->singleElementNS( XML_w, XML_basedOn, - FSNS( XML_w, XML_val ), m_rExport.pStyles->GetStyleId(nBase).getStr(), - FSEND ); - } - if ( nNext != nId && eType != STYLE_TYPE_LIST) { m_pSerializer->singleElementNS( XML_w, XML_next, diff --git a/sw/source/filter/ww8/docxtablestyleexport.cxx b/sw/source/filter/ww8/docxtablestyleexport.cxx index dc0297a7eec8..5cd154c354de 100644 --- a/sw/source/filter/ww8/docxtablestyleexport.cxx +++ b/sw/source/filter/ww8/docxtablestyleexport.cxx @@ -618,12 +618,12 @@ void DocxTableStyleExport::Impl::TableStyle(uno::Sequence& m_pSerializer->singleElementNS(XML_w, XML_uiPriority, FSNS(XML_w, XML_val), OUStringToOString(aUiPriority, RTL_TEXTENCODING_UTF8).getStr(), FSEND); - if (bQFormat) - m_pSerializer->singleElementNS(XML_w, XML_qFormat, FSEND); if (bSemiHidden) m_pSerializer->singleElementNS(XML_w, XML_semiHidden, FSEND); if (bUnhideWhenUsed) m_pSerializer->singleElementNS(XML_w, XML_unhideWhenUsed, FSEND); + if (bQFormat) + m_pSerializer->singleElementNS(XML_w, XML_qFormat, FSEND); if (!aRsid.isEmpty()) m_pSerializer->singleElementNS(XML_w, XML_rsid, FSNS(XML_w, XML_val), OUStringToOString(aRsid, RTL_TEXTENCODING_UTF8).getStr(),