mirror of
https://gitlab.gnome.org/GNOME/libxslt
synced 2025-11-08 11:02:18 +03:00
* 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.
271 lines
5.9 KiB
C
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);
|
|
}
|