2 * extra.c: Implementation of non-standard features
5 * Michael Kay "XSLT Programmer's Reference" pp 637-643
6 * The node-set() extension function
8 * See Copyright for the status of this software.
15 #ifdef WITH_XSLT_DEBUG
16 #define WITH_XSLT_DEBUG_EXTRA
19 /************************************************************************
21 * Handling of XSLT debugging *
23 ************************************************************************/
27 * @ctxt: an XSLT processing context
28 * @node: The current node
29 * @inst: the instruction in the stylesheet
30 * @comp: precomputed informations
32 * Process an debug node
35 xsltDebug(xsltTransformContextPtr ctxt
, xmlNodePtr node ATTRIBUTE_UNUSED
,
36 xmlNodePtr inst ATTRIBUTE_UNUSED
,
37 xsltStylePreCompPtr comp ATTRIBUTE_UNUSED
)
41 xsltGenericError(xsltGenericErrorContext
, "Templates:\n");
42 for (i
= 0, j
= ctxt
->templNr
- 1; ((i
< 15) && (j
>= 0)); i
++, j
--) {
43 xsltGenericError(xsltGenericErrorContext
, "#%d ", i
);
44 if (ctxt
->templTab
[j
]->name
!= NULL
)
45 xsltGenericError(xsltGenericErrorContext
, "name %s ",
46 ctxt
->templTab
[j
]->name
);
47 if (ctxt
->templTab
[j
]->match
!= NULL
)
48 xsltGenericError(xsltGenericErrorContext
, "name %s ",
49 ctxt
->templTab
[j
]->match
);
50 if (ctxt
->templTab
[j
]->mode
!= NULL
)
51 xsltGenericError(xsltGenericErrorContext
, "name %s ",
52 ctxt
->templTab
[j
]->mode
);
53 xsltGenericError(xsltGenericErrorContext
, "\n");
55 xsltGenericError(xsltGenericErrorContext
, "Variables:\n");
56 for (i
= 0, j
= ctxt
->varsNr
- 1; ((i
< 15) && (j
>= 0)); i
++, j
--) {
59 if (ctxt
->varsTab
[j
] == NULL
)
61 xsltGenericError(xsltGenericErrorContext
, "#%d\n", i
);
62 cur
= ctxt
->varsTab
[j
];
64 if (cur
->comp
== NULL
) {
65 xsltGenericError(xsltGenericErrorContext
,
67 } else if (cur
->comp
->type
== XSLT_FUNC_PARAM
) {
68 xsltGenericError(xsltGenericErrorContext
, "param ");
69 } else if (cur
->comp
->type
== XSLT_FUNC_VARIABLE
) {
70 xsltGenericError(xsltGenericErrorContext
, "var ");
72 if (cur
->name
!= NULL
)
73 xsltGenericError(xsltGenericErrorContext
, "%s ",
76 xsltGenericError(xsltGenericErrorContext
, "noname !!!!");
77 #ifdef LIBXML_DEBUG_ENABLED
78 if (cur
->value
!= NULL
) {
79 xmlXPathDebugDumpObject(stdout
, cur
->value
, 1);
81 xsltGenericError(xsltGenericErrorContext
, "NULL !!!!");
84 xsltGenericError(xsltGenericErrorContext
, "\n");
91 /************************************************************************
93 * Classic extensions as described by M. Kay *
95 ************************************************************************/
98 * xsltFunctionNodeSet:
99 * @ctxt: the XPath Parser context
100 * @nargs: the number of arguments
102 * Implement the node-set() XSLT function
103 * node-set node-set(result-tree)
105 * This function is available in libxslt, saxon or xt namespace.
108 xsltFunctionNodeSet(xmlXPathParserContextPtr ctxt
, int nargs
){
110 xsltTransformError(xsltXPathGetTransformContext(ctxt
), NULL
, NULL
,
111 "node-set() : expects one result-tree arg\n");
112 ctxt
->error
= XPATH_INVALID_ARITY
;
115 if ((ctxt
->value
== NULL
) ||
116 ((ctxt
->value
->type
!= XPATH_XSLT_TREE
) &&
117 (ctxt
->value
->type
!= XPATH_NODESET
))) {
118 xsltTransformError(xsltXPathGetTransformContext(ctxt
), NULL
, NULL
,
119 "node-set() invalid arg expecting a result tree\n");
120 ctxt
->error
= XPATH_INVALID_TYPE
;
123 if (ctxt
->value
->type
== XPATH_XSLT_TREE
) {
124 ctxt
->value
->type
= XPATH_NODESET
;
130 * Okay the following really seems unportable and since it's not
131 * part of any standard I'm not too ashamed to do this
133 #if defined(linux) || defined(__sun)
134 #if defined(HAVE_MKTIME) && defined(HAVE_LOCALTIME) && defined(HAVE_ASCTIME)
135 #define WITH_LOCALTIME
138 * xsltFunctionLocalTime:
139 * @ctxt: the XPath Parser context
140 * @nargs: the number of arguments
142 * Implement the localTime XSLT function used by NORM
143 * string localTime(???)
145 * This function is available in Norm's extension namespace
146 * Code (and comments) contributed by Norm
149 xsltFunctionLocalTime(xmlXPathParserContextPtr ctxt
, int nargs
) {
150 xmlXPathObjectPtr obj
;
160 xsltTransformError(xsltXPathGetTransformContext(ctxt
), NULL
, NULL
,
161 "localTime() : invalid number of args %d\n", nargs
);
162 ctxt
->error
= XPATH_INVALID_ARITY
;
166 obj
= valuePop(ctxt
);
168 if (obj
->type
!= XPATH_STRING
) {
169 obj
= xmlXPathConvertString(obj
);
172 valuePush(ctxt
, xmlXPathNewString((const xmlChar
*)""));
176 str
= (char *) obj
->stringval
;
179 memset(digits
, 0, sizeof(digits
));
180 strncpy(digits
, str
+7, 4);
181 field
= strtol(digits
, NULL
, 10);
182 gmt_tm
.tm_year
= field
- 1900;
184 memset(digits
, 0, sizeof(digits
));
185 strncpy(digits
, str
+12, 2);
186 field
= strtol(digits
, NULL
, 10);
187 gmt_tm
.tm_mon
= field
- 1;
189 memset(digits
, 0, sizeof(digits
));
190 strncpy(digits
, str
+15, 2);
191 field
= strtol(digits
, NULL
, 10);
192 gmt_tm
.tm_mday
= field
;
194 memset(digits
, 0, sizeof(digits
));
195 strncpy(digits
, str
+18, 2);
196 field
= strtol(digits
, NULL
, 10);
197 gmt_tm
.tm_hour
= field
;
199 memset(digits
, 0, sizeof(digits
));
200 strncpy(digits
, str
+21, 2);
201 field
= strtol(digits
, NULL
, 10);
202 gmt_tm
.tm_min
= field
;
204 memset(digits
, 0, sizeof(digits
));
205 strncpy(digits
, str
+24, 2);
206 field
= strtol(digits
, NULL
, 10);
207 gmt_tm
.tm_sec
= field
;
209 /* Now turn gmt_tm into a time. */
210 gmt
= mktime(&gmt_tm
);
214 * FIXME: it's been too long since I did manual memory management.
215 * (I swore never to do it again.) Does this introduce a memory leak?
217 local_tm
= localtime(&gmt
);
220 * Calling localtime() has the side-effect of setting timezone.
221 * After we know the timezone, we can adjust for it
223 #if !defined(__FreeBSD__)
224 lmt
= gmt
- timezone
;
225 #else /* FreeBSD DOESN'T have such side-ffect */
226 lmt
= gmt
- local_tm
->tm_gmtoff
;
229 * FIXME: it's been too long since I did manual memory management.
230 * (I swore never to do it again.) Does this introduce a memory leak?
232 local_tm
= localtime(&lmt
);
235 * Now convert local_tm back into a string. This doesn't introduce
236 * a memory leak, so says asctime(3).
239 str
= asctime(local_tm
); /* "Tue Jun 26 05:02:16 2001" */
240 /* 0123456789 123456789 123 */
242 memset(result
, 0, sizeof(result
)); /* "Thu, 26 Jun 2001" */
243 /* 0123456789 12345 */
245 strncpy(result
, str
, 20);
246 strcpy(result
+20, "???"); /* tzname doesn't work, fake it */
247 strncpy(result
+23, str
+19, 5);
249 /* Ok, now result contains the string I want to send back. */
250 valuePush(ctxt
, xmlXPathNewString((xmlChar
*)result
));
253 #endif /* linux or sun */
257 * xsltRegisterExtras:
258 * @ctxt: a XSLT process context
260 * Registers the built-in extensions. This function is deprecated, use
261 * xsltRegisterAllExtras instead.
264 xsltRegisterExtras(xsltTransformContextPtr ctxt ATTRIBUTE_UNUSED
) {
265 xsltRegisterAllExtras();
269 * xsltRegisterAllExtras:
271 * Registers the built-in extensions
274 xsltRegisterAllExtras (void) {
275 xsltRegisterExtModuleFunction((const xmlChar
*) "node-set",
276 XSLT_LIBXSLT_NAMESPACE
,
277 xsltFunctionNodeSet
);
278 xsltRegisterExtModuleFunction((const xmlChar
*) "node-set",
279 XSLT_SAXON_NAMESPACE
,
280 xsltFunctionNodeSet
);
281 xsltRegisterExtModuleFunction((const xmlChar
*) "node-set",
283 xsltFunctionNodeSet
);
284 #ifdef WITH_LOCALTIME
285 xsltRegisterExtModuleFunction((const xmlChar
*) "localTime",
286 XSLT_NORM_SAXON_NAMESPACE
,
287 xsltFunctionLocalTime
);
289 xsltRegisterExtModuleElement((const xmlChar
*) "debug",
290 XSLT_LIBXSLT_NAMESPACE
,
292 (xsltTransformFunction
) xsltDebug
);
293 xsltRegisterExtModuleElement((const xmlChar
*) "output",
294 XSLT_SAXON_NAMESPACE
,
296 (xsltTransformFunction
) xsltDocumentElem
);
297 xsltRegisterExtModuleElement((const xmlChar
*) "write",
298 XSLT_XALAN_NAMESPACE
,
300 (xsltTransformFunction
) xsltDocumentElem
);
301 xsltRegisterExtModuleElement((const xmlChar
*) "document",
304 (xsltTransformFunction
) xsltDocumentElem
);
305 xsltRegisterExtModuleElement((const xmlChar
*) "document",
308 (xsltTransformFunction
) xsltDocumentElem
);