summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Veillard <veillard@src.gnome.org>2001-01-17 16:47:36 +0000
committerDaniel Veillard <veillard@src.gnome.org>2001-01-17 16:47:36 +0000
commit72698cec5af4011028af68ec8dac334d9a1a0a3d (patch)
tree7002a8a53894ffee6c17697dff6bdb64c1e7ae5c
parent52862c898778e5602e1f4c5a45926a9db98c3df6 (diff)
downloadlibxslt-72698cec5af4011028af68ec8dac334d9a1a0a3d.tar.gz
libxslt-72698cec5af4011028af68ec8dac334d9a1a0a3d.tar.bz2
libxslt-72698cec5af4011028af68ec8dac334d9a1a0a3d.zip
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
-rw-r--r--ChangeLog8
-rw-r--r--TODO6
-rw-r--r--configure.in3
-rw-r--r--libxslt/transform.c149
-rw-r--r--libxslt/xsltutils.c56
-rw-r--r--libxslt/xsltutils.h12
6 files changed, 229 insertions, 5 deletions
diff --git a/ChangeLog b/ChangeLog
index 6b7d64a4..0a06ccc9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+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>
* TODO: more stuff
diff --git a/TODO b/TODO
index 7b3cd001..b9552aa7 100644
--- a/TODO
+++ b/TODO
@@ -34,3 +34,9 @@ Error handling:
Support Attribute value templates:
-> starts to be urgent. Design it in flexible ways but try to optimize
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 ?).
+
diff --git a/configure.in b/configure.in
index d506a875..a812342e 100644
--- a/configure.in
+++ b/configure.in
@@ -10,12 +10,13 @@ AM_MAINTAINER_MODE
dnl
dnl Debug for DV
dnl
-if test "${LOGNAME}" = "veillard" ; then
+if test "${LOGNAME}" = "veillard" -a "`pwd`" = "/u/veillard/XSLT" ; then
if test "${with_mem_debug}" = "" ; then
with_mem_debug="yes"
fi
CFLAGS="-Wall -g -pedantic"
fi
+
AC_ARG_WITH(mem_debug, [ --with-mem-debug Add the memory debugging module (off)])
if test "$with_mem_debug" = "yes" ; then
echo Enabling memory debug support
diff --git a/libxslt/transform.c b/libxslt/transform.c
index 0c15d130..849795c3 100644
--- a/libxslt/transform.c
+++ b/libxslt/transform.c
@@ -559,7 +559,7 @@ xsltApplyOneTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node,
ctxt->insert = oldInsert;
} else {
#ifdef DEBUG_PROCESS
- xsltGenericDebug(xsltGenericDebugContext,
+ xsltGenericError(xsltGenericDebugContext,
"xsltApplyOneTemplate: found xslt:%s\n", cur->name);
#endif
TODO
@@ -715,6 +715,141 @@ error:
}
/**
+ * 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:
* @ctxt: a XSLT process context
* @node: the node in the source tree.
@@ -782,14 +917,22 @@ xsltForEach(xsltTransformContextPtr ctxt, xmlNodePtr node,
xsltGenericDebug(xsltGenericDebugContext,
"xsltForEach: select evaluate to %d nodes\n", list->nodeNr);
#endif
- /* TODO: handle and skip the xsl:sort */
- replacement = inst->children;
oldlist = ctxt->nodeList;
ctxt->nodeList = list;
oldContextSize = ctxt->xpathCtxt->contextSize;
oldProximityPosition = ctxt->xpathCtxt->proximityPosition;
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++) {
ctxt->node = list->nodeTab[i];
ctxt->xpathCtxt->proximityPosition = i + 1;
diff --git a/libxslt/xsltutils.c b/libxslt/xsltutils.c
index ee9ae3bf..ddfddfe5 100644
--- a/libxslt/xsltutils.c
+++ b/libxslt/xsltutils.c
@@ -118,3 +118,59 @@ xsltSetGenericDebugFunc(void *ctx, xmlGenericErrorFunc handler) {
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;
+ }
+ }
+ }
+}
diff --git a/libxslt/xsltutils.h b/libxslt/xsltutils.h
index 7994127e..44dbbf2d 100644
--- a/libxslt/xsltutils.h
+++ b/libxslt/xsltutils.h
@@ -37,7 +37,8 @@ void xmlXPathBooleanFunction(xmlXPathParserContextPtr ctxt, int nargs);
__FILE__, __LINE__);
#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) \
(xmlStrEqual((n)->name, (const xmlChar *) (val)))
@@ -55,6 +56,15 @@ void xsltSetGenericErrorFunc (void *ctx,
xmlGenericErrorFunc handler);
void xsltSetGenericDebugFunc (void *ctx,
xmlGenericErrorFunc handler);
+
+/*
+ * Sorting ... this is definitely a temporary interface !
+ */
+
+void xsltSortFunction (xmlNodeSetPtr list,
+ xmlXPathObjectPtr *results,
+ int descending,
+ int number);
#ifdef __cplusplus
}
#endif