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 */ 27static void 28exsltSetsDifferenceFunction (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 */ 64static void 65exsltSetsIntersectionFunction (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 */ 100static void 101exsltSetsDistinctFunction (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 */ 141static void 142exsltSetsHasSameNodesFunction (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 */ 179static void 180exsltSetsLeadingFunction (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 */ 226static void 227exsltSetsTrailingFunction (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 272void 273exsltSetsRegister (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 */ 299int 300exsltSetsXpathCtxtRegister (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