summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEike Rathke <erack@redhat.com>2016-08-17 15:58:42 +0200
committerEike Rathke <erack@redhat.com>2016-08-17 16:01:47 +0200
commit7d733e16513a1b9413303d60feb03c5a0de941fc (patch)
treee5ef06b8dfbd4d4943459f2c616d1f449ac20361
parent190f0685c866b6232564c9d207456d3292d7a551 (diff)
Resolves: tdf#88257 handle FILTERXML array/matrix context
... in which subsequent node elements are to be stored in the result matrix. Change-Id: Ia980a99a2b9ffba0e651f5d4c2420c8acfb80615
-rw-r--r--sc/source/core/tool/interpr7.cxx119
1 files changed, 101 insertions, 18 deletions
diff --git a/sc/source/core/tool/interpr7.cxx b/sc/source/core/tool/interpr7.cxx
index 7b2624b18e27..2d48c6b74ad0 100644
--- a/sc/source/core/tool/interpr7.cxx
+++ b/sc/source/core/tool/interpr7.cxx
@@ -8,6 +8,9 @@
*/
#include "interpre.hxx"
+#include "jumpmatrix.hxx"
+#include "formulacell.hxx"
+#include "scmatrix.hxx"
#include <rtl/strbuf.hxx>
#include <formula/errorcodes.hxx>
#include <svtools/miscopt.hxx>
@@ -33,6 +36,54 @@ void ScInterpreter::ScFilterXML()
sal_uInt8 nParamCount = GetByte();
if (MustHaveParamCount( nParamCount, 2 ) )
{
+ SCSIZE nMatCols = 1, nMatRows = 1, nNode = 0;
+ const ScMatrix* pPathMatrix = nullptr;
+ // In array/matrix context node elements' results are to be
+ // subsequently stored. Check this before obtaining any argument from
+ // the stack so the stack type can be used.
+ if (pJumpMatrix || bMatrixFormula || pCur->IsInForceArray())
+ {
+ if (pJumpMatrix)
+ {
+ // Single result, GetString() will retrieve the corresponding
+ // argument and JumpMatrix() will store it at the proper
+ // position. Note that nMatCols and nMatRows are still 1.
+ SCSIZE nCurCol = 0, nCurRow = 0;
+ pJumpMatrix->GetPos( nCurCol, nCurRow);
+ nNode = nCurRow;
+ }
+ else if (bMatrixFormula)
+ {
+ // If there is no formula cell then continue with a single
+ // result.
+ if (pMyFormulaCell)
+ {
+ SCCOL nCols;
+ SCROW nRows;
+ pMyFormulaCell->GetMatColsRows( nCols, nRows);
+ nMatCols = nCols;
+ nMatRows = nRows;
+ }
+ }
+ else if (GetStackType() == formula::svMatrix)
+ {
+ pPathMatrix = pStack[sp-1]->GetMatrix();
+ if (!pPathMatrix)
+ {
+ PushIllegalParameter();
+ return;
+ }
+ pPathMatrix->GetDimensions( nMatCols, nMatRows);
+
+ /* TODO: it is unclear what should happen if there are
+ * different path arguments in matrix elements. We may have to
+ * evaluate each, and for repeated identical paths use
+ * subsequent nodes. As is, the path at 0,0 is used as obtained
+ * by GetString(). */
+
+ }
+ }
+
OUString aXPathExpression = GetString().getString();
OUString aString = GetString().getString();
if(aString.isEmpty() || aXPathExpression.isEmpty())
@@ -70,8 +121,6 @@ void ScInterpreter::ScFilterXML()
return;
}
- rtl::OUString aResult;
-
switch(pXPathObj->type)
{
case XPATH_UNDEFINED:
@@ -85,30 +134,64 @@ void ScInterpreter::ScFilterXML()
return;
}
- size_t nSize = pNodeSet->nodeNr;
- if( nSize >= 1 )
+ const size_t nSize = pNodeSet->nodeNr;
+ if (nNode >= nSize)
+ {
+ // For pJumpMatrix
+ PushError( formula::NOTAVAILABLE);
+ return;
+ }
+
+ /* TODO: for nMatCols>1 IF stack type is svMatrix, i.e.
+ * pPathMatrix!=nullptr, we may want a result matrix with
+ * nMatCols columns as well, but clarify first how to treat
+ * differing path elements. */
+
+ ScMatrixRef xResMat;
+ if (nMatRows > 1)
{
- if(pNodeSet->nodeTab[0]->type == XML_NAMESPACE_DECL)
+ xResMat = GetNewMat( 1, nMatRows, true);
+ if (!xResMat)
{
- xmlNsPtr ns = reinterpret_cast<xmlNsPtr>(pNodeSet->nodeTab[0]);
- xmlNodePtr cur = reinterpret_cast<xmlNodePtr>(ns->next);
- std::shared_ptr<xmlChar> pChar2(xmlNodeGetContent(cur), xmlFree);
- aResult = OStringToOUString(OString(reinterpret_cast<char*>(pChar2.get())), RTL_TEXTENCODING_UTF8);
+ PushError( formula::errCodeOverflow);
+ return;
+ }
+ }
+
+ for ( ; nNode < nMatRows; ++nNode)
+ {
+ if( nSize > nNode )
+ {
+ rtl::OUString aResult;
+ if(pNodeSet->nodeTab[nNode]->type == XML_NAMESPACE_DECL)
+ {
+ xmlNsPtr ns = reinterpret_cast<xmlNsPtr>(pNodeSet->nodeTab[nNode]);
+ xmlNodePtr cur = reinterpret_cast<xmlNodePtr>(ns->next);
+ std::shared_ptr<xmlChar> pChar2(xmlNodeGetContent(cur), xmlFree);
+ aResult = OStringToOUString(OString(reinterpret_cast<char*>(pChar2.get())), RTL_TEXTENCODING_UTF8);
+ }
+ else
+ {
+ xmlNodePtr cur = pNodeSet->nodeTab[nNode];
+ std::shared_ptr<xmlChar> pChar2(xmlNodeGetContent(cur), xmlFree);
+ aResult = OStringToOUString(OString(reinterpret_cast<char*>(pChar2.get())), RTL_TEXTENCODING_UTF8);
+ }
+ if (xResMat)
+ xResMat->PutString( mrStrPool.intern( aResult), 0, nNode);
+ else
+ PushString(aResult);
}
else
{
- xmlNodePtr cur = pNodeSet->nodeTab[0];
- std::shared_ptr<xmlChar> pChar2(xmlNodeGetContent(cur), xmlFree);
- aResult = OStringToOUString(OString(reinterpret_cast<char*>(pChar2.get())), RTL_TEXTENCODING_UTF8);
+ if (xResMat)
+ xResMat->PutError( formula::NOTAVAILABLE, 0, nNode);
+ else
+ PushError( formula::NOTAVAILABLE );
}
}
- else
- {
- PushError( formula::errNoValue );
- return;
- }
+ if (xResMat)
+ PushMatrix( xResMat);
}
- PushString(aResult);
break;
case XPATH_BOOLEAN:
{