diff options
author | Bayram Çiçek <bayram.cicek@collabora.com> | 2025-09-14 01:16:07 +0300 |
---|---|---|
committer | Caolán McNamara <caolan.mcnamara@collabora.com> | 2025-09-15 09:40:36 +0200 |
commit | 2034abc1bb10a69d9bc4d098f4cb82d63e6f73bf (patch) | |
tree | 33d63bd104d347bd5703c2973b4efd97608979f3 /sc | |
parent | 8c5fd04f0bb5bf75192d1c4ddd4d80f608796d7c (diff) |
tdf#167689: sc: export x15 namespace for xl/connections.xml
- add support for x15 namespace.
- add a unittest.
- add support for <x15:connection> and <x15:rangePr> elements.
- support model and sourceName attributes.
<extLst>
<ext xmlns:x15="..." >
<x15:connection id="..." model="...">
<x15:rangePr sourceName="..."/>
</x15:connection>
</ext>
</extLst>
Signed-off-by: Bayram Çiçek <bayram.cicek@collabora.com>
Change-Id: I3b3e380ddd07f251b23333fe9d3959961dd5c19c
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/190924
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolan.mcnamara@collabora.com>
Diffstat (limited to 'sc')
-rw-r--r-- | sc/qa/unit/data/xlsx/tdf167689_x15_namespace.xlsx | bin | 0 -> 174497 bytes | |||
-rw-r--r-- | sc/qa/unit/subsequent_export_test4.cxx | 22 | ||||
-rw-r--r-- | sc/source/filter/excel/excdoc.cxx | 60 | ||||
-rw-r--r-- | sc/source/filter/inc/connectionsbuffer.hxx | 10 | ||||
-rw-r--r-- | sc/source/filter/oox/connectionsbuffer.cxx | 14 | ||||
-rw-r--r-- | sc/source/filter/oox/connectionsfragment.cxx | 17 |
6 files changed, 110 insertions, 13 deletions
diff --git a/sc/qa/unit/data/xlsx/tdf167689_x15_namespace.xlsx b/sc/qa/unit/data/xlsx/tdf167689_x15_namespace.xlsx Binary files differnew file mode 100644 index 000000000000..afd81dd2edb8 --- /dev/null +++ b/sc/qa/unit/data/xlsx/tdf167689_x15_namespace.xlsx diff --git a/sc/qa/unit/subsequent_export_test4.cxx b/sc/qa/unit/subsequent_export_test4.cxx index e7588ad5a41c..c403a68d3a05 100644 --- a/sc/qa/unit/subsequent_export_test4.cxx +++ b/sc/qa/unit/subsequent_export_test4.cxx @@ -2226,6 +2226,28 @@ CPPUNIT_TEST_FIXTURE(ScExportTest4, testTdf166712) assertXPath(pConn, "/x:connections/x:connection/x:olapPr", 0); } +CPPUNIT_TEST_FIXTURE(ScExportTest4, testTdf167689_x15_namespace) +{ + createScDoc("xlsx/tdf167689_x15_namespace.xlsx"); + + save(u"Calc Office Open XML"_ustr); + + xmlDocUniquePtr pConn = parseExport(u"xl/connections.xml"_ustr); + CPPUNIT_ASSERT(pConn); + + // test if <ext> has xmlns:x15 namespace. + assertXPathNSDef(pConn, "/x:connections/x:connection[3]/x:extLst/x:ext", "x15", + "http://schemas.microsoft.com/office/spreadsheetml/2010/11/main"); + + // test id attribute of <x15:connection> + assertXPath(pConn, "/x:connections/x:connection[3]/x:extLst/x:ext/x15:connection", "id", + u"Tabelle1"); + + // test sourceName attribute of <x15:rangePr> + assertXPath(pConn, "/x:connections/x:connection[3]/x:extLst/x:ext/x15:connection/x15:rangePr", + "sourceName", u"_xlcn.LinkedTable_Tabelle1"); +} + CPPUNIT_TEST_FIXTURE(ScExportTest4, testTdf166939) { // Given a document with a column autostyle name equal to "a" (it could be any single-character diff --git a/sc/source/filter/excel/excdoc.cxx b/sc/source/filter/excel/excdoc.cxx index 38ab0d78b831..0d0c6655aaab 100644 --- a/sc/source/filter/excel/excdoc.cxx +++ b/sc/source/filter/excel/excdoc.cxx @@ -1229,21 +1229,55 @@ void ExcDocument::WriteXml( XclExpXmlStream& rStrm ) // put <extLst>, it has no attributes rStrm.GetCurrentStream()->startElement(XML_extLst); - // export uri attribute of <ext> element + // export <ext> with uri attribute and xmlns:x15 namespace. for (auto& uriValue : rModel.mxExtensionList->vExtension) { - // export <ext> with uri attribute. - rStrm.GetCurrentStream()->startElement(XML_ext, XML_uri, uriValue); - - /* - TODO: export child elements of <ext>. We should export "any element in any namespace", which seems challenging. - - <extLst> - <ext> - (Any element in any namespace) - </ext> - </extLst> - */ + rStrm.GetCurrentStream()->startElement(XML_ext, FSNS(XML_xmlns, XML_x15), + rStrm.getNamespaceURL(OOX_NS(x15)), + XML_uri, uriValue); + + /* + Export child elements of <ext> here. + We should export "any element in any namespace" when it is needed. + + <extLst> + <ext> + (Any element in any namespace) + </ext> + </extLst> + */ + + // export <x15:connection> if not empty + aSeqs = rModel.mxExtensionList->maXFifteenConnectionSequenceAny; + if (aSeqs.hasElements()) + { + rtl::Reference<sax_fastparser::FastAttributeList> + pAttrListXFifteenConnection + = sax_fastparser::FastSerializerHelper::createAttrList(); + + addElemensToAttrList(pAttrListXFifteenConnection, aSeqs); + + rStrm.GetCurrentStream()->startElement(FSNS(XML_x15, XML_connection), + pAttrListXFifteenConnection); + + // export <x15:rangePr> if not empty + aSeqs = rModel.mxExtensionList->maXFifteenRangePrSequenceAny; + if (aSeqs.hasElements()) + { + rtl::Reference<sax_fastparser::FastAttributeList> + pAttrListXFifteenRangePr + = sax_fastparser::FastSerializerHelper::createAttrList(); + + addElemensToAttrList(pAttrListXFifteenRangePr, aSeqs); + + // put <x15:rangePr /> + rStrm.GetCurrentStream()->singleElement(FSNS(XML_x15, XML_rangePr), + pAttrListXFifteenRangePr); + } + + // put </x15:connection> + rStrm.GetCurrentStream()->endElement(FSNS(XML_x15, XML_connection)); + } // put </ext> rStrm.GetCurrentStream()->endElement(XML_ext); diff --git a/sc/source/filter/inc/connectionsbuffer.hxx b/sc/source/filter/inc/connectionsbuffer.hxx index 5f3fb3ac734f..b5742c3c2bff 100644 --- a/sc/source/filter/inc/connectionsbuffer.hxx +++ b/sc/source/filter/inc/connectionsbuffer.hxx @@ -100,6 +100,12 @@ struct ExtensionListModel // <ext> has only one attribute: // - uri (A token to identify version and application information for the particular extension) std::vector<OUString> vExtension; // holds uri (URI) attribute of <ext> (Extension) element. + + // <x15:connection> attributes. A child element of <ext>. + css::uno::Sequence<css::uno::Any> maXFifteenConnectionSequenceAny; + // <x15:rangePr> attributes. A child element of <x15:connection>. + css::uno::Sequence<css::uno::Any> maXFifteenRangePrSequenceAny; + }; /** Common properties of an external data connection. */ @@ -177,6 +183,10 @@ public: void importExtensionList(); /** Imports extensions to the standard SpreadsheetML feature set, from the ext element. */ void importExtension(const AttributeList& rAttribs); + /** Imports <x15:connection> element. */ + void importXFifteenConnection(const AttributeList& rAttribs); + /** Imports <x15:rangePr> element. */ + void importXFifteenRangePr(const AttributeList& rAttribs); /** Imports connection settings from the CONNECTION record. */ void importConnection( SequenceInputStream& rStrm ); diff --git a/sc/source/filter/oox/connectionsbuffer.cxx b/sc/source/filter/oox/connectionsbuffer.cxx index 6da344c4ceb3..2a18b1b08028 100644 --- a/sc/source/filter/oox/connectionsbuffer.cxx +++ b/sc/source/filter/oox/connectionsbuffer.cxx @@ -321,6 +321,20 @@ void Connection::importExtension(const AttributeList& rAttribs) maModel.mxExtensionList->vExtension.push_back(sUri); } +void Connection::importXFifteenConnection(const AttributeList& rAttribs) +{ + if (auto xFastAttributeList = rAttribs.getFastAttributeList()) + maModel.mxExtensionList->maXFifteenConnectionSequenceAny + = getSequenceOfAny(xFastAttributeList); +} + +void Connection::importXFifteenRangePr(const AttributeList& rAttribs) +{ + if (auto xFastAttributeList = rAttribs.getFastAttributeList()) + maModel.mxExtensionList->maXFifteenRangePrSequenceAny + = getSequenceOfAny(xFastAttributeList); +} + css::uno::Sequence<css::uno::Any> Connection::getSequenceOfAny( const css::uno::Reference<css::xml::sax::XFastAttributeList>& xFastAttributeList) { diff --git a/sc/source/filter/oox/connectionsfragment.cxx b/sc/source/filter/oox/connectionsfragment.cxx index 68b30587c547..cefc55e43350 100644 --- a/sc/source/filter/oox/connectionsfragment.cxx +++ b/sc/source/filter/oox/connectionsfragment.cxx @@ -115,6 +115,23 @@ ContextHandlerRef ConnectionContext::onCreateContext( sal_Int32 nElement, const return this; } break; + + case XLS_TOKEN(ext): + if (nElement == X15_TOKEN(connection)) + { + // imports <x15:connection> element + mrConnection.importXFifteenConnection(rAttribs); + return this; + } + break; + case X15_TOKEN(connection): + if (nElement == X15_TOKEN(rangePr)) + { + // imports <x15:rangePr> element + mrConnection.importXFifteenRangePr(rAttribs); + return this; + } + break; } return nullptr; } |