diff --git a/include/XPath/impl/xpath_function_holder.hpp b/include/XPath/impl/xpath_function_holder.hpp index 1aecb3c1..2d842434 100644 --- a/include/XPath/impl/xpath_function_holder.hpp +++ b/include/XPath/impl/xpath_function_holder.hpp @@ -26,29 +26,43 @@ public: const string_type& name, const std::vector >& argExprs) const { - if(!string_adaptor::empty(namespace_uri)) - return 0; - return standardFunction(name, argExprs); + return standardFunction(namespace_uri, name, argExprs); } // resolveFuncton + virtual bool hasFunction(const string_type& namespace_uri, + const string_type& name) const + { + return findFunction(namespace_uri, name); + } // hasFunction + static XPathFunction* - standardFunction(const string_type& name, + standardFunction(const string_type& namespace_uri, + const string_type& name, const std::vector >& argExprs) { - for(const NamedFunction* fn = FunctionLookupTable; fn->name != 0; ++fn) - if(name == string_adaptor::construct_from_utf8(fn->name)) - return fn->creator(argExprs); - - return 0; + const NamedFunction* fn = findFunction(namespace_uri, name); + return (fn != 0) ? fn->creator(argExprs) : 0; } // standardFunction private: - typedef XPathFunction* (*CreateFnPtr)(const std::vector >& argExprs); struct NamedFunction { const char* name; CreateFnPtr creator; }; static const NamedFunction FunctionLookupTable[]; + + static const NamedFunction* findFunction(const string_type& namespace_uri, + const string_type& name) + { + if(!string_adaptor::empty(namespace_uri)) + return 0; + + for(const NamedFunction* fn = FunctionLookupTable; fn->name != 0; ++fn) + if(name == string_adaptor::construct_from_utf8(fn->name)) + return fn; + + return 0; + } // findFunction }; // class StandardXPathFunctionResolver template @@ -123,7 +137,7 @@ public: XPathFunction* func = 0; if(string_adaptor::empty(namespace_uri)) - func = StandardXPathFunctionResolver::standardFunction(name, argExprs); + func = StandardXPathFunctionResolver::standardFunction(namespace_uri, name, argExprs); if(func == 0) func = context.functionResolver().resolveFunction(namespace_uri, name, argExprs); diff --git a/include/XPath/impl/xpath_function_resolver.hpp b/include/XPath/impl/xpath_function_resolver.hpp index 57301597..efa73a48 100644 --- a/include/XPath/impl/xpath_function_resolver.hpp +++ b/include/XPath/impl/xpath_function_resolver.hpp @@ -25,6 +25,8 @@ public: resolveFunction(const string_type& namespace_uri, const string_type& name, const std::vector >& argExprs) const = 0; + + virtual bool hasFunction(const string_type& namespace_uri, const string_type& name) const = 0; }; // class FunctionResolver template @@ -56,6 +58,11 @@ public: string_adaptor::append(error, name); throw UndefinedFunctionException(string_adaptor().asStdString(error)); } // resolveVariable + + virtual bool hasFunction(const string_type&, const string_type&) const + { + return false; + } // hasFunction }; // NullFunctionResolver } // namespace XPath diff --git a/include/XSLT/impl/xslt_compilation_context.hpp b/include/XSLT/impl/xslt_compilation_context.hpp index c9a72c4b..f74f27a5 100644 --- a/include/XSLT/impl/xslt_compilation_context.hpp +++ b/include/XSLT/impl/xslt_compilation_context.hpp @@ -195,6 +195,12 @@ private: return 0; } // resolveFunction + virtual bool hasFunction(const std::string& namespace_uri, + const std::string& name) const + { + return false; + } // hasFunction + // NamespaceContext virtual std::string namespaceURI(const std::string& prefix) const { diff --git a/tests/XPath/execute_test.hpp b/tests/XPath/execute_test.hpp index 91ef0e5b..70cf0b4f 100644 --- a/tests/XPath/execute_test.hpp +++ b/tests/XPath/execute_test.hpp @@ -90,6 +90,8 @@ public: return new TestFunction(argExprs); return 0; } // resolveFunction + + virtual bool hasFunction(const string_type&, const string_type& name) const { return false; } }; // class TestFunctionResolver template diff --git a/tests/XPath/match_test.hpp b/tests/XPath/match_test.hpp index 08b71ca2..1f0581f2 100644 --- a/tests/XPath/match_test.hpp +++ b/tests/XPath/match_test.hpp @@ -61,6 +61,8 @@ public: return new TestKeyFunction(argExprs); return 0; } // resolveFunction + + virtual bool hasFunction(const string_type&, const string_type& name) const { return false; } }; // class TestFunctionResolver diff --git a/tests/XPath/parse_test.hpp b/tests/XPath/parse_test.hpp index f00496d3..4c4c56e1 100644 --- a/tests/XPath/parse_test.hpp +++ b/tests/XPath/parse_test.hpp @@ -21,6 +21,8 @@ public: return new Arabica::XPath::impl::TrueFn(argExprs); return 0; } // resolveFunction + + virtual bool hasFunction(const string_type&, const string_type&) const { return false; } }; // class TrueFunctionResolver template