[xslt] [patch] implement exslt date:sum
- From: joel <jreed ddiworld com>
- To: xslt gnome org
- Subject: [xslt] [patch] implement exslt date:sum
- Date: Wed, 4 Aug 2004 15:57:21 -0400
This patch implements "date:sum"
per http://www.exslt.org/date/functions/sum/index.html
Its largely based on code from AddDuration and math.c for
extension functions using node sets.
Comments appreciated!
jr
example xsl:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:date="http://exslt.org/dates-and-times"
extension-element-prefixes="date">
<xsl:template match="editor">
sum=<xsl:value-of select="date:sum(plaintext/date)"/>
</xsl:template>
</xsl:stylesheet>
with xml file:
<?xml version="1.0" encoding="iso-8859-1"?>
<editor>
<plaintext>
<date>P0Y0M2DT0H4M5.0S</date>
<date>P0Y0M2DT0H2M6.0S</date>
</plaintext>
</editor>
produces:
sum=P4DT6M11S
Index: libexslt/date.c
===================================================================
RCS file: /cvs/gnome/libxslt/libexslt/date.c,v
retrieving revision 1.25
diff -u -r1.25 date.c
--- libexslt/date.c 16 May 2004 22:09:35 -0000 1.25
+++ libexslt/date.c 4 Aug 2004 19:51:52 -0000
@@ -2672,6 +2672,99 @@
}
/**
+ * exsltDateSumFunction:
+ * @ns: a node set of duration strings
+ *
+ * The date:sum function adds a set of durations together.
+ * The string values of the nodes in the node set passed as an argument
+ * are interpreted as durations and added together as if using the
+ * date:add-duration function. (from exslt.org)
+ *
+ * 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 void
+exsltDateSumFunction (xmlXPathParserContextPtr ctxt, int nargs)
+{
+ xmlNodeSetPtr ns;
+ void *user = NULL;
+ xmlChar *tmp;
+ exsltDateValPtr x, total;
+ xmlChar *ret;
+ long carry;
+ int i;
+
+ if (nargs != 1) {
+ xmlXPathSetArityError(ctxt);
+ return;
+ }
+
+ /* We need to delay the freeing of value->user */
+ if ((ctxt->value != NULL) && ctxt->value->boolval != 0) {
+ user = ctxt->value->user;
+ ctxt->value->boolval = 0;
+ ctxt->value->user = NULL;
+ }
+
+ ns = xmlXPathPopNodeSet(ctxt);
+ if (xmlXPathCheckError(ctxt))
+ return;
+
+ if ((ns == NULL) || (ns->nodeNr == 0))
+ return;
+
+ total = exsltDateCreateDate(XS_DURATION);
+
+ for (i = 0; i < ns->nodeNr; i++) {
+
+ tmp = xmlXPathCastNodeToString(ns->nodeTab[i]);
+ if (tmp == NULL)
+ return;
+
+ x = exsltDateParseDuration(tmp);
+ if (x == NULL) {
+ xmlFree(tmp);
+ return;
+ }
+
+ /* months */
+ total->value.dur.mon += x->value.dur.mon;
+
+ /* seconds */
+ total->value.dur.sec += x->value.dur.sec;
+ carry = (long)FQUOTIENT(total->value.dur.sec, SECS_PER_DAY);
+ if (total->value.dur.sec != 0.0) {
+ total->value.dur.sec = MODULO(total->value.dur.sec, SECS_PER_DAY);
+ }
+
+ /* days */
+ total->value.dur.day += x->value.dur.day + carry;
+
+ exsltDateFreeDate(x);
+ xmlFree(tmp);
+ }
+
+ ret = exsltDateFormatDuration(&(total->value.dur));
+ exsltDateFreeDate(total);
+
+ xmlXPathFreeNodeSet(ns);
+ if (user != NULL)
+ xmlFreeNodeList((xmlNodePtr)user);
+
+ if (ret == NULL)
+ xmlXPathReturnEmptyString(ctxt);
+ else
+ xmlXPathReturnString(ctxt, ret);
+}
+
+/**
* exsltDateSeconds:
* @dateTime: a date/time string
*
@@ -3496,78 +3589,81 @@
void
exsltDateRegister(void)
{
+ xsltRegisterExtModuleFunction((const xmlChar *) "add",
+ (const xmlChar *) EXSLT_DATE_NAMESPACE,
+ exsltDateAddFunction);
+ xsltRegisterExtModuleFunction((const xmlChar *) "add-duration",
+ (const xmlChar *) EXSLT_DATE_NAMESPACE,
+ exsltDateAddDurationFunction);
+ xsltRegisterExtModuleFunction((const xmlChar *) "date",
+ (const xmlChar *) EXSLT_DATE_NAMESPACE,
+ exsltDateDateFunction);
#ifdef WITH_TIME
xsltRegisterExtModuleFunction((const xmlChar *) "date-time",
(const xmlChar *) EXSLT_DATE_NAMESPACE,
exsltDateDateTimeFunction);
#endif
- xsltRegisterExtModuleFunction((const xmlChar *) "date",
- (const xmlChar *) EXSLT_DATE_NAMESPACE,
- exsltDateDateFunction);
- xsltRegisterExtModuleFunction((const xmlChar *) "time",
- (const xmlChar *) EXSLT_DATE_NAMESPACE,
- exsltDateTimeFunction);
- xsltRegisterExtModuleFunction((const xmlChar *) "year",
- (const xmlChar *) EXSLT_DATE_NAMESPACE,
- exsltDateYearFunction);
- xsltRegisterExtModuleFunction((const xmlChar *) "leap-year",
- (const xmlChar *) EXSLT_DATE_NAMESPACE,
- exsltDateLeapYearFunction);
- xsltRegisterExtModuleFunction((const xmlChar *) "month-in-year",
- (const xmlChar *) EXSLT_DATE_NAMESPACE,
- exsltDateMonthInYearFunction);
- xsltRegisterExtModuleFunction((const xmlChar *) "month-name",
- (const xmlChar *) EXSLT_DATE_NAMESPACE,
- exsltDateMonthNameFunction);
- xsltRegisterExtModuleFunction((const xmlChar *) "month-abbreviation",
- (const xmlChar *) EXSLT_DATE_NAMESPACE,
- exsltDateMonthAbbreviationFunction);
- xsltRegisterExtModuleFunction((const xmlChar *) "week-in-year",
- (const xmlChar *) EXSLT_DATE_NAMESPACE,
- exsltDateWeekInYearFunction);
- xsltRegisterExtModuleFunction((const xmlChar *) "week-in-month",
- (const xmlChar *) EXSLT_DATE_NAMESPACE,
- exsltDateWeekInMonthFunction);
- xsltRegisterExtModuleFunction((const xmlChar *) "day-in-year",
- (const xmlChar *) EXSLT_DATE_NAMESPACE,
- exsltDateDayInYearFunction);
+ xsltRegisterExtModuleFunction((const xmlChar *) "day-abbreviation",
+ (const xmlChar *) EXSLT_DATE_NAMESPACE,
+ exsltDateDayAbbreviationFunction);
xsltRegisterExtModuleFunction((const xmlChar *) "day-in-month",
(const xmlChar *) EXSLT_DATE_NAMESPACE,
exsltDateDayInMonthFunction);
- xsltRegisterExtModuleFunction((const xmlChar *) "day-of-week-in-month",
- (const xmlChar *) EXSLT_DATE_NAMESPACE,
- exsltDateDayOfWeekInMonthFunction);
xsltRegisterExtModuleFunction((const xmlChar *) "day-in-week",
(const xmlChar *) EXSLT_DATE_NAMESPACE,
exsltDateDayInWeekFunction);
+ xsltRegisterExtModuleFunction((const xmlChar *) "day-in-year",
+ (const xmlChar *) EXSLT_DATE_NAMESPACE,
+ exsltDateDayInYearFunction);
xsltRegisterExtModuleFunction((const xmlChar *) "day-name",
(const xmlChar *) EXSLT_DATE_NAMESPACE,
exsltDateDayNameFunction);
- xsltRegisterExtModuleFunction((const xmlChar *) "day-abbreviation",
+ xsltRegisterExtModuleFunction((const xmlChar *) "day-of-week-in-month",
(const xmlChar *) EXSLT_DATE_NAMESPACE,
- exsltDateDayAbbreviationFunction);
+ exsltDateDayOfWeekInMonthFunction);
+ xsltRegisterExtModuleFunction((const xmlChar *) "difference",
+ (const xmlChar *) EXSLT_DATE_NAMESPACE,
+ exsltDateDifferenceFunction);
+ xsltRegisterExtModuleFunction((const xmlChar *) "duration",
+ (const xmlChar *) EXSLT_DATE_NAMESPACE,
+ exsltDateDurationFunction);
xsltRegisterExtModuleFunction((const xmlChar *) "hour-in-day",
(const xmlChar *) EXSLT_DATE_NAMESPACE,
exsltDateHourInDayFunction);
+ xsltRegisterExtModuleFunction((const xmlChar *) "leap-year",
+ (const xmlChar *) EXSLT_DATE_NAMESPACE,
+ exsltDateLeapYearFunction);
xsltRegisterExtModuleFunction((const xmlChar *) "minute-in-hour",
(const xmlChar *) EXSLT_DATE_NAMESPACE,
exsltDateMinuteInHourFunction);
+ xsltRegisterExtModuleFunction((const xmlChar *) "month-abbreviation",
+ (const xmlChar *) EXSLT_DATE_NAMESPACE,
+ exsltDateMonthAbbreviationFunction);
+ xsltRegisterExtModuleFunction((const xmlChar *) "month-in-year",
+ (const xmlChar *) EXSLT_DATE_NAMESPACE,
+ exsltDateMonthInYearFunction);
+ xsltRegisterExtModuleFunction((const xmlChar *) "month-name",
+ (const xmlChar *) EXSLT_DATE_NAMESPACE,
+ exsltDateMonthNameFunction);
xsltRegisterExtModuleFunction((const xmlChar *) "second-in-minute",
(const xmlChar *) EXSLT_DATE_NAMESPACE,
exsltDateSecondInMinuteFunction);
xsltRegisterExtModuleFunction((const xmlChar *) "seconds",
(const xmlChar *) EXSLT_DATE_NAMESPACE,
exsltDateSecondsFunction);
- xsltRegisterExtModuleFunction((const xmlChar *) "add",
+ xsltRegisterExtModuleFunction((const xmlChar *) "sum",
(const xmlChar *) EXSLT_DATE_NAMESPACE,
- exsltDateAddFunction);
- xsltRegisterExtModuleFunction((const xmlChar *) "add-duration",
- (const xmlChar *) EXSLT_DATE_NAMESPACE,
- exsltDateAddDurationFunction);
- xsltRegisterExtModuleFunction((const xmlChar *) "difference",
- (const xmlChar *) EXSLT_DATE_NAMESPACE,
- exsltDateDifferenceFunction);
- xsltRegisterExtModuleFunction((const xmlChar *) "duration",
- (const xmlChar *) EXSLT_DATE_NAMESPACE,
- exsltDateDurationFunction);
+ exsltDateSumFunction);
+ xsltRegisterExtModuleFunction((const xmlChar *) "time",
+ (const xmlChar *) EXSLT_DATE_NAMESPACE,
+ exsltDateTimeFunction);
+ xsltRegisterExtModuleFunction((const xmlChar *) "week-in-month",
+ (const xmlChar *) EXSLT_DATE_NAMESPACE,
+ exsltDateWeekInMonthFunction);
+ xsltRegisterExtModuleFunction((const xmlChar *) "week-in-year",
+ (const xmlChar *) EXSLT_DATE_NAMESPACE,
+ exsltDateWeekInYearFunction);
+ xsltRegisterExtModuleFunction((const xmlChar *) "year",
+ (const xmlChar *) EXSLT_DATE_NAMESPACE,
+ exsltDateYearFunction);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]