Home | History | Annotate | Download | only in libexslt
      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
     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
     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
    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
    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
    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
    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
    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
    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