• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #define IN_LIBEXSLT
2 #include "libexslt/libexslt.h"
3 
4 #if defined(WIN32) && !defined (__CYGWIN__) && (!__MINGW32__)
5 #include <win32config.h>
6 #else
7 #include "config.h"
8 #endif
9 
10 #include <libxml/tree.h>
11 #include <libxml/xpath.h>
12 #include <libxml/xpathInternals.h>
13 
14 #include <libxslt/xsltutils.h>
15 #include <libxslt/xsltInternals.h>
16 #include <libxslt/extensions.h>
17 
18 #include "exslt.h"
19 
20 /**
21  * exsltSetsDifferenceFunction:
22  * @ctxt:  an XPath parser context
23  * @nargs:  the number of arguments
24  *
25  * Wraps #xmlXPathDifference for use by the XPath processor
26  */
27 static void
exsltSetsDifferenceFunction(xmlXPathParserContextPtr ctxt,int nargs)28 exsltSetsDifferenceFunction (xmlXPathParserContextPtr ctxt, int nargs) {
29     xmlNodeSetPtr arg1, arg2, ret;
30 
31     if (nargs != 2) {
32 	xmlXPathSetArityError(ctxt);
33 	return;
34     }
35 
36     arg2 = xmlXPathPopNodeSet(ctxt);
37     if (xmlXPathCheckError(ctxt)) {
38 	xmlXPathSetTypeError(ctxt);
39 	return;
40     }
41 
42     arg1 = xmlXPathPopNodeSet(ctxt);
43     if (xmlXPathCheckError(ctxt)) {
44 	xmlXPathSetTypeError(ctxt);
45 	return;
46     }
47 
48     ret = xmlXPathDifference(arg1, arg2);
49 
50     if (ret != arg1)
51 	xmlXPathFreeNodeSet(arg1);
52     xmlXPathFreeNodeSet(arg2);
53 
54     xmlXPathReturnNodeSet(ctxt, ret);
55 }
56 
57 /**
58  * exsltSetsIntersectionFunction:
59  * @ctxt:  an XPath parser context
60  * @nargs:  the number of arguments
61  *
62  * Wraps #xmlXPathIntersection for use by the XPath processor
63  */
64 static void
exsltSetsIntersectionFunction(xmlXPathParserContextPtr ctxt,int nargs)65 exsltSetsIntersectionFunction (xmlXPathParserContextPtr ctxt, int nargs) {
66     xmlNodeSetPtr arg1, arg2, ret;
67 
68     if (nargs != 2) {
69 	xmlXPathSetArityError(ctxt);
70 	return;
71     }
72 
73     arg2 = xmlXPathPopNodeSet(ctxt);
74     if (xmlXPathCheckError(ctxt)) {
75 	xmlXPathSetTypeError(ctxt);
76 	return;
77     }
78 
79     arg1 = xmlXPathPopNodeSet(ctxt);
80     if (xmlXPathCheckError(ctxt)) {
81 	xmlXPathSetTypeError(ctxt);
82 	return;
83     }
84 
85     ret = xmlXPathIntersection(arg1, arg2);
86 
87     xmlXPathFreeNodeSet(arg1);
88     xmlXPathFreeNodeSet(arg2);
89 
90     xmlXPathReturnNodeSet(ctxt, ret);
91 }
92 
93 /**
94  * exsltSetsDistinctFunction:
95  * @ctxt:  an XPath parser context
96  * @nargs:  the number of arguments
97  *
98  * Wraps #xmlXPathDistinct for use by the XPath processor
99  */
100 static void
exsltSetsDistinctFunction(xmlXPathParserContextPtr ctxt,int nargs)101 exsltSetsDistinctFunction (xmlXPathParserContextPtr ctxt, int nargs) {
102     xmlXPathObjectPtr obj;
103     xmlNodeSetPtr ns, ret;
104     int boolval = 0;
105     void *user = NULL;
106 
107     if (nargs != 1) {
108 	xmlXPathSetArityError(ctxt);
109 	return;
110     }
111 
112     if (ctxt->value != NULL) {
113         boolval = ctxt->value->boolval;
114 	user = ctxt->value->user;
115 	ctxt->value->boolval = 0;
116 	ctxt->value->user = NULL;
117     }
118     ns = xmlXPathPopNodeSet(ctxt);
119     if (xmlXPathCheckError(ctxt))
120 	return;
121 
122     /* !!! must be sorted !!! */
123     ret = xmlXPathDistinctSorted(ns);
124 
125 	if (ret != ns)
126 		xmlXPathFreeNodeSet(ns);
127 
128     obj = xmlXPathWrapNodeSet(ret);
129     obj->user = user;
130     obj->boolval = boolval;
131     valuePush((ctxt), obj);
132 }
133 
134 /**
135  * exsltSetsHasSameNodesFunction:
136  * @ctxt:  an XPath parser context
137  * @nargs:  the number of arguments
138  *
139  * Wraps #xmlXPathHasSameNodes for use by the XPath processor
140  */
141 static void
exsltSetsHasSameNodesFunction(xmlXPathParserContextPtr ctxt,int nargs)142 exsltSetsHasSameNodesFunction (xmlXPathParserContextPtr ctxt,
143 			      int nargs) {
144     xmlNodeSetPtr arg1, arg2;
145     int ret;
146 
147     if (nargs != 2) {
148 	xmlXPathSetArityError(ctxt);
149 	return;
150     }
151 
152     arg2 = xmlXPathPopNodeSet(ctxt);
153     if (xmlXPathCheckError(ctxt)) {
154 	xmlXPathSetTypeError(ctxt);
155 	return;
156     }
157 
158     arg1 = xmlXPathPopNodeSet(ctxt);
159     if (xmlXPathCheckError(ctxt)) {
160 	xmlXPathSetTypeError(ctxt);
161 	return;
162     }
163 
164     ret = xmlXPathHasSameNodes(arg1, arg2);
165 
166     xmlXPathFreeNodeSet(arg1);
167     xmlXPathFreeNodeSet(arg2);
168 
169     xmlXPathReturnBoolean(ctxt, ret);
170 }
171 
172 /**
173  * exsltSetsLeadingFunction:
174  * @ctxt:  an XPath parser context
175  * @nargs:  the number of arguments
176  *
177  * Wraps #xmlXPathLeading for use by the XPath processor
178  */
179 static void
exsltSetsLeadingFunction(xmlXPathParserContextPtr ctxt,int nargs)180 exsltSetsLeadingFunction (xmlXPathParserContextPtr ctxt, int nargs) {
181     xmlNodeSetPtr arg1, arg2, ret;
182 
183     if (nargs != 2) {
184 	xmlXPathSetArityError(ctxt);
185 	return;
186     }
187 
188     arg2 = xmlXPathPopNodeSet(ctxt);
189     if (xmlXPathCheckError(ctxt)) {
190 	xmlXPathSetTypeError(ctxt);
191 	return;
192     }
193 
194     arg1 = xmlXPathPopNodeSet(ctxt);
195     if (xmlXPathCheckError(ctxt)) {
196 	xmlXPathSetTypeError(ctxt);
197 	return;
198     }
199 
200     /*  If the second node set is empty, then the first node set is
201      * returned.
202      */
203     if (xmlXPathNodeSetIsEmpty(arg2)) {
204 	xmlXPathReturnNodeSet(ctxt, arg1);
205 
206 	xmlXPathFreeNodeSet(arg2);
207 
208 	return;
209     }
210     /* !!! must be sorted */
211     ret = xmlXPathNodeLeadingSorted(arg1, xmlXPathNodeSetItem(arg2, 0));
212 
213     xmlXPathFreeNodeSet(arg1);
214     xmlXPathFreeNodeSet(arg2);
215 
216     xmlXPathReturnNodeSet(ctxt, ret);
217 }
218 
219 /**
220  * exsltSetsTrailingFunction:
221  * @ctxt:  an XPath parser context
222  * @nargs:  the number of arguments
223  *
224  * Wraps #xmlXPathTrailing for use by the XPath processor
225  */
226 static void
exsltSetsTrailingFunction(xmlXPathParserContextPtr ctxt,int nargs)227 exsltSetsTrailingFunction (xmlXPathParserContextPtr ctxt, int nargs) {
228     xmlNodeSetPtr arg1, arg2, ret;
229 
230     if (nargs != 2) {
231 	xmlXPathSetArityError(ctxt);
232 	return;
233     }
234 
235     arg2 = xmlXPathPopNodeSet(ctxt);
236     if (xmlXPathCheckError(ctxt)) {
237 	xmlXPathSetTypeError(ctxt);
238 	return;
239     }
240 
241     arg1 = xmlXPathPopNodeSet(ctxt);
242     if (xmlXPathCheckError(ctxt)) {
243 	xmlXPathSetTypeError(ctxt);
244 	return;
245     }
246 
247     /*  If the second node set is empty, then the first node set is
248      * returned.
249      */
250     if (xmlXPathNodeSetIsEmpty(arg2)) {
251 	xmlXPathReturnNodeSet(ctxt, arg1);
252 
253 	xmlXPathFreeNodeSet(arg2);
254 
255 	return;
256     }
257     /* !!! mist be sorted */
258     ret = xmlXPathNodeTrailingSorted(arg1, xmlXPathNodeSetItem(arg2, 0));
259 
260     xmlXPathFreeNodeSet(arg1);
261     xmlXPathFreeNodeSet(arg2);
262 
263     xmlXPathReturnNodeSet(ctxt, ret);
264 }
265 
266 /**
267  * exsltSetsRegister:
268  *
269  * Registers the EXSLT - Sets module
270  */
271 
272 void
exsltSetsRegister(void)273 exsltSetsRegister (void) {
274     xsltRegisterExtModuleFunction ((const xmlChar *) "difference",
275 				   EXSLT_SETS_NAMESPACE,
276 				   exsltSetsDifferenceFunction);
277     xsltRegisterExtModuleFunction ((const xmlChar *) "intersection",
278 				   EXSLT_SETS_NAMESPACE,
279 				   exsltSetsIntersectionFunction);
280     xsltRegisterExtModuleFunction ((const xmlChar *) "distinct",
281 				   EXSLT_SETS_NAMESPACE,
282 				   exsltSetsDistinctFunction);
283     xsltRegisterExtModuleFunction ((const xmlChar *) "has-same-node",
284 				   EXSLT_SETS_NAMESPACE,
285 				   exsltSetsHasSameNodesFunction);
286     xsltRegisterExtModuleFunction ((const xmlChar *) "leading",
287 				   EXSLT_SETS_NAMESPACE,
288 				   exsltSetsLeadingFunction);
289     xsltRegisterExtModuleFunction ((const xmlChar *) "trailing",
290 				   EXSLT_SETS_NAMESPACE,
291 				   exsltSetsTrailingFunction);
292 }
293 
294 /**
295  * exsltSetsXpathCtxtRegister:
296  *
297  * Registers the EXSLT - Sets module for use outside XSLT
298  */
299 int
exsltSetsXpathCtxtRegister(xmlXPathContextPtr ctxt,const xmlChar * prefix)300 exsltSetsXpathCtxtRegister (xmlXPathContextPtr ctxt, const xmlChar *prefix)
301 {
302     if (ctxt
303         && prefix
304         && !xmlXPathRegisterNs(ctxt,
305                                prefix,
306                                (const xmlChar *) EXSLT_SETS_NAMESPACE)
307         && !xmlXPathRegisterFuncNS(ctxt,
308                                    (const xmlChar *) "difference",
309                                    (const xmlChar *) EXSLT_SETS_NAMESPACE,
310                                    exsltSetsDifferenceFunction)
311         && !xmlXPathRegisterFuncNS(ctxt,
312                                    (const xmlChar *) "intersection",
313                                    (const xmlChar *) EXSLT_SETS_NAMESPACE,
314                                    exsltSetsIntersectionFunction)
315         && !xmlXPathRegisterFuncNS(ctxt,
316                                    (const xmlChar *) "distinct",
317                                    (const xmlChar *) EXSLT_SETS_NAMESPACE,
318                                    exsltSetsDistinctFunction)
319         && !xmlXPathRegisterFuncNS(ctxt,
320                                    (const xmlChar *) "has-same-node",
321                                    (const xmlChar *) EXSLT_SETS_NAMESPACE,
322                                    exsltSetsHasSameNodesFunction)
323         && !xmlXPathRegisterFuncNS(ctxt,
324                                    (const xmlChar *) "leading",
325                                    (const xmlChar *) EXSLT_SETS_NAMESPACE,
326                                    exsltSetsLeadingFunction)
327         && !xmlXPathRegisterFuncNS(ctxt,
328                                    (const xmlChar *) "trailing",
329                                    (const xmlChar *) EXSLT_SETS_NAMESPACE,
330                                    exsltSetsTrailingFunction)) {
331         return 0;
332     }
333     return -1;
334 }
335