summaryrefslogtreecommitdiff
path: root/libexslt/dynamic.c
diff options
context:
space:
mode:
authorKasimier T. Buchcik <kbuchcik@src.gnome.org>2006-07-14 16:10:25 +0000
committerKasimier T. Buchcik <kbuchcik@src.gnome.org>2006-07-14 16:10:25 +0000
commit90d2d1c28995e327dacccf820c5fb8ca90b6dc0b (patch)
tree3e8e712f30d87621379e3152d9839772ae51abfd /libexslt/dynamic.c
parent36615d1c6d582ef9bd2f2a451fae6c12b97d3ede (diff)
downloadlibxslt-90d2d1c28995e327dacccf820c5fb8ca90b6dc0b.tar.gz
libxslt-90d2d1c28995e327dacccf820c5fb8ca90b6dc0b.tar.bz2
libxslt-90d2d1c28995e327dacccf820c5fb8ca90b6dc0b.zip
Refactored xsltValueOf(). Changed to use xmlXPathCastToString() directly,
* libxslt/attributes.c libxslt/documents.c libxslt/functions.c libxslt/keys.c libxslt/namespaces.c libxslt/pattern.c libxslt/preproc.c libxslt/templates.c libxslt/templates.h libxslt/transform.c libxslt/variables.c libxslt/xslt.c libxslt/xsltInternals.h libxslt/xsltutils.c libxslt/xsltutils.h libexslt/common.c libexslt/dynamic.c libexslt/functions.c libexslt/strings.c: Refactored xsltValueOf(). Changed to use xmlXPathCastToString() directly, rather than creating an intermediate object with xmlXPathConvertString(). This now does not add a text-node to the result if the string is empty (this has impact on serialization, since an empty text-node is serialized as <foo></foo>, and now it will be serialized as <foo/>). Refactored other functions in transform.c: Mostly code cleanup/restructuring. Minimized number of function variables for instruction which eat up function stack memory when recursing templates (xsltIf(), xsltChoose(), xsltApplyTemplates(), xsltCallTemplate()). Changed XSLT tests to use xmlXPathCompiledEvalToBoolean(). Implemented redefinition checks at compilation-time and eliminating them at transformation time in the refactored code paths. Introduced the field @currentTemplateRule on xsltTransformContext to reflect the "Current Template Rule" as defined by the spec. NOTE that ctxt->currentTemplateRule and ctxt->templ is not the same; the former is the "Current Template Rule" as defined by the XSLT spec, the latter is simply the template struct being currently processed by Libxslt. Added XML_COMMENT_NODE and XML_CDATA_SECTION_NODE to the macro IS_XSLT_REAL_NODE. Misc code cleanup/restructuring and everything else I already forgot. Refactored lifetime of temporary result tree fragments. Substituted all calls to the now deprecated xsltRegisterTmpRVT() for the new xsltRegisterLocalRVT(). Fragments of xsl:variable and xsl:param are freed when the variable/pram is freed. Fragments created when evaluating a "select" of xsl:varible and xsl:param are also bound to the lifetime of the var/param. EXSLT's func:function now uses the following functions to let take care the transformation's garbage collector of returned tree fragments: xsltExtensionInstructionResultRegister(), xsltExtensionInstructionResultFinalize() Fixes: #339222 - xsl:param at invalid position inside an xsl:template is not catched #346015 - Non-declared caller-parameters are accepted #160400 - Compiles invalid XSLT; unbound variable accepted #308441 - namespaced parameters become unregistered #307103 - problem with proximity position in predicates of match patterns #328218 - problem with exsl:node-set() when converting strings to node sets #318088 - infinite recursion detection #321505 - Multiple contiguous CDATA in output #334493 - "--param" option does not have root context #114377 - weird func:result/xsl:variable/exsl:node-set interaction #150309 - Regression caused by fix for 142768
Diffstat (limited to 'libexslt/dynamic.c')
-rw-r--r--libexslt/dynamic.c548
1 files changed, 274 insertions, 274 deletions
diff --git a/libexslt/dynamic.c b/libexslt/dynamic.c
index 86db6634..87ef8da3 100644
--- a/libexslt/dynamic.c
+++ b/libexslt/dynamic.c
@@ -1,274 +1,274 @@
-/*
- * dynamic.c: Implementation of the EXSLT -- Dynamic module
- *
- * References:
- * http://www.exslt.org/dyn/dyn.html
- *
- * See Copyright for the status of this software.
- *
- * Authors:
- * Mark Vakoc <mark_vakoc@jdedwards.com>
- * Thomas Broyer <tbroyer@ltgt.net>
- *
- * TODO:
- * elements:
- * functions:
- * min
- * max
- * sum
- * map
- * closure
- */
-
-#define IN_LIBEXSLT
-#include "libexslt/libexslt.h"
-
-#if defined(WIN32) && !defined (__CYGWIN__) && (!__MINGW32__)
-#include <win32config.h>
-#else
-#include "config.h"
-#endif
-
-#include <libxml/tree.h>
-#include <libxml/xpath.h>
-#include <libxml/xpathInternals.h>
-
-#include <libxslt/xsltconfig.h>
-#include <libxslt/xsltutils.h>
-#include <libxslt/xsltInternals.h>
-#include <libxslt/extensions.h>
-
-#include "exslt.h"
-
-/**
- * exsltDynEvaluateFunction:
- * @ctxt: an XPath parser context
- * @nargs: the number of arguments
- *
- * Evaluates the string as an XPath expression and returns the result
- * value, which may be a boolean, number, string, node set, result tree
- * fragment or external object.
- */
-
-static void
-exsltDynEvaluateFunction(xmlXPathParserContextPtr ctxt, int nargs) {
- xmlChar *str = NULL;
- xmlXPathObjectPtr ret = NULL;
-
- if (ctxt == NULL)
- return;
- if (nargs != 1) {
- xsltPrintErrorContext(xsltXPathGetTransformContext(ctxt), NULL, NULL);
- xsltGenericError(xsltGenericErrorContext,
- "dyn:evalute() : invalid number of args %d\n", nargs);
- ctxt->error = XPATH_INVALID_ARITY;
- return;
- }
- str = xmlXPathPopString(ctxt);
- /* return an empty node-set if an empty string is passed in */
- if (!str||!xmlStrlen(str)) {
- if (str) xmlFree(str);
- valuePush(ctxt,xmlXPathNewNodeSet(NULL));
- return;
- }
- ret = xmlXPathEval(str,ctxt->context);
- if (ret)
- valuePush(ctxt,ret);
- else {
- xsltGenericError(xsltGenericErrorContext,
- "dyn:evaluate() : unable to evaluate expression '%s'\n",str);
- valuePush(ctxt,xmlXPathNewNodeSet(NULL));
- }
- xmlFree(str);
- return;
-}
-
-/**
- * exsltDynMapFunction:
- * @ctxt: an XPath parser context
- * @nargs: the number of arguments
- *
- * Evaluates the string as an XPath expression and returns the result
- * value, which may be a boolean, number, string, node set, result tree
- * fragment or external object.
- */
-
-static void
-exsltDynMapFunction(xmlXPathParserContextPtr ctxt, int nargs)
-{
- xmlChar *str = NULL;
- xmlNodeSetPtr nodeset = NULL;
- xmlXPathCompExprPtr comp = NULL;
- xmlXPathObjectPtr ret = NULL;
- xmlDocPtr oldDoc, container;
- xmlNodePtr oldNode;
- int oldContextSize;
- int oldProximityPosition;
- int i, j;
-
-
- if (nargs != 2) {
- xmlXPathSetArityError(ctxt);
- return;
- }
- str = xmlXPathPopString(ctxt);
- if (xmlXPathCheckError(ctxt)) {
- xmlXPathSetTypeError(ctxt);
- return;
- }
-
- nodeset = xmlXPathPopNodeSet(ctxt);
- if (xmlXPathCheckError(ctxt)) {
- xmlXPathSetTypeError(ctxt);
- return;
- }
- if (str == NULL || !xmlStrlen(str) || !(comp = xmlXPathCompile(str))) {
- if (nodeset != NULL)
- xmlXPathFreeNodeSet(nodeset);
- if (str != NULL)
- xmlFree(str);
- valuePush(ctxt, xmlXPathNewNodeSet(NULL));
- return;
- }
-
- ret = xmlXPathNewNodeSet(NULL);
- if (ret == NULL) {
- xsltGenericError(xsltGenericErrorContext,
- "exsltDynMapFunctoin: ret == NULL\n");
- goto cleanup;
- }
-
- oldDoc = ctxt->context->doc;
- oldNode = ctxt->context->node;
- oldContextSize = ctxt->context->contextSize;
- oldProximityPosition = ctxt->context->proximityPosition;
-
- /**
- * since we really don't know we're going to be adding node(s)
- * down the road we create the RVT regardless
- */
- container = xsltCreateRVT(xsltXPathGetTransformContext(ctxt));
- if (container != NULL)
- xsltRegisterTmpRVT(xsltXPathGetTransformContext(ctxt), container);
-
- if (nodeset && nodeset->nodeNr > 0) {
- xmlXPathNodeSetSort(nodeset);
- ctxt->context->contextSize = nodeset->nodeNr;
- ctxt->context->proximityPosition = 0;
- for (i = 0; i < nodeset->nodeNr; i++) {
- xmlXPathObjectPtr subResult = NULL;
-
- ctxt->context->proximityPosition++;
- ctxt->context->node = nodeset->nodeTab[i];
- ctxt->context->doc = nodeset->nodeTab[i]->doc;
-
- subResult = xmlXPathCompiledEval(comp, ctxt->context);
- if (subResult != NULL) {
- switch (subResult->type) {
- case XPATH_NODESET:
- if (subResult->nodesetval != NULL)
- for (j = 0; j < subResult->nodesetval->nodeNr;
- j++)
- xmlXPathNodeSetAdd(ret->nodesetval,
- subResult->nodesetval->
- nodeTab[j]);
- break;
- case XPATH_BOOLEAN:
- if (container != NULL) {
- xmlNodePtr cur =
- xmlNewChild((xmlNodePtr) container, NULL,
- BAD_CAST "boolean",
- BAD_CAST (subResult->
- boolval ? "true" : ""));
- if (cur != NULL) {
- cur->ns =
- xmlNewNs(cur,
- BAD_CAST
- "http://exslt.org/common",
- BAD_CAST "exsl");
- xmlXPathNodeSetAddUnique(ret->nodesetval,
- cur);
- }
- }
- break;
- case XPATH_NUMBER:
- if (container != NULL) {
- xmlChar *val =
- xmlXPathCastNumberToString(subResult->
- floatval);
- xmlNodePtr cur =
- xmlNewChild((xmlNodePtr) container, NULL,
- BAD_CAST "number", val);
- if (val != NULL)
- xmlFree(val);
-
- if (cur != NULL) {
- cur->ns =
- xmlNewNs(cur,
- BAD_CAST
- "http://exslt.org/common",
- BAD_CAST "exsl");
- xmlXPathNodeSetAddUnique(ret->nodesetval,
- cur);
- }
- }
- break;
- case XPATH_STRING:
- if (container != NULL) {
- xmlNodePtr cur =
- xmlNewChild((xmlNodePtr) container, NULL,
- BAD_CAST "string",
- subResult->stringval);
- if (cur != NULL) {
- cur->ns =
- xmlNewNs(cur,
- BAD_CAST
- "http://exslt.org/common",
- BAD_CAST "exsl");
- xmlXPathNodeSetAddUnique(ret->nodesetval,
- cur);
- }
- }
- break;
- default:
- break;
- }
- xmlXPathFreeObject(subResult);
- }
- }
- }
- ctxt->context->doc = oldDoc;
- ctxt->context->node = oldNode;
- ctxt->context->contextSize = oldContextSize;
- ctxt->context->proximityPosition = oldProximityPosition;
-
-
- cleanup:
- /* restore the xpath context */
- if (comp != NULL)
- xmlXPathFreeCompExpr(comp);
- if (nodeset != NULL)
- xmlXPathFreeNodeSet(nodeset);
- if (str != NULL)
- xmlFree(str);
- valuePush(ctxt, ret);
- return;
-}
-
-
-/**
- * exsltDynRegister:
- *
- * Registers the EXSLT - Dynamic module
- */
-
-void
-exsltDynRegister (void) {
- xsltRegisterExtModuleFunction ((const xmlChar *) "evaluate",
- EXSLT_DYNAMIC_NAMESPACE,
- exsltDynEvaluateFunction);
- xsltRegisterExtModuleFunction ((const xmlChar *) "map",
- EXSLT_DYNAMIC_NAMESPACE,
- exsltDynMapFunction);
-
-}
+/*
+ * dynamic.c: Implementation of the EXSLT -- Dynamic module
+ *
+ * References:
+ * http://www.exslt.org/dyn/dyn.html
+ *
+ * See Copyright for the status of this software.
+ *
+ * Authors:
+ * Mark Vakoc <mark_vakoc@jdedwards.com>
+ * Thomas Broyer <tbroyer@ltgt.net>
+ *
+ * TODO:
+ * elements:
+ * functions:
+ * min
+ * max
+ * sum
+ * map
+ * closure
+ */
+
+#define IN_LIBEXSLT
+#include "libexslt/libexslt.h"
+
+#if defined(WIN32) && !defined (__CYGWIN__) && (!__MINGW32__)
+#include <win32config.h>
+#else
+#include "config.h"
+#endif
+
+#include <libxml/tree.h>
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+
+#include <libxslt/xsltconfig.h>
+#include <libxslt/xsltutils.h>
+#include <libxslt/xsltInternals.h>
+#include <libxslt/extensions.h>
+
+#include "exslt.h"
+
+/**
+ * exsltDynEvaluateFunction:
+ * @ctxt: an XPath parser context
+ * @nargs: the number of arguments
+ *
+ * Evaluates the string as an XPath expression and returns the result
+ * value, which may be a boolean, number, string, node set, result tree
+ * fragment or external object.
+ */
+
+static void
+exsltDynEvaluateFunction(xmlXPathParserContextPtr ctxt, int nargs) {
+ xmlChar *str = NULL;
+ xmlXPathObjectPtr ret = NULL;
+
+ if (ctxt == NULL)
+ return;
+ if (nargs != 1) {
+ xsltPrintErrorContext(xsltXPathGetTransformContext(ctxt), NULL, NULL);
+ xsltGenericError(xsltGenericErrorContext,
+ "dyn:evalute() : invalid number of args %d\n", nargs);
+ ctxt->error = XPATH_INVALID_ARITY;
+ return;
+ }
+ str = xmlXPathPopString(ctxt);
+ /* return an empty node-set if an empty string is passed in */
+ if (!str||!xmlStrlen(str)) {
+ if (str) xmlFree(str);
+ valuePush(ctxt,xmlXPathNewNodeSet(NULL));
+ return;
+ }
+ ret = xmlXPathEval(str,ctxt->context);
+ if (ret)
+ valuePush(ctxt,ret);
+ else {
+ xsltGenericError(xsltGenericErrorContext,
+ "dyn:evaluate() : unable to evaluate expression '%s'\n",str);
+ valuePush(ctxt,xmlXPathNewNodeSet(NULL));
+ }
+ xmlFree(str);
+ return;
+}
+
+/**
+ * exsltDynMapFunction:
+ * @ctxt: an XPath parser context
+ * @nargs: the number of arguments
+ *
+ * Evaluates the string as an XPath expression and returns the result
+ * value, which may be a boolean, number, string, node set, result tree
+ * fragment or external object.
+ */
+
+static void
+exsltDynMapFunction(xmlXPathParserContextPtr ctxt, int nargs)
+{
+ xmlChar *str = NULL;
+ xmlNodeSetPtr nodeset = NULL;
+ xmlXPathCompExprPtr comp = NULL;
+ xmlXPathObjectPtr ret = NULL;
+ xmlDocPtr oldDoc, container;
+ xmlNodePtr oldNode;
+ int oldContextSize;
+ int oldProximityPosition;
+ int i, j;
+
+
+ if (nargs != 2) {
+ xmlXPathSetArityError(ctxt);
+ return;
+ }
+ str = xmlXPathPopString(ctxt);
+ if (xmlXPathCheckError(ctxt)) {
+ xmlXPathSetTypeError(ctxt);
+ return;
+ }
+
+ nodeset = xmlXPathPopNodeSet(ctxt);
+ if (xmlXPathCheckError(ctxt)) {
+ xmlXPathSetTypeError(ctxt);
+ return;
+ }
+ if (str == NULL || !xmlStrlen(str) || !(comp = xmlXPathCompile(str))) {
+ if (nodeset != NULL)
+ xmlXPathFreeNodeSet(nodeset);
+ if (str != NULL)
+ xmlFree(str);
+ valuePush(ctxt, xmlXPathNewNodeSet(NULL));
+ return;
+ }
+
+ ret = xmlXPathNewNodeSet(NULL);
+ if (ret == NULL) {
+ xsltGenericError(xsltGenericErrorContext,
+ "exsltDynMapFunctoin: ret == NULL\n");
+ goto cleanup;
+ }
+
+ oldDoc = ctxt->context->doc;
+ oldNode = ctxt->context->node;
+ oldContextSize = ctxt->context->contextSize;
+ oldProximityPosition = ctxt->context->proximityPosition;
+
+ /**
+ * since we really don't know we're going to be adding node(s)
+ * down the road we create the RVT regardless
+ */
+ container = xsltCreateRVT(xsltXPathGetTransformContext(ctxt));
+ if (container != NULL)
+ xsltRegisterLocalRVT(xsltXPathGetTransformContext(ctxt), container);
+
+ if (nodeset && nodeset->nodeNr > 0) {
+ xmlXPathNodeSetSort(nodeset);
+ ctxt->context->contextSize = nodeset->nodeNr;
+ ctxt->context->proximityPosition = 0;
+ for (i = 0; i < nodeset->nodeNr; i++) {
+ xmlXPathObjectPtr subResult = NULL;
+
+ ctxt->context->proximityPosition++;
+ ctxt->context->node = nodeset->nodeTab[i];
+ ctxt->context->doc = nodeset->nodeTab[i]->doc;
+
+ subResult = xmlXPathCompiledEval(comp, ctxt->context);
+ if (subResult != NULL) {
+ switch (subResult->type) {
+ case XPATH_NODESET:
+ if (subResult->nodesetval != NULL)
+ for (j = 0; j < subResult->nodesetval->nodeNr;
+ j++)
+ xmlXPathNodeSetAdd(ret->nodesetval,
+ subResult->nodesetval->
+ nodeTab[j]);
+ break;
+ case XPATH_BOOLEAN:
+ if (container != NULL) {
+ xmlNodePtr cur =
+ xmlNewChild((xmlNodePtr) container, NULL,
+ BAD_CAST "boolean",
+ BAD_CAST (subResult->
+ boolval ? "true" : ""));
+ if (cur != NULL) {
+ cur->ns =
+ xmlNewNs(cur,
+ BAD_CAST
+ "http://exslt.org/common",
+ BAD_CAST "exsl");
+ xmlXPathNodeSetAddUnique(ret->nodesetval,
+ cur);
+ }
+ }
+ break;
+ case XPATH_NUMBER:
+ if (container != NULL) {
+ xmlChar *val =
+ xmlXPathCastNumberToString(subResult->
+ floatval);
+ xmlNodePtr cur =
+ xmlNewChild((xmlNodePtr) container, NULL,
+ BAD_CAST "number", val);
+ if (val != NULL)
+ xmlFree(val);
+
+ if (cur != NULL) {
+ cur->ns =
+ xmlNewNs(cur,
+ BAD_CAST
+ "http://exslt.org/common",
+ BAD_CAST "exsl");
+ xmlXPathNodeSetAddUnique(ret->nodesetval,
+ cur);
+ }
+ }
+ break;
+ case XPATH_STRING:
+ if (container != NULL) {
+ xmlNodePtr cur =
+ xmlNewChild((xmlNodePtr) container, NULL,
+ BAD_CAST "string",
+ subResult->stringval);
+ if (cur != NULL) {
+ cur->ns =
+ xmlNewNs(cur,
+ BAD_CAST
+ "http://exslt.org/common",
+ BAD_CAST "exsl");
+ xmlXPathNodeSetAddUnique(ret->nodesetval,
+ cur);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ xmlXPathFreeObject(subResult);
+ }
+ }
+ }
+ ctxt->context->doc = oldDoc;
+ ctxt->context->node = oldNode;
+ ctxt->context->contextSize = oldContextSize;
+ ctxt->context->proximityPosition = oldProximityPosition;
+
+
+ cleanup:
+ /* restore the xpath context */
+ if (comp != NULL)
+ xmlXPathFreeCompExpr(comp);
+ if (nodeset != NULL)
+ xmlXPathFreeNodeSet(nodeset);
+ if (str != NULL)
+ xmlFree(str);
+ valuePush(ctxt, ret);
+ return;
+}
+
+
+/**
+ * exsltDynRegister:
+ *
+ * Registers the EXSLT - Dynamic module
+ */
+
+void
+exsltDynRegister (void) {
+ xsltRegisterExtModuleFunction ((const xmlChar *) "evaluate",
+ EXSLT_DYNAMIC_NAMESPACE,
+ exsltDynEvaluateFunction);
+ xsltRegisterExtModuleFunction ((const xmlChar *) "map",
+ EXSLT_DYNAMIC_NAMESPACE,
+ exsltDynMapFunction);
+
+}