Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 :
21 : #include <string.h>
22 : #include <sal/types.h>
23 : #include <rtl/alloc.h>
24 : #include <rtl/ustring.hxx>
25 : #include <rtl/string.hxx>
26 : #include <rtl/ustrbuf.hxx>
27 : #include <rtl/strbuf.hxx>
28 : #include <tools/date.hxx>
29 : #include <tools/time.hxx>
30 : #include <tools/datetime.hxx>
31 :
32 : #include <com/sun/star/uno/Reference.hxx>
33 : #include <com/sun/star/uno/Sequence.hxx>
34 : #include <com/sun/star/uno/Any.hxx>
35 : #include <com/sun/star/xforms/XModel.hpp>
36 : #include <com/sun/star/xml/dom/XNode.hpp>
37 : #include <com/sun/star/xml/dom/XDocument.hpp>
38 : #include <com/sun/star/lang/XUnoTunnel.hpp>
39 :
40 : #include "xpathlib.hxx"
41 :
42 : #include "extension.hxx"
43 :
44 : // C interface
45 :
46 : using namespace com::sun::star::uno;
47 : using namespace com::sun::star::xml::dom;
48 : using namespace com::sun::star::xforms;
49 : using namespace com::sun::star::lang;
50 :
51 0 : xmlXPathFunction xforms_lookupFunc(void *, const xmlChar *xname, const xmlChar *)
52 : {
53 :
54 0 : const char *name = (char *)xname;
55 0 : if (strcmp("boolean-from-string", name)==0)
56 0 : return xforms_booleanFromStringFunction;
57 0 : else if ((strcmp("if", name))==0)
58 0 : return xforms_ifFunction;
59 0 : else if ((strcmp("avg", name))==0)
60 0 : return xforms_avgFunction;
61 0 : else if ((strcmp("min", name))==0)
62 0 : return xforms_minFunction;
63 0 : else if ((strcmp("max", name))==0)
64 0 : return xforms_maxFunction;
65 0 : else if ((strcmp("count-non-empty", name))==0)
66 0 : return xforms_countNonEmptyFunction;
67 0 : else if ((strcmp("index", name))==0)
68 0 : return xforms_indexFunction;
69 0 : else if ((strcmp("property", name))==0)
70 0 : return xforms_propertyFunction;
71 0 : else if ((strcmp("now", name))==0)
72 0 : return xforms_nowFunction;
73 0 : else if ((strcmp("days-from-date", name))==0)
74 0 : return xforms_daysFromDateFunction;
75 0 : else if ((strcmp("seconds-from-dateTime", name))==0)
76 0 : return xforms_secondsFromDateTimeFunction;
77 0 : else if ((strcmp("seconds", name))==0)
78 0 : return xforms_secondsFuction;
79 0 : else if ((strcmp("months", name))==0)
80 0 : return xforms_monthsFuction;
81 0 : else if ((strcmp("instance", name))==0)
82 0 : return xforms_instanceFuction;
83 0 : else if ((strcmp("current", name))==0)
84 0 : return xforms_currentFunction;
85 : else
86 0 : return NULL;
87 : }
88 :
89 : // boolean functions
90 0 : void xforms_booleanFromStringFunction(xmlXPathParserContextPtr ctxt, int nargs)
91 : {
92 0 : if (nargs != 1) XP_ERROR(XPATH_INVALID_ARITY);
93 0 : xmlChar *pString = xmlXPathPopString(ctxt);
94 0 : if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE);
95 0 : ::rtl::OUString aString((char*)pString, strlen((char*)pString), RTL_TEXTENCODING_UTF8);
96 0 : if (aString.equalsIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("true")) ||
97 0 : aString.equalsIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("1")))
98 0 : xmlXPathReturnTrue(ctxt);
99 0 : else if (aString.equalsIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("false")) ||
100 0 : aString.equalsIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("0")))
101 0 : xmlXPathReturnFalse(ctxt);
102 : else
103 0 : XP_ERROR(XPATH_NUMBER_ERROR);
104 : }
105 :
106 0 : void xforms_ifFunction(xmlXPathParserContextPtr ctxt, int nargs)
107 : {
108 0 : if (nargs != 3) XP_ERROR(XPATH_INVALID_ARITY);
109 0 : xmlChar *s2 = xmlXPathPopString(ctxt);
110 :
111 0 : if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE);
112 0 : xmlChar *s1 = xmlXPathPopString(ctxt);
113 0 : if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE);
114 0 : bool aBool = xmlXPathPopBoolean(ctxt);
115 0 : if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE);
116 :
117 0 : if (aBool)
118 0 : xmlXPathReturnString(ctxt, s1);
119 : else
120 0 : xmlXPathReturnString(ctxt, s2);
121 :
122 : }
123 :
124 : // Number Functions
125 0 : void xforms_avgFunction(xmlXPathParserContextPtr ctxt, int nargs)
126 : {
127 : // use sum(), div() and count()
128 0 : if (nargs != 1) XP_ERROR(XPATH_INVALID_ARITY);
129 :
130 : // save nodeset
131 0 : xmlXPathObjectPtr pObject = valuePop(ctxt);
132 0 : if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE);
133 : //push back a copy
134 0 : valuePush(ctxt, xmlXPathObjectCopy(pObject));
135 : // get the Sum
136 0 : xmlXPathSumFunction(ctxt, 1);
137 0 : double nSum = xmlXPathPopNumber(ctxt);
138 : // push a copy once more
139 0 : valuePush(ctxt, xmlXPathObjectCopy(pObject));
140 0 : xmlXPathCountFunction(ctxt, 1);
141 0 : double nCount = xmlXPathPopNumber(ctxt);
142 : // push args for div()
143 0 : xmlXPathReturnNumber(ctxt, nSum);
144 0 : xmlXPathReturnNumber(ctxt, nCount);
145 0 : xmlXPathDivValues(ctxt);
146 : // the result is now on the ctxt stack
147 0 : xmlXPathFreeObject(pObject);
148 : }
149 :
150 0 : void xforms_minFunction(xmlXPathParserContextPtr ctxt, int nargs)
151 : {
152 0 : if (nargs != 1) XP_ERROR(XPATH_INVALID_ARITY);
153 0 : xmlNodeSetPtr pNodeSet = xmlXPathPopNodeSet(ctxt);
154 0 : if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE);
155 0 : double nMinimum = 0;
156 0 : double nNumber = 0;
157 0 : for (int i = 0; i < xmlXPathNodeSetGetLength(pNodeSet); i++)
158 : {
159 0 : nNumber = xmlXPathCastNodeToNumber(xmlXPathNodeSetItem(pNodeSet, i));
160 0 : if (xmlXPathIsNaN(nNumber))
161 : {
162 0 : xmlXPathReturnNumber(ctxt, xmlXPathNAN);
163 0 : return;
164 : }
165 0 : if (i == 0)
166 0 : nMinimum = nNumber;
167 0 : else if (nNumber < nMinimum)
168 0 : nMinimum = nNumber;
169 : }
170 0 : xmlXPathReturnNumber(ctxt, nMinimum);
171 : }
172 :
173 0 : void xforms_maxFunction(xmlXPathParserContextPtr ctxt, int nargs)
174 : {
175 0 : if (nargs != 1) XP_ERROR(XPATH_INVALID_ARITY);
176 0 : xmlNodeSetPtr pNodeSet = xmlXPathPopNodeSet(ctxt);
177 0 : if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE);
178 0 : double nMaximum = 0;
179 0 : double nNumber = 0;
180 0 : for (int i = 0; i < xmlXPathNodeSetGetLength(pNodeSet); i++)
181 : {
182 0 : nNumber = xmlXPathCastNodeToNumber(xmlXPathNodeSetItem(pNodeSet, i));
183 0 : if (xmlXPathIsNaN(nNumber))
184 : {
185 0 : xmlXPathReturnNumber(ctxt, xmlXPathNAN);
186 0 : return;
187 : }
188 0 : if (i == 0)
189 0 : nMaximum = nNumber;
190 0 : else if (nNumber > nMaximum)
191 0 : nMaximum = nNumber;
192 : }
193 0 : xmlXPathReturnNumber(ctxt, nMaximum);
194 : }
195 0 : void xforms_countNonEmptyFunction(xmlXPathParserContextPtr ctxt, int nargs)
196 : {
197 0 : if (nargs != 1) XP_ERROR(XPATH_INVALID_ARITY);
198 0 : xmlNodeSetPtr pNodeSet = xmlXPathPopNodeSet(ctxt);
199 0 : if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE);
200 : xmlChar *aString;
201 0 : sal_Int32 nNotEmpty = 0;
202 0 : for (int i = 0; i < xmlXPathNodeSetGetLength(pNodeSet); i++)
203 : {
204 0 : aString = xmlXPathCastNodeToString(xmlXPathNodeSetItem(pNodeSet, i));
205 0 : if (*aString != 0) nNotEmpty++;
206 : }
207 0 : xmlXPathReturnNumber(ctxt, nNotEmpty);
208 : }
209 0 : void xforms_indexFunction(xmlXPathParserContextPtr /*ctxt*/, int /*nargs*/)
210 : {
211 : // function index takes a string argument that is the IDREF of a
212 : // 'repeat' and returns the current 1-based position of the repeat
213 : // index of the identified repeat -- see xforms/9.3.1
214 :
215 : // doc.getElementByID
216 : // (...)
217 0 : }
218 :
219 : // String Functions
220 : static const char* _version = "1.0";
221 : static const char* _conformance = "conformance";
222 0 : void xforms_propertyFunction(xmlXPathParserContextPtr ctxt, int nargs)
223 : {
224 0 : if (nargs != 1) XP_ERROR(XPATH_INVALID_ARITY);
225 0 : xmlChar* pString = xmlXPathPopString(ctxt);
226 0 : if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE);
227 0 : ::rtl::OUString aString((char*)pString, strlen((char*)pString), RTL_TEXTENCODING_UTF8);
228 0 : if (aString.equalsIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("version")))
229 0 : xmlXPathReturnString(ctxt, (xmlChar*)_version);
230 0 : else if (aString.equalsIgnoreAsciiCaseAsciiL(RTL_CONSTASCII_STRINGPARAM("conformance-level")))
231 0 : xmlXPathReturnString(ctxt, (xmlChar*)_conformance);
232 : else
233 0 : xmlXPathReturnEmptyString(ctxt);
234 : }
235 :
236 : // Date and Time Functions
237 :
238 0 : static ::rtl::OString makeDateTimeString (const DateTime& aDateTime, sal_Bool bUTC = sal_True)
239 : {
240 0 : ::rtl::OStringBuffer aDateTimeString;
241 0 : aDateTimeString.append((sal_Int32)aDateTime.GetYear());
242 0 : aDateTimeString.append("-");
243 0 : if (aDateTime.GetMonth()<10) aDateTimeString.append("0");
244 0 : aDateTimeString.append((sal_Int32)aDateTime.GetMonth());
245 0 : aDateTimeString.append("-");
246 0 : if (aDateTime.GetDay()<10) aDateTimeString.append("0");
247 0 : aDateTimeString.append((sal_Int32)aDateTime.GetDay());
248 0 : aDateTimeString.append("T");
249 0 : if (aDateTime.GetHour()<10) aDateTimeString.append("0");
250 0 : aDateTimeString.append((sal_Int32)aDateTime.GetHour());
251 0 : aDateTimeString.append(":");
252 0 : if (aDateTime.GetMin()<10) aDateTimeString.append("0");
253 0 : aDateTimeString.append((sal_Int32)aDateTime.GetMin());
254 0 : aDateTimeString.append(":");
255 0 : if (aDateTime.GetSec()<10) aDateTimeString.append("0");
256 0 : aDateTimeString.append((sal_Int32)aDateTime.GetSec());
257 0 : if (bUTC) aDateTimeString.append("Z");
258 :
259 0 : return aDateTimeString.makeStringAndClear();
260 : }
261 :
262 : // returns current system date and time in canonical xsd:dateTime
263 : // format
264 0 : void xforms_nowFunction(xmlXPathParserContextPtr ctxt, int /*nargs*/)
265 : {
266 : /*
267 : A single lexical representation, which is a subset of the lexical representations
268 : allowed by [ISO 8601], is allowed for dateTime. This lexical representation is the
269 : [ISO 8601] extended format CCYY-MM-DDThh:mm:ss where "CC" represents the century,
270 : "YY" the year, "MM" the month and "DD" the day, preceded by an optional leading "-"
271 : sign to indicate a negative number. If the sign is omitted, "+" is assumed. The letter
272 : "T" is the date/time separator and "hh", "mm", "ss" represent hour, minute and second
273 : respectively.
274 : */
275 :
276 : /*
277 : 3.2.7.2 Canonical representation
278 : The canonical representation for dateTime is defined by prohibiting certain options
279 : from the Lexical representation (par.3.2.7.1). Specifically, either the time zone must
280 : be omitted or, if present, the time zone must be Coordinated Universal Time (UTC)
281 : indicated by a "Z".
282 : */
283 0 : DateTime aDateTime( DateTime::SYSTEM );
284 0 : ::rtl::OString aDateTimeString = makeDateTimeString(aDateTime);
285 0 : xmlChar *pString = static_cast<xmlChar*>(xmlMalloc(aDateTimeString.getLength()+1));
286 0 : strncpy((char*)pString, (char*)aDateTimeString.getStr(), aDateTimeString.getLength());
287 0 : pString[aDateTimeString.getLength()] = 0;
288 0 : xmlXPathReturnString(ctxt, pString);
289 0 : }
290 :
291 0 : static sal_Bool parseDateTime(const ::rtl::OUString& aString, DateTime& aDateTime)
292 : {
293 : // take apart a canonical literal xsd:dateTime string
294 : //CCYY-MM-DDThh:mm:ss(Z)
295 :
296 0 : ::rtl::OUString aDateTimeString = aString.trim();
297 :
298 : // check length
299 0 : if (aDateTimeString.getLength() < 19 || aDateTimeString.getLength() > 20)
300 0 : return sal_False;
301 :
302 0 : sal_Int32 nDateLength = 10;
303 0 : sal_Int32 nTimeLength = 8;
304 :
305 0 : ::rtl::OUString aUTCString(RTL_CONSTASCII_USTRINGPARAM("Z"));
306 :
307 0 : ::rtl::OUString aDateString = aDateTimeString.copy(0, nDateLength);
308 0 : ::rtl::OUString aTimeString = aDateTimeString.copy(nDateLength+1, nTimeLength);
309 :
310 0 : sal_Int32 nIndex = 0;
311 0 : sal_Int32 nYear = aDateString.getToken(0, '-', nIndex).toInt32();
312 0 : sal_Int32 nMonth = aDateString.getToken(0, '-', nIndex).toInt32();
313 0 : sal_Int32 nDay = aDateString.getToken(0, '-', nIndex).toInt32();
314 0 : nIndex = 0;
315 0 : sal_Int32 nHour = aTimeString.getToken(0, ':', nIndex).toInt32();
316 0 : sal_Int32 nMinute = aTimeString.getToken(0, ':', nIndex).toInt32();
317 0 : sal_Int32 nSecond = aTimeString.getToken(0, ':', nIndex).toInt32();
318 :
319 0 : Date tmpDate((sal_uInt16)nDay, (sal_uInt16)nMonth, (sal_uInt16)nYear);
320 0 : Time tmpTime(nHour, nMinute, nSecond);
321 0 : DateTime tmpDateTime(tmpDate, tmpTime);
322 0 : if (aString.indexOf(aUTCString) < 0)
323 0 : tmpDateTime.ConvertToUTC();
324 :
325 0 : aDateTime = tmpDateTime;
326 :
327 0 : return sal_True;
328 : }
329 :
330 :
331 0 : void xforms_daysFromDateFunction(xmlXPathParserContextPtr ctxt, int nargs)
332 : {
333 : // number of days from 1970-01-01 to supplied xsd:date(Time)
334 :
335 0 : if (nargs != 1) XP_ERROR(XPATH_INVALID_ARITY);
336 0 : xmlChar* pString = xmlXPathPopString(ctxt);
337 0 : if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE);
338 0 : ::rtl::OUString aString((char*)pString, strlen((char*)pString), RTL_TEXTENCODING_UTF8);
339 :
340 0 : DateTime aDateTime( DateTime::EMPTY );
341 0 : if (parseDateTime(aString, aDateTime))
342 : {
343 0 : Date aReferenceDate(1, 1, 1970);
344 0 : sal_Int32 nDays = aDateTime - aReferenceDate;
345 0 : xmlXPathReturnNumber(ctxt, nDays);
346 : }
347 : else
348 0 : xmlXPathReturnNumber(ctxt, xmlXPathNAN);
349 :
350 :
351 : }
352 :
353 :
354 0 : void xforms_secondsFromDateTimeFunction(xmlXPathParserContextPtr ctxt, int nargs)
355 : {
356 : // number of seconds from 1970-01-01T00:00:00Z to supplied xsd:date(Time)
357 :
358 0 : if (nargs != 1) XP_ERROR(XPATH_INVALID_ARITY);
359 0 : xmlChar* pString = xmlXPathPopString(ctxt);
360 0 : if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE);
361 0 : ::rtl::OUString aString((char*)pString, strlen((char*)pString), RTL_TEXTENCODING_UTF8);
362 :
363 0 : DateTime aDateTime( DateTime::EMPTY );
364 :
365 0 : if (parseDateTime(aString, aDateTime))
366 : {
367 0 : Date aReferenceDate(1, 1, 1970);
368 0 : Time aReferenceTime(0, 0, 0);
369 0 : sal_Int32 nDays = aDateTime - aReferenceDate;
370 0 : sal_Int32 nSeconds = nDays * 24 * 60 * 60;
371 0 : nSeconds += aDateTime.GetHour() * 60 * 60;
372 0 : nSeconds += aDateTime.GetMin() * 60;
373 0 : nSeconds += aDateTime.GetSec();
374 0 : xmlXPathReturnNumber(ctxt, nSeconds);
375 : }
376 : else
377 0 : xmlXPathReturnNumber(ctxt, xmlXPathNAN);
378 :
379 : }
380 :
381 0 : static sal_Bool parseDuration(const xmlChar* aString, sal_Bool& bNegative, sal_Int32& nYears, sal_Int32& nMonth, sal_Int32& nDays,
382 : sal_Int32& nHours, sal_Int32& nMinutes, sal_Int32& nSeconds)
383 : {
384 0 : sal_Bool bTime = sal_False; // in part after T
385 0 : sal_Int32 nLength = strlen((char*)aString)+1;
386 0 : char *pString = (char*)rtl_allocateMemory(nLength);
387 0 : char *pString0 = pString;
388 0 : strncpy(pString, (char*)aString, nLength);
389 :
390 0 : if (pString[0] == '-') {
391 0 : bNegative = sal_True;
392 0 : pString++;
393 : }
394 :
395 0 : if (pString[0] != 'P')
396 0 : return sal_False;
397 0 : pString++;
398 0 : char* pToken = pString;
399 0 : while(pToken[0] != 0)
400 : {
401 0 : switch(pToken[0]) {
402 : case 'Y':
403 0 : pToken[0] = 0;
404 0 : nYears = atoi(pString);
405 0 : pString = ++pToken;
406 0 : break;
407 : case 'M':
408 0 : pToken[0] = 0;
409 0 : if (!bTime)
410 0 : nMonth = atoi(pString);
411 : else
412 0 : nMinutes = atoi(pString);
413 0 : pString = ++pToken;
414 0 : break;
415 : case 'D':
416 0 : pToken[0] = 0;
417 0 : nDays = atoi(pString);
418 0 : pString = ++pToken;
419 0 : break;
420 : case 'H':
421 0 : pToken[0] = 0;
422 0 : nHours = atoi(pString);
423 0 : pString = ++pToken;
424 0 : break;
425 : case 'S':
426 0 : pToken[0] = 0;
427 0 : nSeconds = atoi(pString);
428 0 : pString = ++pToken;
429 0 : break;
430 : case 'T':
431 0 : bTime = sal_True;
432 0 : pString = ++pToken;
433 0 : break;
434 : default:
435 0 : pToken++;
436 : }
437 : }
438 0 : rtl_freeMemory(pString0);
439 0 : return sal_True;
440 : }
441 :
442 0 : void xforms_secondsFuction(xmlXPathParserContextPtr ctxt, int nargs)
443 : {
444 : // convert a xsd:duration to seconds
445 : // (-)PnYnMnDTnHnMnS
446 0 : if (nargs != 1) XP_ERROR(XPATH_INVALID_ARITY);
447 0 : xmlChar* pString = xmlXPathPopString(ctxt);
448 0 : if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE);
449 :
450 0 : sal_Bool bNegative = sal_False;
451 0 : sal_Int32 nYears = 0;
452 0 : sal_Int32 nMonths = 0;
453 0 : sal_Int32 nDays = 0;
454 0 : sal_Int32 nHours = 0;
455 0 : sal_Int32 nMinutes = 0;
456 0 : sal_Int32 nSeconds = 0;
457 :
458 0 : if (parseDuration(pString, bNegative, nYears, nMonths, nDays, nHours, nMinutes, nSeconds))
459 : {
460 0 : nSeconds += nMinutes*60;
461 0 : nSeconds += nHours*60*60;
462 0 : nSeconds += nDays*24*60*60;
463 : // year and month are ignored according to spec
464 0 : if (bNegative)
465 0 : nSeconds = 0 - nSeconds;
466 0 : xmlXPathReturnNumber(ctxt, nSeconds);
467 : }
468 : else
469 0 : xmlXPathReturnNumber(ctxt, xmlXPathNAN);
470 : }
471 :
472 0 : void xforms_monthsFuction(xmlXPathParserContextPtr ctxt, int nargs)
473 : {
474 : // convert a xsd:duration to seconds
475 : // (-)PnYnMnDTnHnMnS
476 0 : if (nargs != 1) XP_ERROR(XPATH_INVALID_ARITY);
477 0 : xmlChar* pString = xmlXPathPopString(ctxt);
478 0 : if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE);
479 :
480 0 : sal_Bool bNegative = sal_False;
481 0 : sal_Int32 nYears = 0;
482 0 : sal_Int32 nMonths = 0;
483 0 : sal_Int32 nDays = 0;
484 0 : sal_Int32 nHours = 0;
485 0 : sal_Int32 nMinutes = 0;
486 0 : sal_Int32 nSeconds = 0;
487 :
488 0 : if (parseDuration(pString, bNegative, nYears, nMonths, nDays, nHours, nMinutes, nSeconds))
489 : {
490 0 : nMonths += nYears*12;
491 : // Days, Houres, Minutes and seconds are ignored, see spec
492 0 : if (bNegative)
493 0 : nMonths = 0 - nMonths;
494 0 : xmlXPathReturnNumber(ctxt, nMonths);
495 : }
496 : else
497 0 : xmlXPathReturnNumber(ctxt, xmlXPathNAN);
498 :
499 : }
500 :
501 : // Node-set Functions
502 0 : void xforms_instanceFuction(xmlXPathParserContextPtr ctxt, int nargs)
503 : {
504 0 : if (nargs != 1) XP_ERROR(XPATH_INVALID_ARITY);
505 0 : xmlChar *pString = xmlXPathPopString(ctxt);
506 0 : if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE);
507 0 : ::rtl::OUString aString((char*)pString, strlen((char*)pString), RTL_TEXTENCODING_UTF8);
508 :
509 0 : Reference< XModel > aModel = ((CLibxml2XFormsExtension*)ctxt->context->funcLookupData)->getModel();
510 0 : if (aModel.is())
511 : {
512 0 : Reference< XDocument > aInstance = aModel->getInstanceDocument(aString);
513 0 : if (aInstance.is())
514 : {
515 : try {
516 : // xmlXPathObjectPtr xmlXPathNewNodeSet (xmlNodePtr val);
517 0 : Reference< XUnoTunnel > aTunnel(aInstance, UNO_QUERY_THROW);
518 0 : xmlNodePtr pNode = reinterpret_cast< xmlNodePtr >( aTunnel->getSomething(Sequence< sal_Int8 >()) );
519 0 : xmlXPathObjectPtr pObject = xmlXPathNewNodeSet(pNode);
520 0 : xmlXPathReturnNodeSet(ctxt, pObject->nodesetval);
521 0 : } catch (const RuntimeException&)
522 : {
523 0 : xmlXPathReturnEmptyNodeSet(ctxt);
524 : }
525 : }
526 : else
527 0 : xmlXPathReturnEmptyNodeSet(ctxt);
528 : }
529 : else
530 0 : xmlXPathReturnEmptyNodeSet(ctxt);
531 :
532 : }
533 :
534 : // Node-set Functions, XForms 1.1
535 0 : void xforms_currentFunction(xmlXPathParserContextPtr ctxt, int nargs)
536 : {
537 0 : if (nargs != 0) XP_ERROR(XPATH_INVALID_ARITY);
538 :
539 0 : Reference< XNode > aNode = ((CLibxml2XFormsExtension*)ctxt->context->funcLookupData)->getContextNode();
540 :
541 0 : if (aNode.is())
542 : {
543 : try {
544 0 : Reference< XUnoTunnel > aTunnel(aNode, UNO_QUERY_THROW);
545 0 : xmlNodePtr pNode = reinterpret_cast< xmlNodePtr >( aTunnel->getSomething(Sequence< sal_Int8 >()) );
546 0 : xmlXPathObjectPtr pObject = xmlXPathNewNodeSet(pNode);
547 0 : xmlXPathReturnNodeSet(ctxt, pObject->nodesetval);
548 : }
549 0 : catch (const RuntimeException&)
550 : {
551 0 : xmlXPathReturnEmptyNodeSet(ctxt);
552 : }
553 : }
554 : else
555 0 : xmlXPathReturnEmptyNodeSet(ctxt);
556 : }
557 :
558 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|