From 3b9620e18bdcb91a229e9aefef5192f346030b52 Mon Sep 17 00:00:00 2001 From: Markus Mohrhard Date: Sun, 16 Jun 2013 01:19:22 +0200 Subject: inital work on FILTERXML function Change-Id: Ifb884a52b275df818812f8be6cd7650dcb97849d --- formula/source/core/resource/core_resource.src | 6 ++ include/formula/compiler.hrc | 5 +- include/formula/opcode.hxx | 1 + sc/CppunitTest_sc_ucalc.mk | 7 +- sc/Library_sc.mk | 3 +- sc/qa/unit/ucalc.cxx | 1 + sc/source/core/inc/interpre.hxx | 2 + sc/source/core/tool/interpr4.cxx | 1 + sc/source/core/tool/interpr7.cxx | 93 ++++++++++++++++++++++++++ sc/source/ui/src/scfuncs.src | 30 +++++++++ 10 files changed, 143 insertions(+), 6 deletions(-) diff --git a/formula/source/core/resource/core_resource.src b/formula/source/core/resource/core_resource.src index f4c5f9654e87..e0123f5cf92c 100644 --- a/formula/source/core/resource/core_resource.src +++ b/formula/source/core/resource/core_resource.src @@ -362,6 +362,7 @@ Resource RID_STRLIST_FUNCTION_NAMES_ENGLISH_ODFF String SC_OPCODE_ERROR_NAME { Text = "#NAME?" ; }; String SC_OPCODE_ERROR_NUM { Text = "#NUM!" ; }; String SC_OPCODE_ERROR_NA { Text = "#N/A" ; }; + String SC_OPCODE_FILTERXML { Text = "COM.MICROSOFT.FILTERXML";}; /* END defined ERROR.TYPE() values. */ }; // DO NOT CHANGE! @@ -1995,6 +1996,11 @@ Resource RID_STRLIST_FUNCTION_NAMES Text [ en-US ] = "#N/A" ; }; /* END defined ERROR.TYPE() values. */ + + String SC_OPCODE_FILTERXML + { + Text [ en-US ] = "FILTERXML"; + }; }; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/formula/compiler.hrc b/include/formula/compiler.hrc index e6c6ef3d0df3..fd7453d74995 100644 --- a/include/formula/compiler.hrc +++ b/include/formula/compiler.hrc @@ -407,9 +407,10 @@ #define SC_OPCODE_RIGHTB 409 #define SC_OPCODE_LEFTB 410 #define SC_OPCODE_MIDB 412 -#define SC_OPCODE_LAST_OPCODE_ID 413 /* last OpCode */ +#define SC_OPCODE_FILTERXML 413 +#define SC_OPCODE_LAST_OPCODE_ID 414 /* last OpCode */ -#define SC_OPCODE_STOP_FUNCTION 412 +#define SC_OPCODE_STOP_FUNCTION 415 /*** Internal ***/ #define SC_OPCODE_INTERNAL_BEGIN 9999 diff --git a/include/formula/opcode.hxx b/include/formula/opcode.hxx index 47e2cdc2dff4..5ebaa6bf7818 100644 --- a/include/formula/opcode.hxx +++ b/include/formula/opcode.hxx @@ -401,6 +401,7 @@ enum OpCodeEnum ocHyperLink = SC_OPCODE_HYPERLINK, ocGetPivotData = SC_OPCODE_GET_PIVOT_DATA, ocEuroConvert = SC_OPCODE_EUROCONVERT, + ocFilterXML = SC_OPCODE_FILTERXML, // internal stuff ocInternalBegin = SC_OPCODE_INTERNAL_BEGIN, ocTTT = SC_OPCODE_TTT, diff --git a/sc/CppunitTest_sc_ucalc.mk b/sc/CppunitTest_sc_ucalc.mk index dd1e64de4591..0933cb58cd1e 100644 --- a/sc/CppunitTest_sc_ucalc.mk +++ b/sc/CppunitTest_sc_ucalc.mk @@ -23,13 +23,14 @@ endif $(eval $(call gb_CppunitTest_use_externals,sc_ucalc,\ boost_headers \ - mdds_headers \ - orcus \ - orcus-parser \ icu_headers \ icudata \ icui18n \ icuuc \ + libxml2 \ + mdds_headers \ + orcus \ + orcus-parser \ )) $(eval $(call gb_CppunitTest_use_libraries,sc_ucalc, \ diff --git a/sc/Library_sc.mk b/sc/Library_sc.mk index 189d7e2bab5c..dba982bc9d34 100644 --- a/sc/Library_sc.mk +++ b/sc/Library_sc.mk @@ -37,11 +37,12 @@ $(eval $(call gb_Library_use_sdk_api,sc)) $(eval $(call gb_Library_use_externals,sc,\ boost_headers \ - mdds_headers \ icu_headers \ icudata \ icui18n \ icuuc \ + libxml2 \ + mdds_headers \ )) ifeq ($(ENABLE_TELEPATHY),TRUE) diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx index 686521d3e245..734b1729d92d 100644 --- a/sc/qa/unit/ucalc.cxx +++ b/sc/qa/unit/ucalc.cxx @@ -5365,6 +5365,7 @@ void Test::testFunctionLists() "DECIMAL", "DOLLAR", "EXACT", + "FILTERXML", "FIND", "FIXED", "JIS", diff --git a/sc/source/core/inc/interpre.hxx b/sc/source/core/inc/interpre.hxx index 102b9b017b3b..36109eeac68d 100644 --- a/sc/source/core/inc/interpre.hxx +++ b/sc/source/core/inc/interpre.hxx @@ -793,6 +793,8 @@ void ScRightB(); void ScLeftB(); void ScMidB(); +void ScFilterXML(); + static const double fMaxGammaArgument; double GetGammaContFraction(double fA,double fX); diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx index 60383f0fa5e2..016345a0db49 100644 --- a/sc/source/core/tool/interpr4.cxx +++ b/sc/source/core/tool/interpr4.cxx @@ -4029,6 +4029,7 @@ StackVar ScInterpreter::Interpret() case ocZW : ScZW(); break; case ocZZR : ScZZR(); break; case ocZins : ScZins(); break; + case ocFilterXML : ScFilterXML(); break; case ocZinsZ : ScZinsZ(); break; case ocKapz : ScKapz(); break; case ocKumZinsZ : ScKumZinsZ(); break; diff --git a/sc/source/core/tool/interpr7.cxx b/sc/source/core/tool/interpr7.cxx index 1ea0f3bf0759..52b362063237 100644 --- a/sc/source/core/tool/interpr7.cxx +++ b/sc/source/core/tool/interpr7.cxx @@ -11,7 +11,100 @@ */ #include "interpre.hxx" +#include "libxml/xpath.h" + +#include // TODO: Add new methods for ScInterpreter here. +void ScInterpreter::ScFilterXML() +{ + sal_uInt8 nParamCount = GetByte(); + if (MustHaveParamCount( nParamCount, 2 ) ) + { + OUString aXPathExpression = GetString(); + OUString aString = GetString(); + + const char* pXPathExpr = OUStringToOString( aXPathExpression, RTL_TEXTENCODING_UTF8 ).getStr(); + const char* pXML = OUStringToOString( aString, RTL_TEXTENCODING_UTF8 ).getStr(); + + boost::shared_ptr pContext( + xmlNewParserCtxt(), xmlFreeParserCtxt ); + + boost::shared_ptr pDoc( xmlParseMemory( pXML, aString.getLength() ), + xmlFreeDoc ); + + + boost::shared_ptr pXPathCtx( xmlXPathNewContext(pDoc.get()), + xmlXPathFreeContext ); + + boost::shared_ptr pXPathObj( xmlXPathEvalExpression(BAD_CAST(pXPathExpr), pXPathCtx.get()), + xmlXPathFreeObject ); + + switch(pXPathObj->type) + { + case XPATH_UNDEFINED: + break; + case XPATH_NODESET: + { + xmlNodeSetPtr pNodeSet = pXPathObj->nodesetval; + size_t nSize = pNodeSet->nodeNr; + if( nSize >= 1 ) + { + if(pNodeSet->nodeTab[0]->type == XML_NAMESPACE_DECL) + { + xmlNsPtr ns = (xmlNsPtr)pNodeSet->nodeTab[0]; + xmlNodePtr cur = (xmlNodePtr)ns->next; + boost::shared_ptr pChar2(xmlNodeGetContent(cur), xmlFree); + OUString aResult = OUString::createFromAscii((char*)pChar2.get()); + PushString(aResult); + } + else if(pNodeSet->nodeTab[0]->type == XML_ELEMENT_NODE) + { + xmlNodePtr cur = pNodeSet->nodeTab[0]; + boost::shared_ptr pChar2(xmlNodeGetContent(cur), xmlFree); + OUString aResult = OUString::createFromAscii((char*)pChar2.get()); + PushString(aResult); + } + else + { + xmlNodePtr cur = pNodeSet->nodeTab[0]; + boost::shared_ptr pChar2(xmlNodeGetContent(cur), xmlFree); + OUString aResult = OUString::createFromAscii((char*)pChar2.get()); + PushString(aResult); + } + } + } + break; + case XPATH_BOOLEAN: + assert(false); + break; + case XPATH_NUMBER: + assert(false); + break; + case XPATH_STRING: + assert(false); + break; + case XPATH_POINT: + assert(false); + break; + case XPATH_RANGE: + assert(false); + break; + case XPATH_LOCATIONSET: + assert(false); + break; + case XPATH_USERS: + assert(false); + break; + case XPATH_XSLT_TREE: + assert(false); + break; + + } + + } + +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/src/scfuncs.src b/sc/source/ui/src/scfuncs.src index 87b9cdd70f8f..702abcde07be 100644 --- a/sc/source/ui/src/scfuncs.src +++ b/sc/source/ui/src/scfuncs.src @@ -9730,6 +9730,36 @@ Resource RID_SC_FUNCTION_DESCRIPTIONS2 String 7 // Description of Parameter 3 { Text [ en-US ] = "The number of characters for the text." ; + } + Resource SC_OPCODE_FILTERXML + { + ExtraData = + { + 0; + ID_FUNCTION_GRP_TEXT; + U2S( HID_FUNC_BITLSHIFT ); + 2; 0; 0; + 0; + } + String 1 // Description + { + Text [ en-US ] = "Apply an XPath expression to an XML document"; + }; + String 2 // Name of Parameter 1 + { + Text [ en-US ] = "XML Document"; + }; + String 3 // Description of Parameter 1 + { + Text [ en-US ] = "String containing a valid XML stream"; + }; + String 4 // Name of parameter 2 + { + Text [ en-US ] = "XPath expression"; + }; + String 5 // Description of Parameter 2 + { + Text [ en-US ] = "String containing a valid XPath expression"; }; }; }; -- cgit