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