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 = reinterpret_cast<char const *>(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 : OUString aString(reinterpret_cast<char*>(pString), strlen(reinterpret_cast<char*>(pString)), RTL_TEXTENCODING_UTF8);
96 0 : if (aString.equalsIgnoreAsciiCase("true") ||
97 0 : aString.equalsIgnoreAsciiCase("1"))
98 0 : xmlXPathReturnTrue(ctxt);
99 0 : else if (aString.equalsIgnoreAsciiCase("false") ||
100 0 : aString.equalsIgnoreAsciiCase("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 : for (int i = 0; i < xmlXPathNodeSetGetLength(pNodeSet); i++)
157 : {
158 0 : double nNumber = xmlXPathCastNodeToNumber(xmlXPathNodeSetItem(pNodeSet, i));
159 0 : if (xmlXPathIsNaN(nNumber))
160 : {
161 0 : xmlXPathReturnNumber(ctxt, xmlXPathNAN);
162 0 : return;
163 : }
164 0 : if (i == 0)
165 0 : nMinimum = nNumber;
166 0 : else if (nNumber < nMinimum)
167 0 : nMinimum = nNumber;
168 : }
169 0 : xmlXPathReturnNumber(ctxt, nMinimum);
170 : }
171 :
172 0 : void xforms_maxFunction(xmlXPathParserContextPtr ctxt, int nargs)
173 : {
174 0 : if (nargs != 1) XP_ERROR(XPATH_INVALID_ARITY);
175 0 : xmlNodeSetPtr pNodeSet = xmlXPathPopNodeSet(ctxt);
176 0 : if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE);
177 0 : double nMaximum = 0;
178 0 : for (int i = 0; i < xmlXPathNodeSetGetLength(pNodeSet); i++)
179 : {
180 0 : double nNumber = xmlXPathCastNodeToNumber(xmlXPathNodeSetItem(pNodeSet, i));
181 0 : if (xmlXPathIsNaN(nNumber))
182 : {
183 0 : xmlXPathReturnNumber(ctxt, xmlXPathNAN);
184 0 : return;
185 : }
186 0 : if (i == 0)
187 0 : nMaximum = nNumber;
188 0 : else if (nNumber > nMaximum)
189 0 : nMaximum = nNumber;
190 : }
191 0 : xmlXPathReturnNumber(ctxt, nMaximum);
192 : }
193 0 : void xforms_countNonEmptyFunction(xmlXPathParserContextPtr ctxt, int nargs)
194 : {
195 0 : if (nargs != 1) XP_ERROR(XPATH_INVALID_ARITY);
196 0 : xmlNodeSetPtr pNodeSet = xmlXPathPopNodeSet(ctxt);
197 0 : if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE);
198 0 : sal_Int32 nNotEmpty = 0;
199 0 : for (int i = 0; i < xmlXPathNodeSetGetLength(pNodeSet); i++)
200 : {
201 0 : const xmlChar *aString = xmlXPathCastNodeToString(xmlXPathNodeSetItem(pNodeSet, i));
202 0 : if (*aString != 0) nNotEmpty++;
203 : }
204 0 : xmlXPathReturnNumber(ctxt, nNotEmpty);
205 : }
206 0 : void xforms_indexFunction(xmlXPathParserContextPtr /*ctxt*/, int /*nargs*/)
207 : {
208 : // function index takes a string argument that is the IDREF of a
209 : // 'repeat' and returns the current 1-based position of the repeat
210 : // index of the identified repeat -- see xforms/9.3.1
211 :
212 : // doc.getElementByID
213 : // (...)
214 0 : }
215 :
216 : // String Functions
217 : static const char* _version = "1.0";
218 : static const char* _conformance = "conformance";
219 0 : void xforms_propertyFunction(xmlXPathParserContextPtr ctxt, int nargs)
220 : {
221 0 : if (nargs != 1) XP_ERROR(XPATH_INVALID_ARITY);
222 0 : xmlChar* pString = xmlXPathPopString(ctxt);
223 0 : if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE);
224 0 : OUString aString(reinterpret_cast<char*>(pString), strlen(reinterpret_cast<char*>(pString)), RTL_TEXTENCODING_UTF8);
225 0 : if (aString.equalsIgnoreAsciiCase("version"))
226 0 : xmlXPathReturnString(ctxt, reinterpret_cast<xmlChar *>(const_cast<char *>(_version)));
227 0 : else if (aString.equalsIgnoreAsciiCase("conformance-level"))
228 0 : xmlXPathReturnString(ctxt, reinterpret_cast<xmlChar *>(const_cast<char *>(_conformance)));
229 : else
230 0 : xmlXPathReturnEmptyString(ctxt);
231 : }
232 :
233 : // Date and Time Functions
234 :
235 0 : static OString makeDateTimeString (const DateTime& aDateTime, bool bUTC = true)
236 : {
237 0 : OStringBuffer aDateTimeString;
238 0 : aDateTimeString.append((sal_Int32)aDateTime.GetYear());
239 0 : aDateTimeString.append("-");
240 0 : if (aDateTime.GetMonth()<10) aDateTimeString.append("0");
241 0 : aDateTimeString.append((sal_Int32)aDateTime.GetMonth());
242 0 : aDateTimeString.append("-");
243 0 : if (aDateTime.GetDay()<10) aDateTimeString.append("0");
244 0 : aDateTimeString.append((sal_Int32)aDateTime.GetDay());
245 0 : aDateTimeString.append("T");
246 0 : if (aDateTime.GetHour()<10) aDateTimeString.append("0");
247 0 : aDateTimeString.append((sal_Int32)aDateTime.GetHour());
248 0 : aDateTimeString.append(":");
249 0 : if (aDateTime.GetMin()<10) aDateTimeString.append("0");
250 0 : aDateTimeString.append((sal_Int32)aDateTime.GetMin());
251 0 : aDateTimeString.append(":");
252 0 : if (aDateTime.GetSec()<10) aDateTimeString.append("0");
253 0 : aDateTimeString.append((sal_Int32)aDateTime.GetSec());
254 0 : if (bUTC) aDateTimeString.append("Z");
255 :
256 0 : return aDateTimeString.makeStringAndClear();
257 : }
258 :
259 : // returns current system date and time in canonical xsd:dateTime
260 : // format
261 0 : void xforms_nowFunction(xmlXPathParserContextPtr ctxt, int /*nargs*/)
262 : {
263 : /*
264 : A single lexical representation, which is a subset of the lexical representations
265 : allowed by [ISO 8601], is allowed for dateTime. This lexical representation is the
266 : [ISO 8601] extended format CCYY-MM-DDThh:mm:ss where "CC" represents the century,
267 : "YY" the year, "MM" the month and "DD" the day, preceded by an optional leading "-"
268 : sign to indicate a negative number. If the sign is omitted, "+" is assumed. The letter
269 : "T" is the date/time separator and "hh", "mm", "ss" represent hour, minute and second
270 : respectively.
271 : */
272 :
273 : /*
274 : 3.2.7.2 Canonical representation
275 : The canonical representation for dateTime is defined by prohibiting certain options
276 : from the Lexical representation (par.3.2.7.1). Specifically, either the time zone must
277 : be omitted or, if present, the time zone must be Coordinated Universal tools::Time (UTC)
278 : indicated by a "Z".
279 : */
280 0 : DateTime aDateTime( DateTime::SYSTEM );
281 0 : OString aDateTimeString = makeDateTimeString(aDateTime);
282 0 : xmlChar *pString = static_cast<xmlChar*>(xmlMalloc(aDateTimeString.getLength()+1));
283 0 : strncpy(reinterpret_cast<char*>(pString), aDateTimeString.getStr(), aDateTimeString.getLength());
284 0 : pString[aDateTimeString.getLength()] = 0;
285 0 : xmlXPathReturnString(ctxt, pString);
286 0 : }
287 :
288 0 : static bool parseDateTime(const OUString& aString, DateTime& aDateTime)
289 : {
290 : // take apart a canonical literal xsd:dateTime string
291 : //CCYY-MM-DDThh:mm:ss(Z)
292 :
293 0 : OUString aDateTimeString = aString.trim();
294 :
295 : // check length
296 0 : if (aDateTimeString.getLength() < 19 || aDateTimeString.getLength() > 20)
297 0 : return false;
298 :
299 0 : sal_Int32 nDateLength = 10;
300 0 : sal_Int32 nTimeLength = 8;
301 :
302 0 : OUString aUTCString("Z");
303 :
304 0 : OUString aDateString = aDateTimeString.copy(0, nDateLength);
305 0 : OUString aTimeString = aDateTimeString.copy(nDateLength+1, nTimeLength);
306 :
307 0 : sal_Int32 nIndex = 0;
308 0 : sal_Int32 nYear = aDateString.getToken(0, '-', nIndex).toInt32();
309 0 : sal_Int32 nMonth = aDateString.getToken(0, '-', nIndex).toInt32();
310 0 : sal_Int32 nDay = aDateString.getToken(0, '-', nIndex).toInt32();
311 0 : nIndex = 0;
312 0 : sal_Int32 nHour = aTimeString.getToken(0, ':', nIndex).toInt32();
313 0 : sal_Int32 nMinute = aTimeString.getToken(0, ':', nIndex).toInt32();
314 0 : sal_Int32 nSecond = aTimeString.getToken(0, ':', nIndex).toInt32();
315 :
316 0 : Date tmpDate((sal_uInt16)nDay, (sal_uInt16)nMonth, (sal_uInt16)nYear);
317 0 : tools::Time tmpTime(nHour, nMinute, nSecond);
318 0 : DateTime tmpDateTime(tmpDate, tmpTime);
319 0 : if (aString.indexOf(aUTCString) < 0)
320 0 : tmpDateTime.ConvertToUTC();
321 :
322 0 : aDateTime = tmpDateTime;
323 :
324 0 : return true;
325 : }
326 :
327 :
328 0 : void xforms_daysFromDateFunction(xmlXPathParserContextPtr ctxt, int nargs)
329 : {
330 : // number of days from 1970-01-01 to supplied xsd:date(Time)
331 :
332 0 : if (nargs != 1) XP_ERROR(XPATH_INVALID_ARITY);
333 0 : xmlChar* pString = xmlXPathPopString(ctxt);
334 0 : if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE);
335 0 : OUString aString(reinterpret_cast<char*>(pString), strlen(reinterpret_cast<char*>(pString)), RTL_TEXTENCODING_UTF8);
336 :
337 0 : DateTime aDateTime( DateTime::EMPTY );
338 0 : if (parseDateTime(aString, aDateTime))
339 : {
340 0 : Date aReferenceDate(1, 1, 1970);
341 0 : sal_Int32 nDays = aDateTime - aReferenceDate;
342 0 : xmlXPathReturnNumber(ctxt, nDays);
343 : }
344 : else
345 0 : xmlXPathReturnNumber(ctxt, xmlXPathNAN);
346 :
347 :
348 : }
349 :
350 :
351 0 : void xforms_secondsFromDateTimeFunction(xmlXPathParserContextPtr ctxt, int nargs)
352 : {
353 : // number of seconds from 1970-01-01T00:00:00Z to supplied xsd:date(Time)
354 :
355 0 : if (nargs != 1) XP_ERROR(XPATH_INVALID_ARITY);
356 0 : xmlChar* pString = xmlXPathPopString(ctxt);
357 0 : if (xmlXPathCheckError(ctxt)) XP_ERROR(XPATH_INVALID_TYPE);
358 0 : OUString aString(reinterpret_cast<char*>(pString), strlen(reinterpret_cast<char*>(pString)), RTL_TEXTENCODING_UTF8);
359 :
360 0 : DateTime aDateTime( DateTime::EMPTY );
361 :
362 0 : if (parseDateTime(aString, aDateTime))
363 : {
364 0 : Date aReferenceDate(1, 1, 1970);
365 0 : sal_Int32 nDays = aDateTime - aReferenceDate;
366 0 : sal_Int32 nSeconds = nDays * 24 * 60 * 60;
367 0 : nSeconds += aDateTime.GetHour() * 60 * 60;
368 0 : nSeconds += aDateTime.GetMin() * 60;
369 0 : nSeconds += aDateTime.GetSec();
370 0 : xmlXPathReturnNumber(ctxt, nSeconds);
371 : }
372 : else
373 0 : xmlXPathReturnNumber(ctxt, xmlXPathNAN);
374 :
375 : }
376 :
377 0 : static bool parseDuration(const xmlChar* aString, bool& bNegative, sal_Int32& nYears, sal_Int32& nMonth, sal_Int32& nDays,
378 : sal_Int32& nHours, sal_Int32& nMinutes, sal_Int32& nSeconds)
379 : {
380 0 : bool bTime = false; // in part after T
381 0 : sal_Int32 nLength = strlen(reinterpret_cast<char const *>(aString))+1;
382 0 : char *pString = static_cast<char*>(rtl_allocateMemory(nLength));
383 0 : char *pString0 = pString;
384 0 : strncpy(pString, reinterpret_cast<char const *>(aString), nLength);
385 :
386 0 : if (pString[0] == '-') {
387 0 : bNegative = true;
388 0 : pString++;
389 : }
390 :
391 0 : if (pString[0] != 'P')
392 : {
393 0 : rtl_freeMemory(pString0);
394 0 : return false;
395 : }
396 :
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 = true;
432 0 : pString = ++pToken;
433 0 : break;
434 : default:
435 0 : pToken++;
436 : }
437 : }
438 0 : rtl_freeMemory(pString0);
439 0 : return 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 : bool bNegative = 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 : bool bNegative = 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 : OUString aString(reinterpret_cast<char*>(pString), strlen(reinterpret_cast<char*>(pString)), RTL_TEXTENCODING_UTF8);
508 :
509 0 : Reference< XModel > aModel = static_cast<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 = static_cast<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: */
|