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