<?xml version="1.0" encoding="UTF-8" standalone="no"?> | |
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> | |
<html> | |
<head> | |
<title>ASF: Xalan-C++ Extension Functions</title> | |
<meta http-equiv="content-type" content="text/html; charset=UTF-8" /> | |
<meta http-equiv="Content-Style-Type" content="text/css" /> | |
<link rel="stylesheet" type="text/css" href="resources/apache-xalan.css" /> | |
</head> | |
<!-- | |
* 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. | |
--> | |
<body> | |
<div id="title"> | |
<table class="HdrTitle"> | |
<tbody> | |
<tr> | |
<th rowspan="2"> | |
<a href="../index.html"> | |
<img alt="Trademark Logo" src="resources/XalanC-Logo-tm.png" width="190" height="90" /> | |
</a> | |
</th> | |
<th text-align="center" width="75%"> | |
<a href="index.html">Xalan-C/C++ Version 1.11</a> | |
</th> | |
</tr> | |
<tr> | |
<td valign="middle">Xalan-C++ Extension Functions</td> | |
</tr> | |
</tbody> | |
</table> | |
<table class="HdrButtons" align="center" border="1"> | |
<tbody> | |
<tr> | |
<td> | |
<a href="http://www.apache.org">Apache Foundation</a> | |
</td> | |
<td> | |
<a href="http://xalan.apache.org">Xalan Project</a> | |
</td> | |
<td> | |
<a href="http://xerces.apache.org">Xerces Project</a> | |
</td> | |
<td> | |
<a href="http://www.w3.org/TR">Web Consortium</a> | |
</td> | |
<td> | |
<a href="http://www.oasis-open.org/standards">Oasis Open</a> | |
</td> | |
</tr> | |
</tbody> | |
</table> | |
</div> | |
<div id="navLeft"> | |
<ul> | |
<li> | |
<a href="resources.html">Resources</a> | |
<br /> | |
</li> | |
<li> | |
<a href="../index.html">Home</a> | |
</li></ul><hr /><ul> | |
<li> | |
<a href="index.html">Xalan-C++ 1.11</a> | |
</li> | |
<li> | |
<a href="whatsnew.html">What's New</a> | |
</li> | |
<li> | |
<a href="license.html">Licenses</a> | |
</li></ul><hr /><ul> | |
<li> | |
<a href="overview.html">Overview</a> | |
</li> | |
<li> | |
<a href="charter.html">Charter</a> | |
</li></ul><hr /><ul> | |
<li> | |
<a href="download.html">Download</a> | |
</li> | |
<li> | |
<a href="buildlibs.html">Build Libraries</a> | |
</li> | |
<li> | |
<a href="install.html">Installation</a> | |
</li> | |
<li> | |
<a href="builddocs.html">Build Documents</a> | |
</li></ul><hr /><ul> | |
<li> | |
<a href="samples.html">Sample Apps</a> | |
</li> | |
<li> | |
<a href="commandline.html">Command Line</a> | |
</li> | |
<li> | |
<a href="usagepatterns.html">Usage Patterns</a> | |
</li></ul><hr /><ul> | |
<li> | |
<a href="programming.html">Programming</a> | |
</li> | |
<li>Extensions<br /> | |
</li> | |
<li> | |
<a href="extensionslib.html">Extensions Library</a> | |
</li> | |
<li> | |
<a href="apiDocs/index.html">API Reference</a> | |
</li></ul><hr /><ul> | |
<li> | |
<a href="faq.html">Xalan-C FAQs</a> | |
</li></ul><hr /><ul> | |
<li> | |
<a href="whatsnew.html#bugs">Bugs</a> | |
</li> | |
<li> | |
<a href="http://xalan.apache.org/old/xalan-j/test/run.html#how-to-run-c">Testing</a> | |
</li> | |
<li> | |
<a href="secureweb.html">Web Security</a> | |
</li> | |
</ul> | |
</div> | |
<div id="content"> | |
<h2>Xalan-C++ Extension Functions</h2> | |
<ul> | |
<li> | |
<a href="#intro">Introduction</a> | |
</li> | |
<li> | |
<a href="#implement">Implementing an extension function</a> | |
</li> | |
<li> | |
<a href="#install">Installing an extension function</a> | |
</li> | |
<li> | |
<a href="#use">Using an extension function</a> | |
</li> | |
</ul> | |
<a name="intro"></a> | |
<p align="right" size="2"> | |
<a href="#content">(top)</a> | |
</p> | |
<h3>Introduction</h3> | |
<p>At times, you may want to call your own custom C functions from a stylesheet. For these situations, Xalan-C++ supports the | |
creation and use of extension functions. Xalan-C++ also provides a <a href="extensionslib.html">library of extension functions | |
</a> for your use.</p> | |
<p>You can think of extension functions as extending the core library of functions that XPath provides. Like the | |
XPath functions, an extension function returns an XObject, which may contain a value of any of the five XSLT | |
data types: node-set, result-tree-fragment, string, boolean, or number.</p> | |
<p>You can send arguments to an extension function in the form of XPath expressions, literals (for string, boolean, and number), | |
the values returned by other functions, and XSL variables or parameters set to any of the preceding.</p> | |
<p>For an example that implements, installs, and uses three extension functions, see the | |
<a href="samples.html#externalfunctions">External Functions</a> sample.</p> | |
<table class="note"> | |
<tr> | |
<td class="noteImg"> | |
<img src="resources/note.gif" alt="note" /> | |
</td> | |
<td class="noteTxt">Xalan-C++ does not support extension elements.</td> | |
</tr> | |
</table> | |
<a name="implement"></a> | |
<p align="right" size="2"> | |
<a href="#content">(top)</a> | |
</p> | |
<h3>Implementing an extension function</h3> | |
<p>Like the standard XPath functions, the functions you create derive from the Function base class. Set up your | |
extension function class as follows:</p> | |
<ol> | |
<li>The body of a function is the execute() method. Use the appropriate XObjectFactory method -- createNumber() | |
in the example below -- to create an XObject corresponding to the XSLT data type the function returns.<br /> | |
<br /> | |
</li> | |
<li>Implement a clone() method to enable Xalan to create and maintain a copy of the extension | |
function.<br /> | |
<br /> | |
</li> | |
<li>(Optional) As Xalan does for the XPath functions, you may want to prevent the compiler from generating | |
an assignment or equality operator for this function.</li> | |
</ol> | |
<p>These features all appear in the following example.</p> | |
<blockquote class="source"> | |
<pre> | |
// Base header file. Must be first. | |
#include <xalanc/Include/PlatformDefinitions.hpp> | |
#include <cmath> | |
#include <ctime> | |
#include <xercesc/util/PlatformUtils.hpp> | |
#include <xalanc/XalanTransformer/XalanTransformer.hpp> | |
#include <xalanc/XPath/XObjectFactory.hpp> | |
XALAN_CPP_NAMESPACE_USE | |
// 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 | |
* XObject. | |
* | |
* @param executionContext executing context | |
* @param context current context node | |
* @param opPos current op position | |
* @param args vector of pointers to XObject arguments | |
* @return pointer to the result XObject | |
*/ | |
virtual XObjectPtr | |
execute( | |
XPathExecutionContext& executionContext, | |
XalanNode* /* context */, | |
const XObjectPtr arg, | |
const Locator* /* locator */) const | |
{ | |
if (args.size() != 1) | |
{ | |
executionContext.error("The square-root() function takes one argument!", | |
context); | |
} | |
assert(args[0] != 0); | |
// Use the XObjectFactory createNumber() method to create an XObject | |
// corresponding to the XSLT number data type. | |
return executionContext.getXObjectFactory().createNumber( | |
sqrt(args[0]->num())); | |
} | |
/** | |
* Implement clone() so Xalan can copy the square-root function into | |
* its own function table. | |
* | |
* @return pointer to the new object | |
*/ | |
// For compilers that do not support covariant return types, | |
// clone() must be declared to return the base type. | |
#if defined(XALAN_NO_COVARIANT_RETURN_TYPE) | |
virtual Function* | |
#else | |
virtual FunctionSquareRoot* | |
#endif | |
clone() const | |
{ | |
return new FunctionSquareRoot(*this); | |
} | |
private: | |
// The assignment and equality operators are not implemented... | |
FunctionSquareRoot& | |
operator=(const FunctionSquareRoot&); | |
bool | |
operator==(const FunctionSquareRoot&) const; | |
} | |
</pre> | |
</blockquote> | |
<a name="install"></a> | |
<p align="right" size="2"> | |
<a href="#content">(top)</a> | |
</p> | |
<h3>Installing an extension function</h3> | |
<p> | |
<a href="apiDocs/classXalanTransformer.html">XalanTransformer</a> provides methods for installing and uninstalling external functions:</p> | |
<ul> | |
<li>installExternalFunction() makes the function available in the current instance of XalanTransformer. Use uninstallExternalFunction() to remove the function.<br /> | |
<br /> | |
</li> | |
<li>installExternalFunctionGlobal() makes the function available globally. Use uninstallExternalFunctionGlobal() to remove the function. The global install and uninstall operations are not thread-safe. However, all global functions should be thread-safe, because multiple threads could call a particular function instance at the same time.</li> | |
</ul> | |
<p>These methods include arguments for the namespace, the function name, and the function implementation.</p> | |
<p>When you install an extension function, the function inhabits the namespace you designate. For information about XML namespaces, see <a href="http://www.w3.org/TR/REC-xml-names/">Namespaces in XML</a>.</p> | |
<p>The following code fragment installs locally the square root function defined above, and binds it to the extension-function name "square-root" in the namespace "http://MyExternalFunction.mycompany.org" so it can be accessed from stylesheets. Keep in mind that the function name does not need to be the same as the name of the function class, and that a function name may be used more than once provided that each function with that name is installed in a different namespace.</p> | |
<blockquote class="source"> | |
<pre>#include <xalanc/Include/PlatformDefinitions.hpp> | |
#include <xercesc/util/PlatformUtils.hpp> | |
#include <xalanc/XalanTransformer/XalanTransformer.hpp> | |
// You have created a header file for FunctionSquareRoot. | |
#include <MyFunctions/FunctionSquareRoot.hpp> | |
// The namespace... | |
const XalanDOMString | |
theNamespace("http://MyExternalFunction.mycompany.org"); | |
theXalanTransformer.installExternalFunction(theNamespace, | |
XalanDOMString("square-root"), | |
FunctionSquareRoot());</pre> | |
</blockquote> | |
<p>For an example that installs three functions, see the <a href="samples.html#externalfunctions">External Functions</a> sample.</p> | |
<a name="use"></a> | |
<p align="right" size="2"> | |
<a href="#content">(top)</a> | |
</p> | |
<h3>Using an extension function</h3> | |
<p>To use the extension function in a stylesheet, you must do the following:</p> | |
<ol> | |
<li>Declare the extension function namespace.<br /> | |
<br /> | |
<code>xmlns:<b> | |
<i>prefix</i> | |
</b>=<b> | |
<i>URI</i> | |
</b> | |
</code> | |
<br /> | |
<br /> | |
The <b> | |
<i>prefix</i> | |
</b> identifies the namespace, and <b> | |
<i>URI</i> | |
</b> matches the namespace specified when the function | |
is installed.<br /> | |
<br /> | |
By default, namespace declarations are included in the transformation output. To exclude namespaces from the output, | |
use<br /> | |
<br /> | |
<code>exclude-result-prefixes="<b> | |
<i>prefix-1 prefix-2 ...</i> | |
</b>"</code> | |
<br /> | |
<br /> | |
in the stylesheet element or<br /> | |
<br /> | |
<code>xsl:exclude-result-prefixes="<b> | |
<i>prefix-1 prefix-2 ...</i> | |
</b>"</code> | |
<br /> | |
<br /> | |
in a literal result element or extension element.<br /> | |
<br /> | |
</li> | |
<li>Call the extension function in the same manner you would call an XPath function. The function name you use in the stylesheet is a Qualified Name (QName) made up of the prefix you declared in step 1 and the function name you specified when you installed the function.<br /> | |
<br /> | |
You can use XPath expressions, literals (for string, boolean, and number), and values returned by other functions to | |
specify function arguments.</li> | |
</ol> | |
<p>Suppose, for example, you are working with XML documents containing area elements like | |
<code><area value="397"/></code>, where the value attribute identifies the area of a square.</p> | |
<p>The following stylesheet declares the square-root function namespace (the prefix is up to you), instructs | |
the processor not to copy the namespace declaration to the result tree, and uses the square-root function to return | |
the square root of //area/@value:</p> | |
<blockquote class="source"> | |
<pre> | |
<?xml version="1.0"?> | |
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" | |
version="1.0" | |
xmlns:external="http://ExternalFunction.xalan-c.xml.apache.org" | |
exclude-result-prefixes="external"> | |
<xsl:template match="//area"> | |
<out> | |
The area of the square is | |
<xsl:value-of select="@value"/> square units. | |
The length of each side is | |
<xsl:value-of select="external:square-root(@value)"/> units | |
</out> | |
</pre> | |
</blockquote> | |
<p>This stylesheet converts <code><area value="397"/></code> into the following output:</p> | |
<blockquote class="source"> | |
<pre><out> | |
The area of the square is | |
397 square units. | |
The length of each side is | |
19.9249 units. | |
</out> | |
</pre> | |
</blockquote> | |
<p>For a slightly more complex variation on this example, | |
see the <a href="samples.html#externalfunctions">External Functions</a> sample.</p> | |
<p align="right" size="2"> | |
<a href="#content">(top)</a> | |
</p> | |
<h4>Passing Nodes to a function</h4> | |
<p>Please keep in mind that <b>all</b> LocationPath expressions return a node-set, even if the expression only | |
returns a single attribute or a text node (node-sets with one member). You can use the XSLT string() function | |
to convert a node-set value to string, and the number() function to convert a node-set value to number (a double).</p> | |
<p>If you pass a node-set to an extension function, be sure to set up the function to process a node-set.</p> | |
<p>Suppose, for example, you have a ProcessNodes function class that uses<br /> | |
<br /> | |
<code>const NodeRefListBase& theNodeList = args[0]->nodeset();</code> | |
<br /> | |
<br /> | |
in the execute() method to get a reference to the node-set.</p> | |
<p>Assuming you install the function as "ProcessNodes" and use the "node-ext" prefix in a stylesheet to refer to the ProcessNodes function namespace, any of the following function calls are syntactically possible:</p> | |
<p> | |
<code><!--Process the current node--></code> | |
<br /> | |
<code><xsl:variable name="success" select="node-ext:ProcessNodes(.)"/></code> | |
</p> | |
<p> | |
<code><!--Process all nodes in current context--></code> | |
<br /> | |
<code><xsl:variable name="success" select="node-ext:ProcessNodes(*)"/></code> | |
</p> | |
<p> | |
<code><!-- Process all nodes --></code> | |
<br /> | |
<code><xsl:variable name="success" select="node-ext:ProcessNodes(/*)"/></code> | |
</p> | |
<p> | |
<code><!--Process the foo/baz nodes in current context --></code> | |
<br /> | |
<code><xsl:variable name="success" select="node-ext:ProcessNodes(foo/baz)"/></code> | |
</p> | |
<p> | |
<code><!--Process the/foo/baz and /bar/saz nodes --></code> | |
<br /> | |
<code><xsl:variable name="success" select="node-ext:ProcessNodes(/foo/baz | /bar/saz)"/></code> | |
</p> | |
<p>The NodeRefListBase is in fact a list of references into the XML document, so keep in mind that getNextSibling(), | |
for example, gets you the next sibling in the document, which may not be the next Node in the node-set.</p> | |
<p align="right" size="2"> | |
<a href="#content">(top)</a> | |
</p> | |
</div> | |
<div id="footer">Copyright © 1999-2012 The Apache Software Foundation<br />Apache, Xalan, and the Feather logo are trademarks of The Apache Software Foundation<div class="small">Web Page created on - Sun 09/09/2012</div> | |
</div> | |
</body> | |
</html> |