Roll src/third_party/WebKit a3b4a2e:7441784 (svn 202551:202552)
[chromium-blink-merge.git] / third_party / libxslt / libexslt / dynamic.c
blobe0bfe817046d599cac14337548e925fef807c6e7
1 /*
2 * dynamic.c: Implementation of the EXSLT -- Dynamic module
4 * References:
5 * http://www.exslt.org/dyn/dyn.html
7 * See Copyright for the status of this software.
9 * Authors:
10 * Mark Vakoc <mark_vakoc@jdedwards.com>
11 * Thomas Broyer <tbroyer@ltgt.net>
13 * TODO:
14 * elements:
15 * functions:
16 * min
17 * max
18 * sum
19 * map
20 * closure
23 #define IN_LIBEXSLT
24 #include "libexslt/libexslt.h"
26 #if defined(WIN32) && !defined (__CYGWIN__) && (!__MINGW32__)
27 #include <win32config.h>
28 #else
29 #include "config.h"
30 #endif
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>
41 #include "exslt.h"
43 /**
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.
53 static void
54 exsltDynEvaluateFunction(xmlXPathParserContextPtr ctxt, int nargs) {
55 xmlChar *str = NULL;
56 xmlXPathObjectPtr ret = NULL;
58 if (ctxt == NULL)
59 return;
60 if (nargs != 1) {
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;
65 return;
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));
72 return;
74 ret = xmlXPathEval(str,ctxt->context);
75 if (ret)
76 valuePush(ctxt,ret);
77 else {
78 xsltGenericError(xsltGenericErrorContext,
79 "dyn:evaluate() : unable to evaluate expression '%s'\n",str);
80 valuePush(ctxt,xmlXPathNewNodeSet(NULL));
82 xmlFree(str);
83 return;
86 /**
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.
96 static void
97 exsltDynMapFunction(xmlXPathParserContextPtr ctxt, int nargs)
99 xmlChar *str = NULL;
100 xmlNodeSetPtr nodeset = NULL;
101 xsltTransformContextPtr tctxt;
102 xmlXPathCompExprPtr comp = NULL;
103 xmlXPathObjectPtr ret = NULL;
104 xmlDocPtr oldDoc, container = NULL;
105 xmlNodePtr oldNode;
106 int oldContextSize;
107 int oldProximityPosition;
108 int i, j;
111 if (nargs != 2) {
112 xmlXPathSetArityError(ctxt);
113 return;
115 str = xmlXPathPopString(ctxt);
116 if (xmlXPathCheckError(ctxt)) {
117 xmlXPathSetTypeError(ctxt);
118 return;
121 nodeset = xmlXPathPopNodeSet(ctxt);
122 if (xmlXPathCheckError(ctxt)) {
123 xmlXPathSetTypeError(ctxt);
124 return;
126 if (str == NULL || !xmlStrlen(str) || !(comp = xmlXPathCompile(str))) {
127 if (nodeset != NULL)
128 xmlXPathFreeNodeSet(nodeset);
129 if (str != NULL)
130 xmlFree(str);
131 valuePush(ctxt, xmlXPathNewNodeSet(NULL));
132 return;
135 ret = xmlXPathNewNodeSet(NULL);
136 if (ret == NULL) {
137 xsltGenericError(xsltGenericErrorContext,
138 "exsltDynMapFunction: ret == NULL\n");
139 goto cleanup;
142 oldDoc = ctxt->context->doc;
143 oldNode = ctxt->context->node;
144 oldContextSize = ctxt->context->contextSize;
145 oldProximityPosition = ctxt->context->proximityPosition;
148 * since we really don't know we're going to be adding node(s)
149 * down the road we create the RVT regardless
151 tctxt = xsltXPathGetTransformContext(ctxt);
152 if (tctxt == NULL) {
153 xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL,
154 "dyn:map : internal error tctxt == NULL\n");
155 goto cleanup;
157 container = xsltCreateRVT(tctxt);
158 if (container == NULL) {
159 xsltTransformError(tctxt, NULL, NULL,
160 "dyn:map : internal error container == NULL\n");
161 goto cleanup;
163 xsltRegisterLocalRVT(tctxt, container);
164 if (nodeset && nodeset->nodeNr > 0) {
165 xmlXPathNodeSetSort(nodeset);
166 ctxt->context->contextSize = nodeset->nodeNr;
167 ctxt->context->proximityPosition = 0;
168 for (i = 0; i < nodeset->nodeNr; i++) {
169 xmlXPathObjectPtr subResult = NULL;
171 ctxt->context->proximityPosition++;
172 ctxt->context->node = nodeset->nodeTab[i];
173 ctxt->context->doc = nodeset->nodeTab[i]->doc;
175 subResult = xmlXPathCompiledEval(comp, ctxt->context);
176 if (subResult != NULL) {
177 switch (subResult->type) {
178 case XPATH_NODESET:
179 if (subResult->nodesetval != NULL)
180 for (j = 0; j < subResult->nodesetval->nodeNr;
181 j++)
182 xmlXPathNodeSetAdd(ret->nodesetval,
183 subResult->nodesetval->
184 nodeTab[j]);
185 break;
186 case XPATH_BOOLEAN:
187 if (container != NULL) {
188 xmlNodePtr cur =
189 xmlNewChild((xmlNodePtr) container, NULL,
190 BAD_CAST "boolean",
191 BAD_CAST (subResult->
192 boolval ? "true" : ""));
193 if (cur != NULL) {
194 cur->ns =
195 xmlNewNs(cur,
196 BAD_CAST
197 "http://exslt.org/common",
198 BAD_CAST "exsl");
199 xmlXPathNodeSetAddUnique(ret->nodesetval,
200 cur);
202 xsltExtensionInstructionResultRegister(tctxt, ret);
204 break;
205 case XPATH_NUMBER:
206 if (container != NULL) {
207 xmlChar *val =
208 xmlXPathCastNumberToString(subResult->
209 floatval);
210 xmlNodePtr cur =
211 xmlNewChild((xmlNodePtr) container, NULL,
212 BAD_CAST "number", val);
213 if (val != NULL)
214 xmlFree(val);
216 if (cur != NULL) {
217 cur->ns =
218 xmlNewNs(cur,
219 BAD_CAST
220 "http://exslt.org/common",
221 BAD_CAST "exsl");
222 xmlXPathNodeSetAddUnique(ret->nodesetval,
223 cur);
225 xsltExtensionInstructionResultRegister(tctxt, ret);
227 break;
228 case XPATH_STRING:
229 if (container != NULL) {
230 xmlNodePtr cur =
231 xmlNewChild((xmlNodePtr) container, NULL,
232 BAD_CAST "string",
233 subResult->stringval);
234 if (cur != NULL) {
235 cur->ns =
236 xmlNewNs(cur,
237 BAD_CAST
238 "http://exslt.org/common",
239 BAD_CAST "exsl");
240 xmlXPathNodeSetAddUnique(ret->nodesetval,
241 cur);
243 xsltExtensionInstructionResultRegister(tctxt, ret);
245 break;
246 default:
247 break;
249 xmlXPathFreeObject(subResult);
253 ctxt->context->doc = oldDoc;
254 ctxt->context->node = oldNode;
255 ctxt->context->contextSize = oldContextSize;
256 ctxt->context->proximityPosition = oldProximityPosition;
259 cleanup:
260 /* restore the xpath context */
261 if (comp != NULL)
262 xmlXPathFreeCompExpr(comp);
263 if (nodeset != NULL)
264 xmlXPathFreeNodeSet(nodeset);
265 if (str != NULL)
266 xmlFree(str);
267 valuePush(ctxt, ret);
268 return;
273 * exsltDynRegister:
275 * Registers the EXSLT - Dynamic module
278 void
279 exsltDynRegister (void) {
280 xsltRegisterExtModuleFunction ((const xmlChar *) "evaluate",
281 EXSLT_DYNAMIC_NAMESPACE,
282 exsltDynEvaluateFunction);
283 xsltRegisterExtModuleFunction ((const xmlChar *) "map",
284 EXSLT_DYNAMIC_NAMESPACE,
285 exsltDynMapFunction);