diff options
-rw-r--r-- | ChangeLog | 12 | ||||
-rw-r--r-- | libexslt/Makefile.am | 3 | ||||
-rw-r--r-- | libexslt/exslt.c | 1 | ||||
-rw-r--r-- | libexslt/exslt.h | 2 | ||||
-rw-r--r-- | libexslt/saxon.c | 186 | ||||
-rw-r--r-- | tests/exslt/common/object-type.1.out | 2 | ||||
-rw-r--r-- | tests/extensions/evaluate.xsl | 16 | ||||
-rw-r--r-- | tests/extensions/list.out | 5 | ||||
-rw-r--r-- | tests/extensions/list.xsl | 8 |
9 files changed, 214 insertions, 21 deletions
@@ -1,3 +1,15 @@ +Sun Oct 7 18:53:34 CEST 2001 Thomas Broyer <tbroyer@ltgt.net> + + * libexslt/saxon.c libexslt/Makefile.am libexslt/exslt.[ch]: + added implementation of SAXON expression(), eval() and + evaluate() functions. + See http://saxon.sourceforge.net/saxon6.4.4/extensions.html + * tests/extension/evaluate.xsl tests/extension/list.{xsl,out}: + modified to use SAXON namespace (functions are not registered + in the LibXSLT namespace) + * tests/exslt/common/object-type.1.out: modified to take account + of the new saxon:expression function + Sun Oct 7 13:15:33 CEST 2001 Daniel Veillard <daniel@veillard.com> * libxslt/numbers.c: fixed bug #61070, number ANY formatting diff --git a/libexslt/Makefile.am b/libexslt/Makefile.am index d297676f..c50fa89b 100644 --- a/libexslt/Makefile.am +++ b/libexslt/Makefile.am @@ -19,7 +19,8 @@ libexslt_la_SOURCES = \ sets.c \ functions.c \ strings.c \ - date.c + date.c \ + saxon.c libexslt_la_LIBADD = $(EXTRA_LIBS) libexslt_la_LDFLAGS = -version-info @LIBEXSLT_VERSION_INFO@ diff --git a/libexslt/exslt.c b/libexslt/exslt.c index 32d88106..50082fde 100644 --- a/libexslt/exslt.c +++ b/libexslt/exslt.c @@ -28,5 +28,6 @@ exsltRegisterAll (void) { exsltFuncRegister(); exsltStrRegister(); exsltDateRegister(); + exsltSaxonRegister(); } diff --git a/libexslt/exslt.h b/libexslt/exslt.h index 5d57937a..0bb53eaf 100644 --- a/libexslt/exslt.h +++ b/libexslt/exslt.h @@ -16,6 +16,7 @@ LIBEXSLT_PUBLIC extern const int exsltLibxmlVersion; #define EXSLT_FUNCTIONS_NAMESPACE ((const xmlChar *) "http://exslt.org/functions") #define EXSLT_STRINGS_NAMESPACE ((const xmlChar *) "http://exslt.org/strings") #define EXSLT_DATE_NAMESPACE ((const xmlChar *) "http://exslt.org/dates-and-times") +#define SAXON_NAMESPACE ((const xmlChar *) "http://icl.com/saxon") void exsltCommonRegister (void); void exsltMathRegister (void); @@ -23,6 +24,7 @@ void exsltSetsRegister (void); void exsltFuncRegister (void); void exsltStrRegister (void); void exsltDateRegister (void); +void exsltSaxonRegister (void); void exsltRegisterAll (void); diff --git a/libexslt/saxon.c b/libexslt/saxon.c new file mode 100644 index 00000000..2a8325e6 --- /dev/null +++ b/libexslt/saxon.c @@ -0,0 +1,186 @@ +#include <libxml/tree.h> +#include <libxml/xpath.h> +#include <libxml/xpathInternals.h> +#include <libxml/parser.h> + +#include <libxslt/xsltconfig.h> +#include <libxslt/xsltutils.h> +#include <libxslt/xsltInternals.h> +#include <libxslt/extensions.h> + +#include "exslt.h" + +/** + * exsltSaxonInit: + * @ctxt: an XSLT transformation context + * @URI: the namespace URI for the extension + * + * Initializes the SAXON module. + * + * Returns the data for this transformation + */ +static xmlHashTablePtr +exsltSaxonInit (xsltTransformContextPtr ctxt ATTRIBUTE_UNUSED, + const xmlChar *URI ATTRIBUTE_UNUSED) { + return xmlHashCreate(1); +} + +/** + * exsltSaxonShutdown: + * @ctxt: an XSLT transformation context + * @URI: the namespace URI for the extension + * @data: the module data to free up + * + * Shutdown the SAXON extension module + */ +static void +exsltSaxonShutdown (xsltTransformContextPtr ctxt ATTRIBUTE_UNUSED, + const xmlChar *URI ATTRIBUTE_UNUSED, + xmlHashTablePtr data) { + xmlHashFree(data, (xmlHashDeallocator) xmlXPathFreeCompExpr); +} + + +/** + * exsltSaxonExpressionFunction: + * @ctxt: an XPath parser context + * @nargs: the number of arguments + * + * The supplied string must contain an XPath expression. The result of + * the function is a stored expression, which may be supplied as an + * argument to other extension functions such as saxon:eval(), + * saxon:sum() and saxon:distinct(). The result of the expression will + * usually depend on the current node. The expression may contain + * references to variables that are in scope at the point where + * saxon:expression() is called: these variables will be replaced in + * the stored expression with the values they take at the time + * saxon:expression() is called, not the values of the variables at + * the time the stored expression is evaluated. Similarly, if the + * expression contains namespace prefixes, these are interpreted in + * terms of the namespace declarations in scope at the point where the + * saxon:expression() function is called, not those in scope where the + * stored expression is evaluated. + * + * TODO: current implementation doesn't conform to SAXON behaviour + * regarding context and namespaces. + */ +static void +exsltSaxonExpressionFunction (xmlXPathParserContextPtr ctxt, int nargs) { + xmlChar *arg; + xmlXPathCompExprPtr ret; + xmlHashTablePtr hash; + xsltTransformContextPtr tctxt = xsltXPathGetTransformContext(ctxt); + + if (nargs != 1) { + xmlXPathSetArityError(ctxt); + return; + } + + arg = xmlXPathPopString(ctxt); + if (xmlXPathCheckError(ctxt) || (arg == NULL)) { + xmlXPathSetTypeError(ctxt); + return; + } + + hash = (xmlHashTablePtr) xsltGetExtData(tctxt->style, + ctxt->context->functionURI); + + ret = xmlHashLookup(hash, arg); + if (ret != NULL) + goto done; + + ret = xmlXPathCompile(arg); + + xmlHashAddEntry(hash, arg, (void *) ret); + +done: + xmlFree(arg); + + xmlXPathReturnExternal(ctxt, ret); +} + +/** + * exsltSaxonEvalFunction: + * @ctxt: an XPath parser context + * @nargs: number of arguments + * + * Implements de SAXON eval() function: + * object saxon:eval (saxon:stored-expression) + * Returns the result of evaluating the supplied stored expression. + * A stored expression may be obtained as the result of calling + * the saxon:expression() function. + * The stored expression is evaluated in the current context, that + * is, the context node is the current node, and the context position + * and context size are the same as the result of calling position() + * or last() respectively. + */ +static void +exsltSaxonEvalFunction (xmlXPathParserContextPtr ctxt, int nargs) { + xmlXPathCompExprPtr expr; + xmlXPathObjectPtr ret; + + if (nargs != 1) { + xmlXPathSetArityError(ctxt); + return; + } + + if (!xmlXPathStackIsExternal(ctxt)) { + xmlXPathSetTypeError(ctxt); + return; + } + + expr = (xmlXPathCompExprPtr) xmlXPathPopExternal(ctxt); + + ret = xmlXPathCompiledEval(expr, ctxt->context); + + valuePush(ctxt, ret); +} + +/** + * exsltSaxonEvaluateFunction: + * @ctxt: an XPath parser context + * @nargs: number of arguments + * + * Implements the SAXON evaluate() function + * object saxon:evaluate (string) + * The supplied string must contain an XPath expression. The result of + * the function is the result of evaluating the XPath expression. This + * is useful where an expression needs to be constructed at run-time or + * passed to the stylesheet as a parameter, for example where the sort + * key is determined dynamically. The context for the expression (e.g. + * which variables and namespaces are available) is exactly the same as + * if the expression were written explicitly at this point in the + * stylesheet. The function saxon:evaluate(string) is shorthand for + * saxon:eval(saxon:expression(string)). + */ +static void +exsltSaxonEvaluateFunction (xmlXPathParserContextPtr ctxt, int nargs) { + if (nargs != 1) { + xmlXPathSetArityError(ctxt); + return; + } + + exsltSaxonExpressionFunction(ctxt, 1); + exsltSaxonEvalFunction(ctxt, 1); +} + +/** + * exsltSaxonRegister: + * + * Registers the SAXON extension module + */ +void +exsltSaxonRegister (void) { + xsltRegisterExtModule (SAXON_NAMESPACE, + (xsltExtInitFunction) exsltSaxonInit, + (xsltExtShutdownFunction) exsltSaxonShutdown); + xsltRegisterExtModuleFunction((const xmlChar *) "expression", + SAXON_NAMESPACE, + exsltSaxonExpressionFunction); + xsltRegisterExtModuleFunction((const xmlChar *) "eval", + SAXON_NAMESPACE, + exsltSaxonEvalFunction); + xsltRegisterExtModuleFunction((const xmlChar *) "evaluate", + SAXON_NAMESPACE, + exsltSaxonEvaluateFunction); +} diff --git a/tests/exslt/common/object-type.1.out b/tests/exslt/common/object-type.1.out index e21cdcaa..81375b5e 100644 --- a/tests/exslt/common/object-type.1.out +++ b/tests/exslt/common/object-type.1.out @@ -5,5 +5,5 @@ boolean; node-set; RTF; - ; + external; </out> diff --git a/tests/extensions/evaluate.xsl b/tests/extensions/evaluate.xsl index a58470f6..c44bfc8c 100644 --- a/tests/extensions/evaluate.xsl +++ b/tests/extensions/evaluate.xsl @@ -1,24 +1,24 @@ <?xml version='1.0'?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" - xmlns:libxslt="http://xmlsoft.org/XSLT/namespace" + xmlns:saxon="http://icl.com/saxon" version='1.0'> -<xsl:variable name="expression" select="libxslt:expression('doc/two')"/> +<xsl:variable name="expression" select="saxon:expression('doc/two')"/> <xsl:template match="/"> <xsl:variable name="string">doc/one</xsl:variable> - <xsl:value-of select="libxslt:evaluate($string)"/> - <xsl:value-of select="count(libxslt:evaluate('/doc/one')/../*)"/> - <xsl:value-of select="libxslt:evaluate(/doc/three)"/> - <xsl:value-of select="libxslt:eval($expression)"/> + <xsl:value-of select="saxon:evaluate($string)"/> + <xsl:value-of select="count(saxon:evaluate('/doc/one')/../*)"/> + <xsl:value-of select="saxon:evaluate(/doc/three)"/> + <xsl:value-of select="saxon:eval($expression)"/> <xsl:apply-templates/> </xsl:template> <xsl:template match="four"> <xsl:variable name="string">doc/one</xsl:variable> - <xsl:value-of select="libxslt:evaluate($string)"/> - <xsl:value-of select="libxslt:eval($expression)"/> + <xsl:value-of select="saxon:evaluate($string)"/> + <xsl:value-of select="saxon:eval($expression)"/> </xsl:template> <xsl:template match="text()"/> diff --git a/tests/extensions/list.out b/tests/extensions/list.out index c910ba08..e2d9ce12 100644 --- a/tests/extensions/list.out +++ b/tests/extensions/list.out @@ -30,14 +30,11 @@ saxon:output available xalanredirect:write available xt:document available libxslt:debug available - === 9 Extension functions: + === 6 Extension functions: libxslt:node-set() available saxon:node-set() available xt:node-set() available -libxslt:evaluate() available saxon:evaluate() available -libxslt:expression() available saxon:expression() available -libxslt:eval() available saxon:eval() available diff --git a/tests/extensions/list.xsl b/tests/extensions/list.xsl index d4fc6693..0523342b 100644 --- a/tests/extensions/list.xsl +++ b/tests/extensions/list.xsl @@ -69,7 +69,7 @@ </xsl:if> <xsl:if test="element-available('libxslt:debug')">libxslt:debug available </xsl:if> -<xsl:text> === 9 Extension functions: +<xsl:text> === 6 Extension functions: </xsl:text> <xsl:if test="function-available('libxslt:node-set')">libxslt:node-set() available </xsl:if> @@ -77,16 +77,10 @@ </xsl:if> <xsl:if test="function-available('xt:node-set')">xt:node-set() available </xsl:if> -<xsl:if test="function-available('libxslt:evaluate')">libxslt:evaluate() available -</xsl:if> <xsl:if test="function-available('saxon:evaluate')">saxon:evaluate() available </xsl:if> -<xsl:if test="function-available('libxslt:expression')">libxslt:expression() available -</xsl:if> <xsl:if test="function-available('saxon:expression')">saxon:expression() available </xsl:if> -<xsl:if test="function-available('libxslt:eval')">libxslt:eval() available -</xsl:if> <xsl:if test="function-available('saxon:eval')">saxon:eval() available </xsl:if> </xsl:template> |