Skip to content
Snippets Groups Projects
Commit 866a0e5dc96f authored by Daniel Veillard's avatar Daniel Veillard
Browse files

Continuous hacking ...

- TODO: guess what, it's growing :-(
- configure.in: setup hacking values when compiling in my
  own environment.
- libxslt/transform.c libxslt/xsltutils.[hc]: added a first
  very rudimentary version of xsl:sort
Daniel
parent 563e1383046f
No related branches found
No related tags found
No related merge requests found
Wed Jan 17 17:45:20 CET 2001 Daniel Veillard <Daniel.Veillard@imag.fr>
* TODO: guess what, it's growing :-(
* configure.in: setup hacking values when compiling in my
own environment.
* libxslt/transform.c libxslt/xsltutils.[hc]: added a first
very rudimentary version of xsl:sort
Wed Jan 17 14:25:25 CET 2001 Daniel Veillard <Daniel.Veillard@imag.fr> Wed Jan 17 14:25:25 CET 2001 Daniel Veillard <Daniel.Veillard@imag.fr>
* TODO: more stuff * TODO: more stuff
......
...@@ -34,3 +34,9 @@ ...@@ -34,3 +34,9 @@
Support Attribute value templates: Support Attribute value templates:
-> starts to be urgent. Design it in flexible ways but try to optimize -> starts to be urgent. Design it in flexible ways but try to optimize
to handle most of it at the stylesheet parse time ... to handle most of it at the stylesheet parse time ...
Sorting:
-> add support for imbricated sorts
-> add lang and case-order
-> add foreign sorting functions (interfaces ?).
...@@ -10,9 +10,9 @@ ...@@ -10,9 +10,9 @@
dnl dnl
dnl Debug for DV dnl Debug for DV
dnl dnl
if test "${LOGNAME}" = "veillard" ; then if test "${LOGNAME}" = "veillard" -a "`pwd`" = "/u/veillard/XSLT" ; then
if test "${with_mem_debug}" = "" ; then if test "${with_mem_debug}" = "" ; then
with_mem_debug="yes" with_mem_debug="yes"
fi fi
CFLAGS="-Wall -g -pedantic" CFLAGS="-Wall -g -pedantic"
fi fi
...@@ -14,8 +14,9 @@ ...@@ -14,8 +14,9 @@
if test "${with_mem_debug}" = "" ; then if test "${with_mem_debug}" = "" ; then
with_mem_debug="yes" with_mem_debug="yes"
fi fi
CFLAGS="-Wall -g -pedantic" CFLAGS="-Wall -g -pedantic"
fi fi
AC_ARG_WITH(mem_debug, [ --with-mem-debug Add the memory debugging module (off)]) AC_ARG_WITH(mem_debug, [ --with-mem-debug Add the memory debugging module (off)])
if test "$with_mem_debug" = "yes" ; then if test "$with_mem_debug" = "yes" ; then
echo Enabling memory debug support echo Enabling memory debug support
......
...@@ -559,7 +559,7 @@ ...@@ -559,7 +559,7 @@
ctxt->insert = oldInsert; ctxt->insert = oldInsert;
} else { } else {
#ifdef DEBUG_PROCESS #ifdef DEBUG_PROCESS
xsltGenericDebug(xsltGenericDebugContext, xsltGenericError(xsltGenericDebugContext,
"xsltApplyOneTemplate: found xslt:%s\n", cur->name); "xsltApplyOneTemplate: found xslt:%s\n", cur->name);
#endif #endif
TODO TODO
...@@ -715,6 +715,141 @@ ...@@ -715,6 +715,141 @@
} }
/** /**
* xsltSort:
* @ctxt: a XSLT process context
* @node: the node in the source tree.
* @inst: the xslt sort node
*
* Process the xslt sort node on the source node
*/
void
xsltSort(xsltTransformContextPtr ctxt, xmlNodePtr node,
xmlNodePtr inst) {
xmlXPathObjectPtr *results = NULL;
xmlNodeSetPtr list = NULL;
xmlXPathParserContextPtr xpathParserCtxt = NULL;
xmlChar *prop;
xmlXPathObjectPtr res, tmp;
const xmlChar *start;
int descending = 0;
int number = 0;
int len;
int i;
if ((ctxt == NULL) || (node == NULL) || (inst == NULL))
return;
list = ctxt->nodeList;
if ((list == NULL) || (list->nodeNr <= 1))
goto error; /* nothing to do */
len = list->nodeNr;
prop = xmlGetNsProp(inst, (const xmlChar *)"data-type", XSLT_NAMESPACE);
if (prop != NULL) {
if (xmlStrEqual(prop, (const xmlChar *) "text"))
number = 0;
else if (xmlStrEqual(prop, (const xmlChar *) "number"))
number = 1;
else {
xsltGenericError(xsltGenericErrorContext,
"xsltSort: no support for data-type = %s\n", prop);
goto error;
}
xmlFree(prop);
}
prop = xmlGetNsProp(inst, (const xmlChar *)"order", XSLT_NAMESPACE);
if (prop != NULL) {
if (xmlStrEqual(prop, (const xmlChar *) "ascending"))
descending = 0;
else if (xmlStrEqual(prop, (const xmlChar *) "descending"))
descending = 1;
else {
xsltGenericError(xsltGenericErrorContext,
"xsltSort: invalid value %s for order\n", prop);
goto error;
}
xmlFree(prop);
}
/* TODO: xsl:sort lang attribute */
/* TODO: xsl:sort order attribute */
/* TODO: xsl:sort case-order attribute */
prop = xmlGetNsProp(inst, (const xmlChar *)"select", XSLT_NAMESPACE);
if (prop == NULL) {
xsltGenericError(xsltGenericErrorContext,
"xsltSort: select is not defined\n");
return;
}
xpathParserCtxt = xmlXPathNewParserContext(prop, ctxt->xpathCtxt);
if (xpathParserCtxt == NULL)
goto error;
results = xmlMalloc(len * sizeof(xmlXPathObjectPtr));
if (results == NULL) {
xsltGenericError(xsltGenericErrorContext,
"xsltSort: memory allocation failure\n");
goto error;
}
start = xpathParserCtxt->cur;
for (i = 0;i < len;i++) {
xpathParserCtxt->cur = start;
node = ctxt->node = list->nodeTab[i];
ctxt->xpathCtxt->proximityPosition = i + 1;
valuePush(xpathParserCtxt, xmlXPathNewNodeSet(node));
xmlXPathEvalExpr(xpathParserCtxt);
xmlXPathStringFunction(xpathParserCtxt, 1);
if (number)
xmlXPathNumberFunction(xpathParserCtxt, 1);
res = valuePop(xpathParserCtxt);
do {
tmp = valuePop(xpathParserCtxt);
if (tmp != NULL) {
xmlXPathFreeObject(tmp);
}
} while (tmp != NULL);
if (res != NULL) {
if (number) {
if (res->type == XPATH_NUMBER) {
results[i] = res;
} else {
#ifdef DEBUG_PROCESS
xsltGenericDebug(xsltGenericDebugContext,
"xsltSort: select didn't evaluate to a number\n");
#endif
results[i] = NULL;
}
} else {
if (res->type == XPATH_STRING) {
results[i] = res;
} else {
#ifdef DEBUG_PROCESS
xsltGenericDebug(xsltGenericDebugContext,
"xsltSort: select didn't evaluate to a string\n");
#endif
results[i] = NULL;
}
}
}
}
xsltSortFunction(list, &results[0], descending, number);
error:
if (xpathParserCtxt != NULL)
xmlXPathFreeParserContext(xpathParserCtxt);
if (prop != NULL)
xmlFree(prop);
if (results != NULL) {
for (i = 0;i < len;i++)
xmlXPathFreeObject(results[i]);
xmlFree(results);
}
}
/**
* xsltForEach: * xsltForEach:
* @ctxt: a XSLT process context * @ctxt: a XSLT process context
* @node: the node in the source tree. * @node: the node in the source tree.
...@@ -782,11 +917,9 @@ ...@@ -782,11 +917,9 @@
xsltGenericDebug(xsltGenericDebugContext, xsltGenericDebug(xsltGenericDebugContext,
"xsltForEach: select evaluate to %d nodes\n", list->nodeNr); "xsltForEach: select evaluate to %d nodes\n", list->nodeNr);
#endif #endif
/* TODO: handle and skip the xsl:sort */
replacement = inst->children;
oldlist = ctxt->nodeList; oldlist = ctxt->nodeList;
ctxt->nodeList = list; ctxt->nodeList = list;
oldContextSize = ctxt->xpathCtxt->contextSize; oldContextSize = ctxt->xpathCtxt->contextSize;
oldProximityPosition = ctxt->xpathCtxt->proximityPosition; oldProximityPosition = ctxt->xpathCtxt->proximityPosition;
ctxt->xpathCtxt->contextSize = list->nodeNr; ctxt->xpathCtxt->contextSize = list->nodeNr;
...@@ -787,9 +920,19 @@ ...@@ -787,9 +920,19 @@
oldlist = ctxt->nodeList; oldlist = ctxt->nodeList;
ctxt->nodeList = list; ctxt->nodeList = list;
oldContextSize = ctxt->xpathCtxt->contextSize; oldContextSize = ctxt->xpathCtxt->contextSize;
oldProximityPosition = ctxt->xpathCtxt->proximityPosition; oldProximityPosition = ctxt->xpathCtxt->proximityPosition;
ctxt->xpathCtxt->contextSize = list->nodeNr; ctxt->xpathCtxt->contextSize = list->nodeNr;
/*
* handle and skip the xsl:sort
*/
replacement = inst->children;
while (IS_XSLT_ELEM(replacement) && (IS_XSLT_NAME(replacement, "sort"))) {
xsltSort(ctxt, node, replacement);
replacement = replacement->next;
}
for (i = 0;i < list->nodeNr;i++) { for (i = 0;i < list->nodeNr;i++) {
ctxt->node = list->nodeTab[i]; ctxt->node = list->nodeTab[i];
ctxt->xpathCtxt->proximityPosition = i + 1; ctxt->xpathCtxt->proximityPosition = i + 1;
......
...@@ -118,3 +118,59 @@ ...@@ -118,3 +118,59 @@
xsltGenericDebug = xsltGenericDebugDefaultFunc; xsltGenericDebug = xsltGenericDebugDefaultFunc;
} }
/************************************************************************
* *
* Sorting *
* *
************************************************************************/
/**
* xsltSortFunction:
* @list: the node set
* @results: the results
* @descending: direction of order
* @number: the type of the result
*
* reorder the current node list @list accordingly to the values
* present in the array of results @results
*/
void
xsltSortFunction(xmlNodeSetPtr list, xmlXPathObjectPtr *results,
int descending, int number) {
int i, j;
int len, tst;
xmlNodePtr node;
xmlXPathObjectPtr tmp;
if ((list == NULL) || (results == NULL))
return;
len = list->nodeNr;
if (len <= 1)
return;
/* TODO: sort is really not optimized, does it needs to ? */
for (i = 0;i < len -1;i++) {
for (j = i + 1; j < len; j++) {
if (results[i] == NULL)
tst = 0;
else if (results[j] == NULL)
tst = 1;
else if (number) {
tst = (results[i]->floatval > results[j]->floatval);
if (descending)
tst = !tst;
} else {
tst = xmlStrcmp(results[i]->stringval, results[j]->stringval);
if (descending)
tst = !tst;
}
if (tst) {
tmp = results[i];
results[i] = results[j];
results[j] = tmp;
node = list->nodeTab[i];
list->nodeTab[i] = list->nodeTab[j];
list->nodeTab[j] = node;
}
}
}
}
...@@ -37,7 +37,8 @@ ...@@ -37,7 +37,8 @@
__FILE__, __LINE__); __FILE__, __LINE__);
#define IS_XSLT_ELEM(n) \ #define IS_XSLT_ELEM(n) \
((n)->ns != NULL) && (xmlStrEqual((n)->ns->href, XSLT_NAMESPACE)) (((n) != NULL) && ((n)->ns != NULL) && \
(xmlStrEqual((n)->ns->href, XSLT_NAMESPACE)))
#define IS_XSLT_NAME(n, val) \ #define IS_XSLT_NAME(n, val) \
(xmlStrEqual((n)->name, (const xmlChar *) (val))) (xmlStrEqual((n)->name, (const xmlChar *) (val)))
...@@ -55,6 +56,15 @@ ...@@ -55,6 +56,15 @@
xmlGenericErrorFunc handler); xmlGenericErrorFunc handler);
void xsltSetGenericDebugFunc (void *ctx, void xsltSetGenericDebugFunc (void *ctx,
xmlGenericErrorFunc handler); xmlGenericErrorFunc handler);
/*
* Sorting ... this is definitely a temporary interface !
*/
void xsltSortFunction (xmlNodeSetPtr list,
xmlXPathObjectPtr *results,
int descending,
int number);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment