diff options
author | Kasimier T. Buchcik <kbuchcik@src.gnome.org> | 2006-07-14 16:10:25 +0000 |
---|---|---|
committer | Kasimier T. Buchcik <kbuchcik@src.gnome.org> | 2006-07-14 16:10:25 +0000 |
commit | 90d2d1c28995e327dacccf820c5fb8ca90b6dc0b (patch) | |
tree | 3e8e712f30d87621379e3152d9839772ae51abfd /libexslt/dynamic.c | |
parent | 36615d1c6d582ef9bd2f2a451fae6c12b97d3ede (diff) | |
download | libxslt-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.c | 548 |
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);
+
+}
|