[xslt] Patch to implement date:sum(node-set)



LibXSLT developers (esp. Daniel Veillard and Charles Bozeman),

This patch to libxslt 1.1.5 implements the date:sum function as
specified in http://exslt.org/date/functions/sum/
Please provide feedback, or apply it to the source.

Thanks,

Derek Poon


--- libxslt-1.1.5/libexslt/date.c.datesum	2004-03-05 11:58:29.000000000 +0100
+++ libxslt-1.1.5/libexslt/date.c	2004-09-22 14:17:34.610735640 +0200
@@ -2665,6 +2665,56 @@
 }
 
 /**
+ * exsltDateSum:
+ * @ns:        set of nodes to be summed as durations
+ *
+ * Implements the date:sum (node-set) function which returns
+ * the duration resulting from adding all of the durations in the node set.
+ * Each node is a string in the format defined for xs:duration
+ * in [3.2.6 duration] of [XML Schema Part 2: Datatypes]. If any
+ * argument is not in this format, the function returns an empty string
+ * (''). 
+ * The return value is a string in the format defined for xs:duration
+ * in [3.2.6 duration] of [XML Schema Part 2: Datatypes]. 
+ * The durations can usually be added by summing the numbers given for
+ * each of the components in the durations. However, if the durations
+ * are differently signed, then this sometimes results in durations
+ * that are impossible to express in this syntax (e.g. 'P1M' + '-P1D').
+ * In these cases, the function returns an empty string (''). 
+ *
+ * Returns duration string or NULL.
+ */
+static xmlChar *
+exsltDateSum (xmlNodeSetPtr ns) {
+    exsltDateValPtr cumul, oldcumul, xdur;
+    xmlChar *ret, *xstr;
+    int i;
+
+    cumul = exsltDateCreateDate(XS_DURATION);
+    if (cumul == NULL)
+	return NULL;
+
+    if (ns != NULL) {
+	for (i = 0; i < ns->nodeNr; i++) {
+	    xstr = xmlXPathCastNodeToString(ns->nodeTab[i]);
+	    xdur = exsltDateParseDuration(xstr);
+	    if (xdur == NULL) {
+		exsltDateFreeDate(cumul);
+		return NULL;
+	    }
+
+	    oldcumul = cumul;
+	    cumul = _exsltDateAddDuration(oldcumul, xdur);
+	    exsltDateFreeDate(oldcumul);
+	}
+    }
+
+    ret = exsltDateFormatDuration(&(cumul->value.dur));
+    exsltDateFreeDate(cumul);
+    return ret;
+}
+
+/**
  * exsltDateSeconds:
  * @dateTime: a date/time string
  *
@@ -3410,6 +3460,38 @@
 }
 
 /**
+ * exsltDateSumFunction:
+ * @ctxt:  an XPath parser context
+ * @nargs:  the number of arguments
+ *
+ * Wraps exsltDateSum() for use by the XPath processor.
+ */
+static void
+exsltDateSumFunction (xmlXPathParserContextPtr ctxt, int nargs) {
+    xmlNodeSetPtr ns;
+    xmlChar *ret;
+
+    if (nargs != 1) {
+	xmlXPathSetArityError(ctxt);
+	return;
+    }
+
+    ns = xmlXPathPopNodeSet(ctxt);
+    if (xmlXPathCheckError(ctxt)) {
+	xmlXPathSetTypeError(ctxt);
+	return;
+    }
+
+    ret = exsltDateSum(ns);
+    xmlXPathFreeNodeSet(ns);
+
+    if (ret == NULL)
+	xmlXPathReturnEmptyString(ctxt);
+    else
+    	xmlXPathReturnString(ctxt, ret);
+}
+
+/**
  * exsltDateDifferenceFunction:
  * @ctxt:  an XPath parser context
  * @nargs:  the number of arguments
@@ -3557,6 +3639,9 @@
     xsltRegisterExtModuleFunction((const xmlChar *) "add-duration",
                             (const xmlChar *) EXSLT_DATE_NAMESPACE,
                             exsltDateAddDurationFunction);
+    xsltRegisterExtModuleFunction((const xmlChar *) "sum",
+                            (const xmlChar *) EXSLT_DATE_NAMESPACE,
+                            exsltDateSumFunction);
     xsltRegisterExtModuleFunction((const xmlChar *) "difference",
                             (const xmlChar *) EXSLT_DATE_NAMESPACE,
                             exsltDateDifferenceFunction);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]