/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include #include #include #include using xalanc::Function; using xalanc::Locator; using xalanc::XPathExecutionContext; using xalanc::XalanDOMString; using xalanc::XalanNode; using xalanc::XObjectPtr; using xalanc::MemoryManager; using xalanc::XalanCopyConstruct; // This class defines a function that will return the square root // of its argument. class FunctionSquareRoot : public Function { public: /** * Execute an XPath function object. The function must return a valid * object. Extension functions should override this version of execute(), * rather than one of the other calls designed for a specific number of * arguments. * * @param executionContext executing context * @param context current context node * @param args vector of pointers to XObject arguments * @param locator Locator for the XPath expression that contains the function call * @return pointer to the result XObject */ virtual XObjectPtr execute( XPathExecutionContext& executionContext, XalanNode* context, const XObjectArgVectorType& args, const Locator* locator) const { if (args.size() != 1) { XPathExecutionContext::GetAndReleaseCachedString theGuard(executionContext); generalError(executionContext, context, locator); } assert(args[0].null() == false); using std::sqrt; return executionContext.getXObjectFactory().createNumber(sqrt(args[0]->num(executionContext))); } using Function::execute; /** * Create a copy of the function object. * * @return pointer to the new object */ virtual FunctionSquareRoot* clone(MemoryManager& theManager) const { return XalanCopyConstruct(theManager, *this); } protected: /** * Get the error message to report when * the function is called with the wrong * number of arguments. * * @return function error message */ const XalanDOMString& getError(XalanDOMString& theResult) const { theResult.assign("The square-root() function accepts one argument!"); return theResult; } private: // Not implemented... FunctionSquareRoot& operator=(const FunctionSquareRoot&); bool operator==(const FunctionSquareRoot&) const; }; // This class defines a function that will return the cube // of its argument. class FunctionCube : public Function { public: /** * Execute an XPath function object. The function must return a valid * object. Extension functions should override this version of execute(), * rather than one of the other calls designed for a specific number of * arguments. * * @param executionContext executing context * @param context current context node * @param args vector of pointers to XObject arguments * @param locator Locator for the XPath expression that contains the function call * @return pointer to the result XObject */ virtual XObjectPtr execute( XPathExecutionContext& executionContext, XalanNode* context, const XObjectArgVectorType& args, const Locator* locator) const { if (args.size() != 1) { XPathExecutionContext::GetAndReleaseCachedString theGuard(executionContext); generalError(executionContext, context, locator); } assert(args[0].null() == false); using std::pow; return executionContext.getXObjectFactory().createNumber(pow(args[0]->num(executionContext), 3)); } using Function::execute; /** * Create a copy of the function object. * * @return pointer to the new object */ virtual FunctionCube* clone(MemoryManager& theManager) const { return XalanCopyConstruct(theManager, *this); } protected: /** * Get the error message to report when * the function is called with the wrong * number of arguments. * * @return function error message */ const XalanDOMString& getError(XalanDOMString& theResult) const { theResult.assign("The cube() function accepts one argument!"); return theResult; } private: // Not implemented... FunctionCube& operator=(const FunctionCube&); bool operator==(const FunctionCube&) const; }; // This class defines a function that runs the C function // asctime() using the current system time. class FunctionAsctime : public Function { public: /** * Execute an XPath function object. The function must return a valid * object. Extension functions should override this version of execute(), * rather than one of the other calls designed for a specific number of * arguments. * * @param executionContext executing context * @param context current context node * @param args vector of pointers to XObject arguments * @param locator Locator for the XPath expression that contains the function call * @return pointer to the result XObject */ virtual XObjectPtr execute( XPathExecutionContext& executionContext, XalanNode* context, const XObjectArgVectorType& args, const Locator* locator) const { if (args.empty() == false) { generalError(executionContext, context, locator); } using std::time; using std::time_t; using std::localtime; using std::asctime; using std::strlen; time_t theTime; time(&theTime); char* const theTimeString = asctime(localtime(&theTime)); assert(theTimeString != 0); // The resulting string has a newline character at the end, // so get rid of it. theTimeString[strlen(theTimeString) - 1] = '\0'; return executionContext.getXObjectFactory().createString(XalanDOMString(theTimeString)); } using Function::execute; /** * Create a copy of the function object. * * @return pointer to the new object */ virtual FunctionAsctime* clone(MemoryManager& theManager) const { return XalanCopyConstruct(theManager, *this); } protected: /** * Get the error message to report when * the function is called with the wrong * number of arguments. * * @return function error message */ const XalanDOMString& getError(XalanDOMString& theResult) const { theResult.assign("The asctime() function accepts one argument!"); return theResult; } private: // Not implemented... FunctionAsctime& operator=(const FunctionAsctime&); bool operator==(const FunctionAsctime&) const; }; int main( int argc, char* /* argv */[]) { using std::cerr; using std::endl; int theResult = 0; if (argc != 1) { cerr << "Usage: ExternalFunction" << endl << endl; } else { using xercesc::XMLPlatformUtils; using xercesc::XMLException; using xalanc::XalanTransformer; // Call the static initializer for Xerces. try { XMLPlatformUtils::Initialize(); } catch (const XMLException& toCatch) { cerr << "Error during Xerces initialization. Error code was " << toCatch.getCode() << "." << endl; theResult = -1; } if (theResult == 0) { // Initialize Xalan. XalanTransformer::initialize(); { // Create a XalanTransformer. XalanTransformer theXalanTransformer; // The namespace for our functions... const XalanDOMString theNamespace("http://ExternalFunction.xalan-c++.xml.apache.org"); // Install the functions in the local space. They will only // be installed in this instance, so no other instances // will know about them... theXalanTransformer.installExternalFunction( theNamespace, XalanDOMString("asctime"), FunctionAsctime()); theXalanTransformer.installExternalFunction( theNamespace, XalanDOMString("square-root"), FunctionSquareRoot()); theXalanTransformer.installExternalFunction( theNamespace, XalanDOMString("cube"), FunctionCube()); // Do the transform. theResult = theXalanTransformer.transform("foo.xml", "foo.xsl", "foo.out"); if(theResult != 0) { cerr << "ExternalFunction Error: \n" << theXalanTransformer.getLastError() << endl << endl; } } // Terminate Xalan... XalanTransformer::terminate(); } // Terminate Xerces... XMLPlatformUtils::Terminate(); // Clean up the ICU, if it's integrated... XalanTransformer::ICUCleanUp(); } return theResult; }