1
0
mirror of https://gitlab.gnome.org/GNOME/libxslt synced 2025-11-08 11:02:18 +03:00
Files
libxslt/libexslt/sets.c
Thomas Broyer cbb27d0555 fixed bugs in exsltTrailingFunction and exsltLeadingFunction when passing
* libexslt/sets.c: fixed bugs in exsltTrailingFunction and
	  exsltLeadingFunction when passing an empty node-set as the
	  second argument
	* libxslt/functions.[ch]: gave priority to context-level functions
	  over extension module functions. This allows a function declared
	  with a func:function element to override an extension module
	  function for example. This is a bit hackish...
	* tests/exslt/sets/{lead,trail}ing.1.out: fixed errors. The result
	  values didn't conform to the expected values. This is a bug in
	  the EXSLT official use cases.
2001-07-31 23:38:57 +00:00

271 lines
5.9 KiB
C

#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) {
xmlNodeSetPtr ns, ret;
if (nargs != 1) {
xmlXPathSetArityError(ctxt);
return;
}
ns = xmlXPathPopNodeSet(ctxt);
if (xmlXPathCheckError(ctxt))
return;
/* !!! must be sorted !!! */
ret = xmlXPathDistinctSorted(ns);
xmlXPathFreeNodeSet(ns);
xmlXPathReturnNodeSet(ctxt, ret);
}
/**
* 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);
}
/**
* exsltCommonRegister:
*
* 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);
}