| #define IN_LIBEXSLT |
| #include "libexslt/libexslt.h" |
| |
| #if defined(WIN32) && !defined (__CYGWIN__) && (!__MINGW32__) |
| #include <win32config.h> |
| #else |
| #include "config.h" |
| #endif |
| |
| #include <libxml/tree.h> |
| #include <libxml/xpath.h> |
| #include <libxml/xpathInternals.h> |
| |
| #include <libxslt/xsltutils.h> |
| #include <libxslt/xsltInternals.h> |
| #include <libxslt/extensions.h> |
| |
| #include "exslt.h" |
| |
| /** |
| * exsltSetsDifferenceFunction: |
| * @ctxt: an XPath parser context |
| * @nargs: the number of arguments |
| * |
| * Wraps #xmlXPathDifference for use by the XPath processor |
| */ |
| static void |
| exsltSetsDifferenceFunction (xmlXPathParserContextPtr ctxt, int nargs) { |
| xmlNodeSetPtr arg1, arg2, ret; |
| |
| if (nargs != 2) { |
| xmlXPathSetArityError(ctxt); |
| return; |
| } |
| |
| arg2 = xmlXPathPopNodeSet(ctxt); |
| if (xmlXPathCheckError(ctxt)) { |
| xmlXPathSetTypeError(ctxt); |
| return; |
| } |
| |
| arg1 = xmlXPathPopNodeSet(ctxt); |
| if (xmlXPathCheckError(ctxt)) { |
| xmlXPathSetTypeError(ctxt); |
| return; |
| } |
| |
| ret = xmlXPathDifference(arg1, arg2); |
| |
| if (ret != arg1) |
| xmlXPathFreeNodeSet(arg1); |
| xmlXPathFreeNodeSet(arg2); |
| |
| xmlXPathReturnNodeSet(ctxt, ret); |
| } |
| |
| /** |
| * exsltSetsIntersectionFunction: |
| * @ctxt: an XPath parser context |
| * @nargs: the number of arguments |
| * |
| * Wraps #xmlXPathIntersection for use by the XPath processor |
| */ |
| static void |
| exsltSetsIntersectionFunction (xmlXPathParserContextPtr ctxt, int nargs) { |
| xmlNodeSetPtr arg1, arg2, ret; |
| |
| if (nargs != 2) { |
| xmlXPathSetArityError(ctxt); |
| return; |
| } |
| |
| arg2 = xmlXPathPopNodeSet(ctxt); |
| if (xmlXPathCheckError(ctxt)) { |
| xmlXPathSetTypeError(ctxt); |
| return; |
| } |
| |
| arg1 = xmlXPathPopNodeSet(ctxt); |
| if (xmlXPathCheckError(ctxt)) { |
| xmlXPathSetTypeError(ctxt); |
| return; |
| } |
| |
| ret = xmlXPathIntersection(arg1, arg2); |
| |
| xmlXPathFreeNodeSet(arg1); |
| xmlXPathFreeNodeSet(arg2); |
| |
| xmlXPathReturnNodeSet(ctxt, ret); |
| } |
| |
| /** |
| * exsltSetsDistinctFunction: |
| * @ctxt: an XPath parser context |
| * @nargs: the number of arguments |
| * |
| * Wraps #xmlXPathDistinct for use by the XPath processor |
| */ |
| static void |
| exsltSetsDistinctFunction (xmlXPathParserContextPtr ctxt, int nargs) { |
| xmlXPathObjectPtr obj; |
| xmlNodeSetPtr ns, ret; |
| int boolval = 0; |
| void *user = NULL; |
| |
| if (nargs != 1) { |
| xmlXPathSetArityError(ctxt); |
| return; |
| } |
| |
| if (ctxt->value != NULL) { |
| boolval = ctxt->value->boolval; |
| user = ctxt->value->user; |
| ctxt->value->boolval = 0; |
| ctxt->value->user = NULL; |
| } |
| ns = xmlXPathPopNodeSet(ctxt); |
| if (xmlXPathCheckError(ctxt)) |
| return; |
| |
| /* !!! must be sorted !!! */ |
| ret = xmlXPathDistinctSorted(ns); |
| |
| if (ret != ns) |
| xmlXPathFreeNodeSet(ns); |
| |
| obj = xmlXPathWrapNodeSet(ret); |
| obj->user = user; |
| obj->boolval = boolval; |
| valuePush((ctxt), obj); |
| } |
| |
| /** |
| * exsltSetsHasSameNodesFunction: |
| * @ctxt: an XPath parser context |
| * @nargs: the number of arguments |
| * |
| * Wraps #xmlXPathHasSameNodes for use by the XPath processor |
| */ |
| static void |
| exsltSetsHasSameNodesFunction (xmlXPathParserContextPtr ctxt, |
| int nargs) { |
| xmlNodeSetPtr arg1, arg2; |
| int ret; |
| |
| if (nargs != 2) { |
| xmlXPathSetArityError(ctxt); |
| return; |
| } |
| |
| arg2 = xmlXPathPopNodeSet(ctxt); |
| if (xmlXPathCheckError(ctxt)) { |
| xmlXPathSetTypeError(ctxt); |
| return; |
| } |
| |
| arg1 = xmlXPathPopNodeSet(ctxt); |
| if (xmlXPathCheckError(ctxt)) { |
| xmlXPathSetTypeError(ctxt); |
| return; |
| } |
| |
| ret = xmlXPathHasSameNodes(arg1, arg2); |
| |
| xmlXPathFreeNodeSet(arg1); |
| xmlXPathFreeNodeSet(arg2); |
| |
| xmlXPathReturnBoolean(ctxt, ret); |
| } |
| |
| /** |
| * exsltSetsLeadingFunction: |
| * @ctxt: an XPath parser context |
| * @nargs: the number of arguments |
| * |
| * Wraps #xmlXPathLeading for use by the XPath processor |
| */ |
| static void |
| exsltSetsLeadingFunction (xmlXPathParserContextPtr ctxt, int nargs) { |
| xmlNodeSetPtr arg1, arg2, ret; |
| |
| if (nargs != 2) { |
| xmlXPathSetArityError(ctxt); |
| return; |
| } |
| |
| arg2 = xmlXPathPopNodeSet(ctxt); |
| if (xmlXPathCheckError(ctxt)) { |
| xmlXPathSetTypeError(ctxt); |
| return; |
| } |
| |
| arg1 = xmlXPathPopNodeSet(ctxt); |
| if (xmlXPathCheckError(ctxt)) { |
| xmlXPathSetTypeError(ctxt); |
| return; |
| } |
| |
| /* If the second node set is empty, then the first node set is |
| * returned. |
| */ |
| if (xmlXPathNodeSetIsEmpty(arg2)) { |
| xmlXPathReturnNodeSet(ctxt, arg1); |
| |
| xmlXPathFreeNodeSet(arg2); |
| |
| return; |
| } |
| /* !!! must be sorted */ |
| ret = xmlXPathNodeLeadingSorted(arg1, xmlXPathNodeSetItem(arg2, 0)); |
| |
| xmlXPathFreeNodeSet(arg1); |
| xmlXPathFreeNodeSet(arg2); |
| |
| xmlXPathReturnNodeSet(ctxt, ret); |
| } |
| |
| /** |
| * exsltSetsTrailingFunction: |
| * @ctxt: an XPath parser context |
| * @nargs: the number of arguments |
| * |
| * Wraps #xmlXPathTrailing for use by the XPath processor |
| */ |
| static void |
| exsltSetsTrailingFunction (xmlXPathParserContextPtr ctxt, int nargs) { |
| xmlNodeSetPtr arg1, arg2, ret; |
| |
| if (nargs != 2) { |
| xmlXPathSetArityError(ctxt); |
| return; |
| } |
| |
| arg2 = xmlXPathPopNodeSet(ctxt); |
| if (xmlXPathCheckError(ctxt)) { |
| xmlXPathSetTypeError(ctxt); |
| return; |
| } |
| |
| arg1 = xmlXPathPopNodeSet(ctxt); |
| if (xmlXPathCheckError(ctxt)) { |
| xmlXPathSetTypeError(ctxt); |
| return; |
| } |
| |
| /* If the second node set is empty, then the first node set is |
| * returned. |
| */ |
| if (xmlXPathNodeSetIsEmpty(arg2)) { |
| xmlXPathReturnNodeSet(ctxt, arg1); |
| |
| xmlXPathFreeNodeSet(arg2); |
| |
| return; |
| } |
| /* !!! mist be sorted */ |
| ret = xmlXPathNodeTrailingSorted(arg1, xmlXPathNodeSetItem(arg2, 0)); |
| |
| xmlXPathFreeNodeSet(arg1); |
| xmlXPathFreeNodeSet(arg2); |
| |
| xmlXPathReturnNodeSet(ctxt, ret); |
| } |
| |
| /** |
| * exsltSetsRegister: |
| * |
| * Registers the EXSLT - Sets module |
| */ |
| |
| void |
| exsltSetsRegister (void) { |
| xsltRegisterExtModuleFunction ((const xmlChar *) "difference", |
| EXSLT_SETS_NAMESPACE, |
| exsltSetsDifferenceFunction); |
| xsltRegisterExtModuleFunction ((const xmlChar *) "intersection", |
| EXSLT_SETS_NAMESPACE, |
| exsltSetsIntersectionFunction); |
| xsltRegisterExtModuleFunction ((const xmlChar *) "distinct", |
| EXSLT_SETS_NAMESPACE, |
| exsltSetsDistinctFunction); |
| xsltRegisterExtModuleFunction ((const xmlChar *) "has-same-node", |
| EXSLT_SETS_NAMESPACE, |
| exsltSetsHasSameNodesFunction); |
| xsltRegisterExtModuleFunction ((const xmlChar *) "leading", |
| EXSLT_SETS_NAMESPACE, |
| exsltSetsLeadingFunction); |
| xsltRegisterExtModuleFunction ((const xmlChar *) "trailing", |
| EXSLT_SETS_NAMESPACE, |
| exsltSetsTrailingFunction); |
| } |
| |
| /** |
| * exsltSetsXpathCtxtRegister: |
| * |
| * Registers the EXSLT - Sets module for use outside XSLT |
| */ |
| int |
| exsltSetsXpathCtxtRegister (xmlXPathContextPtr ctxt, const xmlChar *prefix) |
| { |
| if (ctxt |
| && prefix |
| && !xmlXPathRegisterNs(ctxt, |
| prefix, |
| (const xmlChar *) EXSLT_SETS_NAMESPACE) |
| && !xmlXPathRegisterFuncNS(ctxt, |
| (const xmlChar *) "difference", |
| (const xmlChar *) EXSLT_SETS_NAMESPACE, |
| exsltSetsDifferenceFunction) |
| && !xmlXPathRegisterFuncNS(ctxt, |
| (const xmlChar *) "intersection", |
| (const xmlChar *) EXSLT_SETS_NAMESPACE, |
| exsltSetsIntersectionFunction) |
| && !xmlXPathRegisterFuncNS(ctxt, |
| (const xmlChar *) "distinct", |
| (const xmlChar *) EXSLT_SETS_NAMESPACE, |
| exsltSetsDistinctFunction) |
| && !xmlXPathRegisterFuncNS(ctxt, |
| (const xmlChar *) "has-same-node", |
| (const xmlChar *) EXSLT_SETS_NAMESPACE, |
| exsltSetsHasSameNodesFunction) |
| && !xmlXPathRegisterFuncNS(ctxt, |
| (const xmlChar *) "leading", |
| (const xmlChar *) EXSLT_SETS_NAMESPACE, |
| exsltSetsLeadingFunction) |
| && !xmlXPathRegisterFuncNS(ctxt, |
| (const xmlChar *) "trailing", |
| (const xmlChar *) EXSLT_SETS_NAMESPACE, |
| exsltSetsTrailingFunction)) { |
| return 0; |
| } |
| return -1; |
| } |