2 * dynamic.c: Implementation of the EXSLT -- Dynamic module
5 * http://www.exslt.org/dyn/dyn.html
7 * See Copyright for the status of this software.
10 * Mark Vakoc <mark_vakoc@jdedwards.com>
11 * Thomas Broyer <tbroyer@ltgt.net>
24 #include "libexslt/libexslt.h"
26 #if defined(WIN32) && !defined (__CYGWIN__) && (!__MINGW32__)
27 #include <win32config.h>
32 #include <libxml/tree.h>
33 #include <libxml/xpath.h>
34 #include <libxml/xpathInternals.h>
36 #include <libxslt/xsltconfig.h>
37 #include <libxslt/xsltutils.h>
38 #include <libxslt/xsltInternals.h>
39 #include <libxslt/extensions.h>
44 * exsltDynEvaluateFunction:
45 * @ctxt: an XPath parser context
46 * @nargs: the number of arguments
48 * Evaluates the string as an XPath expression and returns the result
49 * value, which may be a boolean, number, string, node set, result tree
50 * fragment or external object.
54 exsltDynEvaluateFunction(xmlXPathParserContextPtr ctxt, int nargs) {
56 xmlXPathObjectPtr ret = NULL;
61 xsltPrintErrorContext(xsltXPathGetTransformContext(ctxt), NULL, NULL);
62 xsltGenericError(xsltGenericErrorContext,
63 "dyn:evalute() : invalid number of args %d\n", nargs);
64 ctxt->error = XPATH_INVALID_ARITY;
67 str = xmlXPathPopString(ctxt);
68 /* return an empty node-set if an empty string is passed in */
69 if (!str||!xmlStrlen(str)) {
70 if (str) xmlFree(str);
71 valuePush(ctxt,xmlXPathNewNodeSet(NULL));
74 ret = xmlXPathEval(str,ctxt->context);
78 xsltGenericError(xsltGenericErrorContext,
79 "dyn:evaluate() : unable to evaluate expression '%s'\n",str);
80 valuePush(ctxt,xmlXPathNewNodeSet(NULL));
87 * exsltDynMapFunction:
88 * @ctxt: an XPath parser context
89 * @nargs: the number of arguments
91 * Evaluates the string as an XPath expression and returns the result
92 * value, which may be a boolean, number, string, node set, result tree
93 * fragment or external object.
97 exsltDynMapFunction(xmlXPathParserContextPtr ctxt, int nargs)
100 xmlNodeSetPtr nodeset = NULL;
101 xsltTransformContextPtr tctxt;
102 xmlXPathCompExprPtr comp = NULL;
103 xmlXPathObjectPtr ret = NULL;
104 xmlDocPtr oldDoc, container = NULL;
107 int oldProximityPosition;
112 xmlXPathSetArityError(ctxt);
115 str = xmlXPathPopString(ctxt);
116 if (xmlXPathCheckError(ctxt))
119 nodeset = xmlXPathPopNodeSet(ctxt);
120 if (xmlXPathCheckError(ctxt))
123 ret = xmlXPathNewNodeSet(NULL);
125 xsltGenericError(xsltGenericErrorContext,
126 "exsltDynMapFunction: ret == NULL\n");
130 if (str == NULL || !xmlStrlen(str) || !(comp = xmlXPathCompile(str)))
133 oldDoc = ctxt->context->doc;
134 oldNode = ctxt->context->node;
135 oldContextSize = ctxt->context->contextSize;
136 oldProximityPosition = ctxt->context->proximityPosition;
139 * since we really don't know we're going to be adding node(s)
140 * down the road we create the RVT regardless
142 tctxt = xsltXPathGetTransformContext(ctxt);
144 xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
145 "dyn:map : internal error tctxt == NULL\n");
148 container = xsltCreateRVT(tctxt);
149 if (container == NULL) {
150 xsltTransformError(tctxt, NULL, NULL,
151 "dyn:map : internal error container == NULL\n");
154 xsltRegisterLocalRVT(tctxt, container);
155 if (nodeset && nodeset->nodeNr > 0) {
156 xmlXPathNodeSetSort(nodeset);
157 ctxt->context->contextSize = nodeset->nodeNr;
158 ctxt->context->proximityPosition = 0;
159 for (i = 0; i < nodeset->nodeNr; i++) {
160 xmlXPathObjectPtr subResult = NULL;
161 xmlNodePtr cur = nodeset->nodeTab[i];
163 ctxt->context->proximityPosition++;
164 ctxt->context->node = cur;
166 if (cur->type == XML_NAMESPACE_DECL) {
168 * The XPath module sets the owner element of a ns-node on
169 * the ns->next field.
171 cur = (xmlNodePtr) ((xmlNsPtr) cur)->next;
172 if ((cur == NULL) || (cur->type != XML_ELEMENT_NODE)) {
173 xsltGenericError(xsltGenericErrorContext,
174 "Internal error in exsltDynMapFunction: "
175 "Cannot retrieve the doc of a namespace node.\n");
178 ctxt->context->doc = cur->doc;
180 ctxt->context->doc = cur->doc;
183 subResult = xmlXPathCompiledEval(comp, ctxt->context);
184 if (subResult != NULL) {
185 switch (subResult->type) {
187 if (subResult->nodesetval != NULL)
188 for (j = 0; j < subResult->nodesetval->nodeNr;
190 xmlXPathNodeSetAdd(ret->nodesetval,
191 subResult->nodesetval->
195 if (container != NULL) {
197 xmlNewChild((xmlNodePtr) container, NULL,
199 BAD_CAST (subResult->
200 boolval ? "true" : ""));
205 "http://exslt.org/common",
207 xmlXPathNodeSetAddUnique(ret->nodesetval,
213 if (container != NULL) {
215 xmlXPathCastNumberToString(subResult->
218 xmlNewChild((xmlNodePtr) container, NULL,
219 BAD_CAST "number", val);
227 "http://exslt.org/common",
229 xmlXPathNodeSetAddUnique(ret->nodesetval,
235 if (container != NULL) {
237 xmlNewChild((xmlNodePtr) container, NULL,
239 subResult->stringval);
244 "http://exslt.org/common",
246 xmlXPathNodeSetAddUnique(ret->nodesetval,
254 xmlXPathFreeObject(subResult);
258 ctxt->context->doc = oldDoc;
259 ctxt->context->node = oldNode;
260 ctxt->context->contextSize = oldContextSize;
261 ctxt->context->proximityPosition = oldProximityPosition;
265 /* restore the xpath context */
267 xmlXPathFreeCompExpr(comp);
269 xmlXPathFreeNodeSet(nodeset);
272 valuePush(ctxt, ret);
280 * Registers the EXSLT - Dynamic module
284 exsltDynRegister (void) {
285 xsltRegisterExtModuleFunction ((const xmlChar *) "evaluate",
286 EXSLT_DYNAMIC_NAMESPACE,
287 exsltDynEvaluateFunction);
288 xsltRegisterExtModuleFunction ((const xmlChar *) "map",
289 EXSLT_DYNAMIC_NAMESPACE,
290 exsltDynMapFunction);