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>
This commit is contained in:
Bayram Çiçek
2025-09-15 09:40:36 +02:00
committed by Caolán McNamara
parent 8c5fd04f0b
commit 2034abc1bb
10 changed files with 115 additions and 11 deletions
+2
View File
@@ -147,6 +147,8 @@ const Sequence< beans::Pair< OUString, sal_Int32 > >& NamespaceIds()
NMSP_p15},
{u"http://schemas.microsoft.com/office/spreadsheetml/2011/1/ac"_ustr,
NMSP_x12ac},
{u"http://schemas.microsoft.com/office/spreadsheetml/2010/11/main"_ustr,
NMSP_x15},
{u"http://schemas.microsoft.com/office/drawing/2012/chart"_ustr,
NMSP_c15},
{u"http://schemas.microsoft.com/office/spreadsheetml/2015/revision2"_ustr,
+1
View File
@@ -62,6 +62,7 @@ inline sal_Int32 getNamespace( sal_Int32 nToken ) { return nToken & NMSP_MASK; }
#define W_TOKEN( token ) OOX_TOKEN( doc, token )
#define LOEXT_TOKEN( token ) OOX_TOKEN( loext, token )
#define M_TOKEN(token) OOX_TOKEN(officeMath, token)
#define X15_TOKEN(token) OOX_TOKEN(x15, token)
#define XR2_TOKEN(token) OOX_TOKEN(xr2, token)
#define XR16_TOKEN(token) OOX_TOKEN(xr16, token)
#define WPC_TOKEN(token) OOX_TOKEN(wpc, token)
+2
View File
@@ -3503,6 +3503,7 @@ miterlimit
moccasin
mod
modId
model
modelId
modern
modified
@@ -4918,6 +4919,7 @@ sourceData
sourceFile
sourceFileName
sourceLinked
sourceName
sourceObject
sourceRef
sourceSheetId
Binary file not shown.
+22
View File
@@ -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
+45 -11
View File
@@ -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);
rStrm.GetCurrentStream()->startElement(XML_ext, FSNS(XML_xmlns, XML_x15),
rStrm.getNamespaceURL(OOX_NS(x15)),
XML_uri, uriValue);
/*
TODO: export child elements of <ext>. We should export "any element in any namespace", which seems challenging.
/*
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>
*/
<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);
@@ -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 );
@@ -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)
{
@@ -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;
}
+2
View File
@@ -480,6 +480,8 @@ void XmlTestTools::registerOOXMLNamespaces(xmlXPathContextPtr& pXmlXpathCtx)
BAD_CAST("http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing"));
xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("x14"),
BAD_CAST("http://schemas.microsoft.com/office/spreadsheetml/2009/9/main"));
xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("x15"),
BAD_CAST("http://schemas.microsoft.com/office/spreadsheetml/2010/11/main"));
xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("xm"),
BAD_CAST("http://schemas.microsoft.com/office/excel/2006/main"));
xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("x12ac"),