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
)) {
117 xmlXPathSetTypeError(ctxt
);
121 nodeset
= xmlXPathPopNodeSet(ctxt
);
122 if (xmlXPathCheckError(ctxt
)) {
123 xmlXPathSetTypeError(ctxt
);
126 if (str
== NULL
|| !xmlStrlen(str
) || !(comp
= xmlXPathCompile(str
))) {
128 xmlXPathFreeNodeSet(nodeset
);
131 valuePush(ctxt
, xmlXPathNewNodeSet(NULL
));
135 ret
= xmlXPathNewNodeSet(NULL
);
137 xsltGenericError(xsltGenericErrorContext
,
138 "exsltDynMapFunction: ret == NULL\n");
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
);
153 xsltTransformError(xsltXPathGetTransformContext(ctxt
), NULL
, NULL
,
154 "dyn:map : internal error tctxt == NULL\n");
157 container
= xsltCreateRVT(tctxt
);
158 if (container
== NULL
) {
159 xsltTransformError(tctxt
, NULL
, NULL
,
160 "dyn:map : internal error container == NULL\n");
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
) {
179 if (subResult
->nodesetval
!= NULL
)
180 for (j
= 0; j
< subResult
->nodesetval
->nodeNr
;
182 xmlXPathNodeSetAdd(ret
->nodesetval
,
183 subResult
->nodesetval
->
187 if (container
!= NULL
) {
189 xmlNewChild((xmlNodePtr
) container
, NULL
,
191 BAD_CAST (subResult
->
192 boolval
? "true" : ""));
197 "http://exslt.org/common",
199 xmlXPathNodeSetAddUnique(ret
->nodesetval
,
202 xsltExtensionInstructionResultRegister(tctxt
, ret
);
206 if (container
!= NULL
) {
208 xmlXPathCastNumberToString(subResult
->
211 xmlNewChild((xmlNodePtr
) container
, NULL
,
212 BAD_CAST
"number", val
);
220 "http://exslt.org/common",
222 xmlXPathNodeSetAddUnique(ret
->nodesetval
,
225 xsltExtensionInstructionResultRegister(tctxt
, ret
);
229 if (container
!= NULL
) {
231 xmlNewChild((xmlNodePtr
) container
, NULL
,
233 subResult
->stringval
);
238 "http://exslt.org/common",
240 xmlXPathNodeSetAddUnique(ret
->nodesetval
,
243 xsltExtensionInstructionResultRegister(tctxt
, ret
);
249 xmlXPathFreeObject(subResult
);
253 ctxt
->context
->doc
= oldDoc
;
254 ctxt
->context
->node
= oldNode
;
255 ctxt
->context
->contextSize
= oldContextSize
;
256 ctxt
->context
->proximityPosition
= oldProximityPosition
;
260 /* restore the xpath context */
262 xmlXPathFreeCompExpr(comp
);
264 xmlXPathFreeNodeSet(nodeset
);
267 valuePush(ctxt
, ret
);
275 * Registers the EXSLT - Dynamic module
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
);