1 #define IN_LIBEXSLT 2 #include "libexslt/libexslt.h" 3 4 #if defined(WIN32) && !defined (__CYGWIN__) && (!__MINGW32__) 5 #include <win32config.h> 6 #else 7 #include "config.h" 8 #endif 9 10 #include <libxml/tree.h> 11 #include <libxml/xpath.h> 12 #include <libxml/xpathInternals.h> 13 #include <libxml/parser.h> 14 #include <libxml/encoding.h> 15 #include <libxml/uri.h> 16 17 #include <libxslt/xsltconfig.h> 18 #include <libxslt/xsltutils.h> 19 #include <libxslt/xsltInternals.h> 20 #include <libxslt/extensions.h> 21 22 #include "exslt.h" 23 24 /** 25 * exsltStrTokenizeFunction: 26 * @ctxt: an XPath parser context 27 * @nargs: the number of arguments 28 * 29 * Splits up a string on the characters of the delimiter string and returns a 30 * node set of token elements, each containing one token from the string. 31 */ 32 static void 33 exsltStrTokenizeFunction(xmlXPathParserContextPtr ctxt, int nargs) 34 { 35 xsltTransformContextPtr tctxt; 36 xmlChar *str, *delimiters, *cur; 37 const xmlChar *token, *delimiter; 38 xmlNodePtr node; 39 xmlDocPtr container; 40 xmlXPathObjectPtr ret = NULL; 41 int clen; 42 43 if ((nargs < 1) || (nargs > 2)) { 44 xmlXPathSetArityError(ctxt); 45 return; 46 } 47 48 if (nargs == 2) { 49 delimiters = xmlXPathPopString(ctxt); 50 if (xmlXPathCheckError(ctxt)) 51 return; 52 } else { 53 delimiters = xmlStrdup((const xmlChar *) "\t\r\n "); 54 } 55 if (delimiters == NULL) 56 return; 57 58 str = xmlXPathPopString(ctxt); 59 if (xmlXPathCheckError(ctxt) || (str == NULL)) { 60 xmlFree(delimiters); 61 return; 62 } 63 64 /* Return a result tree fragment */ 65 tctxt = xsltXPathGetTransformContext(ctxt); 66 if (tctxt == NULL) { 67 xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, 68 "exslt:tokenize : internal error tctxt == NULL\n"); 69 goto fail; 70 } 71 72 container = xsltCreateRVT(tctxt); 73 if (container != NULL) { 74 xsltRegisterLocalRVT(tctxt, container); 75 ret = xmlXPathNewNodeSet(NULL); 76 if (ret != NULL) { 77 for (cur = str, token = str; *cur != 0; cur += clen) { 78 clen = xmlUTF8Size(cur); 79 if (*delimiters == 0) { /* empty string case */ 80 xmlChar ctmp; 81 ctmp = *(cur+clen); 82 *(cur+clen) = 0; 83 node = xmlNewDocRawNode(container, NULL, 84 (const xmlChar *) "token", cur); 85 xmlAddChild((xmlNodePtr) container, node); 86 xmlXPathNodeSetAddUnique(ret->nodesetval, node); 87 *(cur+clen) = ctmp; /* restore the changed byte */ 88 token = cur + clen; 89 } else for (delimiter = delimiters; *delimiter != 0; 90 delimiter += xmlUTF8Size(delimiter)) { 91 if (!xmlUTF8Charcmp(cur, delimiter)) { 92 if (cur == token) { 93 /* discard empty tokens */ 94 token = cur + clen; 95 break; 96 } 97 *cur = 0; /* terminate the token */ 98 node = xmlNewDocRawNode(container, NULL, 99 (const xmlChar *) "token", token); 100 xmlAddChild((xmlNodePtr) container, node); 101 xmlXPathNodeSetAddUnique(ret->nodesetval, node); 102 *cur = *delimiter; /* restore the changed byte */ 103 token = cur + clen; 104 break; 105 } 106 } 107 } 108 if (token != cur) { 109 node = xmlNewDocRawNode(container, NULL, 110 (const xmlChar *) "token", token); 111 xmlAddChild((xmlNodePtr) container, node); 112 xmlXPathNodeSetAddUnique(ret->nodesetval, node); 113 } 114 /* 115 * Mark it as a function result in order to avoid garbage 116 * collecting of tree fragments 117 */ 118 xsltExtensionInstructionResultRegister(tctxt, ret); 119 } 120 } 121 122 fail: 123 if (str != NULL) 124 xmlFree(str); 125 if (delimiters != NULL) 126 xmlFree(delimiters); 127 if (ret != NULL) 128 valuePush(ctxt, ret); 129 else 130 valuePush(ctxt, xmlXPathNewNodeSet(NULL)); 131 } 132 133 /** 134 * exsltStrSplitFunction: 135 * @ctxt: an XPath parser context 136 * @nargs: the number of arguments 137 * 138 * Splits up a string on a delimiting string and returns a node set of token 139 * elements, each containing one token from the string. 140 */ 141 static void 142 exsltStrSplitFunction(xmlXPathParserContextPtr ctxt, int nargs) { 143 xsltTransformContextPtr tctxt; 144 xmlChar *str, *delimiter, *cur; 145 const xmlChar *token; 146 xmlNodePtr node; 147 xmlDocPtr container; 148 xmlXPathObjectPtr ret = NULL; 149 int delimiterLength; 150 151 if ((nargs < 1) || (nargs > 2)) { 152 xmlXPathSetArityError(ctxt); 153 return; 154 } 155 156 if (nargs == 2) { 157 delimiter = xmlXPathPopString(ctxt); 158 if (xmlXPathCheckError(ctxt)) 159 return; 160 } else { 161 delimiter = xmlStrdup((const xmlChar *) " "); 162 } 163 if (delimiter == NULL) 164 return; 165 delimiterLength = xmlStrlen (delimiter); 166 167 str = xmlXPathPopString(ctxt); 168 if (xmlXPathCheckError(ctxt) || (str == NULL)) { 169 xmlFree(delimiter); 170 return; 171 } 172 173 /* Return a result tree fragment */ 174 tctxt = xsltXPathGetTransformContext(ctxt); 175 if (tctxt == NULL) { 176 xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, 177 "exslt:tokenize : internal error tctxt == NULL\n"); 178 goto fail; 179 } 180 181 /* 182 * OPTIMIZE TODO: We are creating an xmlDoc for every split! 183 */ 184 container = xsltCreateRVT(tctxt); 185 if (container != NULL) { 186 xsltRegisterLocalRVT(tctxt, container); 187 ret = xmlXPathNewNodeSet(NULL); 188 if (ret != NULL) { 189 for (cur = str, token = str; *cur != 0; cur++) { 190 if (delimiterLength == 0) { 191 if (cur != token) { 192 xmlChar tmp = *cur; 193 *cur = 0; 194 node = xmlNewDocRawNode(container, NULL, 195 (const xmlChar *) "token", token); 196 xmlAddChild((xmlNodePtr) container, node); 197 xmlXPathNodeSetAddUnique(ret->nodesetval, node); 198 *cur = tmp; 199 token++; 200 } 201 } 202 else if (!xmlStrncasecmp(cur, delimiter, delimiterLength)) { 203 if (cur == token) { 204 /* discard empty tokens */ 205 cur = cur + delimiterLength - 1; 206 token = cur + 1; 207 continue; 208 } 209 *cur = 0; 210 node = xmlNewDocRawNode(container, NULL, 211 (const xmlChar *) "token", token); 212 xmlAddChild((xmlNodePtr) container, node); 213 xmlXPathNodeSetAddUnique(ret->nodesetval, node); 214 *cur = *delimiter; 215 cur = cur + delimiterLength - 1; 216 token = cur + 1; 217 } 218 } 219 if (token != cur) { 220 node = xmlNewDocRawNode(container, NULL, 221 (const xmlChar *) "token", token); 222 xmlAddChild((xmlNodePtr) container, node); 223 xmlXPathNodeSetAddUnique(ret->nodesetval, node); 224 } 225 /* 226 * Mark it as a function result in order to avoid garbage 227 * collecting of tree fragments 228 */ 229 xsltExtensionInstructionResultRegister(tctxt, ret); 230 } 231 } 232 233 fail: 234 if (str != NULL) 235 xmlFree(str); 236 if (delimiter != NULL) 237 xmlFree(delimiter); 238 if (ret != NULL) 239 valuePush(ctxt, ret); 240 else 241 valuePush(ctxt, xmlXPathNewNodeSet(NULL)); 242 } 243 244 /** 245 * exsltStrEncodeUriFunction: 246 * @ctxt: an XPath parser context 247 * @nargs: the number of arguments 248 * 249 * URI-Escapes a string 250 */ 251 static void 252 exsltStrEncodeUriFunction (xmlXPathParserContextPtr ctxt, int nargs) { 253 int escape_all = 1, str_len = 0; 254 xmlChar *str = NULL, *ret = NULL, *tmp; 255 256 if ((nargs < 2) || (nargs > 3)) { 257 xmlXPathSetArityError(ctxt); 258 return; 259 } 260 261 if (nargs >= 3) { 262 /* check for UTF-8 if encoding was explicitly given; 263 we don't support anything else yet */ 264 tmp = xmlXPathPopString(ctxt); 265 if (xmlUTF8Strlen(tmp) != 5 || xmlStrcmp((const xmlChar *)"UTF-8",tmp)) { 266 xmlXPathReturnEmptyString(ctxt); 267 xmlFree(tmp); 268 return; 269 } 270 xmlFree(tmp); 271 } 272 273 escape_all = xmlXPathPopBoolean(ctxt); 274 275 str = xmlXPathPopString(ctxt); 276 str_len = xmlUTF8Strlen(str); 277 278 if (str_len == 0) { 279 xmlXPathReturnEmptyString(ctxt); 280 xmlFree(str); 281 return; 282 } 283 284 ret = xmlURIEscapeStr(str,(const xmlChar *)(escape_all?"-_.!~*'()":"-_.!~*'();/?:@&=+$,[]")); 285 xmlXPathReturnString(ctxt, ret); 286 287 if (str != NULL) 288 xmlFree(str); 289 } 290 291 /** 292 * exsltStrDecodeUriFunction: 293 * @ctxt: an XPath parser context 294 * @nargs: the number of arguments 295 * 296 * reverses URI-Escaping of a string 297 */ 298 static void 299 exsltStrDecodeUriFunction (xmlXPathParserContextPtr ctxt, int nargs) { 300 int str_len = 0; 301 xmlChar *str = NULL, *ret = NULL, *tmp; 302 303 if ((nargs < 1) || (nargs > 2)) { 304 xmlXPathSetArityError(ctxt); 305 return; 306 } 307 308 if (nargs >= 2) { 309 /* check for UTF-8 if encoding was explicitly given; 310 we don't support anything else yet */ 311 tmp = xmlXPathPopString(ctxt); 312 if (xmlUTF8Strlen(tmp) != 5 || xmlStrcmp((const xmlChar *)"UTF-8",tmp)) { 313 xmlXPathReturnEmptyString(ctxt); 314 xmlFree(tmp); 315 return; 316 } 317 xmlFree(tmp); 318 } 319 320 str = xmlXPathPopString(ctxt); 321 str_len = xmlUTF8Strlen(str); 322 323 if (str_len == 0) { 324 xmlXPathReturnEmptyString(ctxt); 325 xmlFree(str); 326 return; 327 } 328 329 ret = (xmlChar *) xmlURIUnescapeString((const char *)str,0,NULL); 330 if (!xmlCheckUTF8(ret)) { 331 /* FIXME: instead of throwing away the whole URI, we should 332 only discard the invalid sequence(s). How to do that? */ 333 xmlXPathReturnEmptyString(ctxt); 334 xmlFree(str); 335 xmlFree(ret); 336 return; 337 } 338 339 xmlXPathReturnString(ctxt, ret); 340 341 if (str != NULL) 342 xmlFree(str); 343 } 344 345 /** 346 * exsltStrPaddingFunction: 347 * @ctxt: an XPath parser context 348 * @nargs: the number of arguments 349 * 350 * Creates a padding string of a certain length. 351 */ 352 static void 353 exsltStrPaddingFunction (xmlXPathParserContextPtr ctxt, int nargs) { 354 int number, str_len = 0; 355 xmlChar *str = NULL, *ret = NULL, *tmp; 356 357 if ((nargs < 1) || (nargs > 2)) { 358 xmlXPathSetArityError(ctxt); 359 return; 360 } 361 362 if (nargs == 2) { 363 str = xmlXPathPopString(ctxt); 364 str_len = xmlUTF8Strlen(str); 365 } 366 if (str_len == 0) { 367 if (str != NULL) xmlFree(str); 368 str = xmlStrdup((const xmlChar *) " "); 369 str_len = 1; 370 } 371 372 number = (int) xmlXPathPopNumber(ctxt); 373 374 if (number <= 0) { 375 xmlXPathReturnEmptyString(ctxt); 376 xmlFree(str); 377 return; 378 } 379 380 while (number >= str_len) { 381 ret = xmlStrncat(ret, str, str_len); 382 number -= str_len; 383 } 384 tmp = xmlUTF8Strndup (str, number); 385 ret = xmlStrcat(ret, tmp); 386 if (tmp != NULL) 387 xmlFree (tmp); 388 389 xmlXPathReturnString(ctxt, ret); 390 391 if (str != NULL) 392 xmlFree(str); 393 } 394 395 /** 396 * exsltStrAlignFunction: 397 * @ctxt: an XPath parser context 398 * @nargs: the number of arguments 399 * 400 * Aligns a string within another string. 401 */ 402 static void 403 exsltStrAlignFunction (xmlXPathParserContextPtr ctxt, int nargs) { 404 xmlChar *str, *padding, *alignment, *ret; 405 int str_l, padding_l; 406 407 if ((nargs < 2) || (nargs > 3)) { 408 xmlXPathSetArityError(ctxt); 409 return; 410 } 411 412 if (nargs == 3) 413 alignment = xmlXPathPopString(ctxt); 414 else 415 alignment = NULL; 416 417 padding = xmlXPathPopString(ctxt); 418 str = xmlXPathPopString(ctxt); 419 420 str_l = xmlUTF8Strlen (str); 421 padding_l = xmlUTF8Strlen (padding); 422 423 if (str_l == padding_l) { 424 xmlXPathReturnString (ctxt, str); 425 xmlFree(padding); 426 xmlFree(alignment); 427 return; 428 } 429 430 if (str_l > padding_l) { 431 ret = xmlUTF8Strndup (str, padding_l); 432 } else { 433 if (xmlStrEqual(alignment, (const xmlChar *) "right")) { 434 ret = xmlUTF8Strndup (padding, padding_l - str_l); 435 ret = xmlStrcat (ret, str); 436 } else if (xmlStrEqual(alignment, (const xmlChar *) "center")) { 437 int left = (padding_l - str_l) / 2; 438 int right_start; 439 440 ret = xmlUTF8Strndup (padding, left); 441 ret = xmlStrcat (ret, str); 442 443 right_start = xmlUTF8Strsize (padding, left + str_l); 444 ret = xmlStrcat (ret, padding + right_start); 445 } else { 446 int str_s; 447 448 str_s = xmlStrlen (str); 449 ret = xmlStrdup (str); 450 ret = xmlStrcat (ret, padding + str_s); 451 } 452 } 453 454 xmlXPathReturnString (ctxt, ret); 455 456 xmlFree(str); 457 xmlFree(padding); 458 xmlFree(alignment); 459 } 460 461 /** 462 * exsltStrConcatFunction: 463 * @ctxt: an XPath parser context 464 * @nargs: the number of arguments 465 * 466 * Takes a node set and returns the concatenation of the string values 467 * of the nodes in that node set. If the node set is empty, it 468 * returns an empty string. 469 */ 470 static void 471 exsltStrConcatFunction (xmlXPathParserContextPtr ctxt, int nargs) { 472 xmlXPathObjectPtr obj; 473 xmlChar *ret = NULL; 474 int i; 475 476 if (nargs != 1) { 477 xmlXPathSetArityError(ctxt); 478 return; 479 } 480 481 if (!xmlXPathStackIsNodeSet(ctxt)) { 482 xmlXPathSetTypeError(ctxt); 483 return; 484 } 485 486 obj = valuePop (ctxt); 487 488 if (xmlXPathNodeSetIsEmpty(obj->nodesetval)) { 489 xmlXPathReturnEmptyString(ctxt); 490 return; 491 } 492 493 for (i = 0; i < obj->nodesetval->nodeNr; i++) { 494 xmlChar *tmp; 495 tmp = xmlXPathCastNodeToString(obj->nodesetval->nodeTab[i]); 496 497 ret = xmlStrcat (ret, tmp); 498 499 xmlFree(tmp); 500 } 501 502 xmlXPathFreeObject (obj); 503 504 xmlXPathReturnString(ctxt, ret); 505 } 506 507 /** 508 * exsltStrReturnString: 509 * @ctxt: an XPath parser context 510 * @str: a string 511 * @len: length of string 512 * 513 * Returns a string as a node set. 514 */ 515 static int 516 exsltStrReturnString(xmlXPathParserContextPtr ctxt, const xmlChar *str, 517 int len) 518 { 519 xsltTransformContextPtr tctxt = xsltXPathGetTransformContext(ctxt); 520 xmlDocPtr container; 521 xmlNodePtr text_node; 522 xmlXPathObjectPtr ret; 523 524 container = xsltCreateRVT(tctxt); 525 if (container == NULL) { 526 xmlXPathSetError(ctxt, XPATH_MEMORY_ERROR); 527 return(-1); 528 } 529 xsltRegisterLocalRVT(tctxt, container); 530 531 text_node = xmlNewTextLen(str, len); 532 if (text_node == NULL) { 533 xmlXPathSetError(ctxt, XPATH_MEMORY_ERROR); 534 return(-1); 535 } 536 xmlAddChild((xmlNodePtr) container, text_node); 537 538 ret = xmlXPathNewNodeSet(text_node); 539 if (ret == NULL) { 540 xmlXPathSetError(ctxt, XPATH_MEMORY_ERROR); 541 return(-1); 542 } 543 544 xsltExtensionInstructionResultRegister(tctxt, ret); 545 valuePush(ctxt, ret); 546 547 return(0); 548 } 549 550 /** 551 * exsltStrReplaceFunction: 552 * @ctxt: an XPath parser context 553 * @nargs: the number of arguments 554 * 555 * Takes a string, and two node sets and returns the string with all strings in 556 * the first node set replaced by all strings in the second node set. 557 */ 558 static void 559 exsltStrReplaceFunction (xmlXPathParserContextPtr ctxt, int nargs) { 560 int i, i_empty, n, slen0, rlen0, *slen, *rlen; 561 void *mem = NULL; 562 const xmlChar *src, *start; 563 xmlChar *string, *search_str = NULL, *replace_str = NULL; 564 xmlChar **search, **replace; 565 xmlNodeSetPtr search_set = NULL, replace_set = NULL; 566 xmlBufferPtr buf; 567 568 if (nargs != 3) { 569 xmlXPathSetArityError(ctxt); 570 return; 571 } 572 573 /* get replace argument */ 574 575 if (!xmlXPathStackIsNodeSet(ctxt)) 576 replace_str = xmlXPathPopString(ctxt); 577 else 578 replace_set = xmlXPathPopNodeSet(ctxt); 579 580 if (xmlXPathCheckError(ctxt)) 581 goto fail_replace; 582 583 /* get search argument */ 584 585 if (!xmlXPathStackIsNodeSet(ctxt)) { 586 search_str = xmlXPathPopString(ctxt); 587 n = 1; 588 } 589 else { 590 search_set = xmlXPathPopNodeSet(ctxt); 591 n = search_set != NULL ? search_set->nodeNr : 0; 592 } 593 594 if (xmlXPathCheckError(ctxt)) 595 goto fail_search; 596 597 /* get string argument */ 598 599 string = xmlXPathPopString(ctxt); 600 if (xmlXPathCheckError(ctxt)) 601 goto fail_string; 602 603 /* check for empty search node list */ 604 605 if (n <= 0) { 606 exsltStrReturnString(ctxt, string, xmlStrlen(string)); 607 goto done_empty_search; 608 } 609 610 /* allocate memory for string pointer and length arrays */ 611 612 if (n == 1) { 613 search = &search_str; 614 replace = &replace_str; 615 slen = &slen0; 616 rlen = &rlen0; 617 } 618 else { 619 mem = xmlMalloc(2 * n * (sizeof(const xmlChar *) + sizeof(int))); 620 if (mem == NULL) { 621 xmlXPathSetError(ctxt, XPATH_MEMORY_ERROR); 622 goto fail_malloc; 623 } 624 search = (xmlChar **) mem; 625 replace = search + n; 626 slen = (int *) (replace + n); 627 rlen = slen + n; 628 } 629 630 /* process arguments */ 631 632 i_empty = -1; 633 634 for (i=0; i<n; ++i) { 635 if (search_set != NULL) { 636 search[i] = xmlXPathCastNodeToString(search_set->nodeTab[i]); 637 if (search[i] == NULL) { 638 n = i; 639 goto fail_process_args; 640 } 641 } 642 643 slen[i] = xmlStrlen(search[i]); 644 if (i_empty < 0 && slen[i] == 0) 645 i_empty = i; 646 647 if (replace_set != NULL) { 648 if (i < replace_set->nodeNr) { 649 replace[i] = xmlXPathCastNodeToString(replace_set->nodeTab[i]); 650 if (replace[i] == NULL) { 651 n = i + 1; 652 goto fail_process_args; 653 } 654 } 655 else 656 replace[i] = NULL; 657 } 658 else { 659 if (i == 0) 660 replace[i] = replace_str; 661 else 662 replace[i] = NULL; 663 } 664 665 if (replace[i] == NULL) 666 rlen[i] = 0; 667 else 668 rlen[i] = xmlStrlen(replace[i]); 669 } 670 671 if (i_empty >= 0 && rlen[i_empty] == 0) 672 i_empty = -1; 673 674 /* replace operation */ 675 676 buf = xmlBufferCreate(); 677 if (buf == NULL) { 678 xmlXPathSetError(ctxt, XPATH_MEMORY_ERROR); 679 goto fail_buffer; 680 } 681 src = string; 682 start = string; 683 684 while (*src != 0) { 685 int max_len = 0, i_match = 0; 686 687 for (i=0; i<n; ++i) { 688 if (*src == search[i][0] && 689 slen[i] > max_len && 690 xmlStrncmp(src, search[i], slen[i]) == 0) 691 { 692 i_match = i; 693 max_len = slen[i]; 694 } 695 } 696 697 if (max_len == 0) { 698 if (i_empty >= 0 && start < src) { 699 if (xmlBufferAdd(buf, start, src - start) || 700 xmlBufferAdd(buf, replace[i_empty], rlen[i_empty])) 701 { 702 xmlXPathSetError(ctxt, XPATH_MEMORY_ERROR); 703 goto fail_buffer_add; 704 } 705 start = src; 706 } 707 708 src += xmlUTF8Size(src); 709 } 710 else { 711 if ((start < src && 712 xmlBufferAdd(buf, start, src - start)) || 713 (rlen[i_match] && 714 xmlBufferAdd(buf, replace[i_match], rlen[i_match]))) 715 { 716 xmlXPathSetError(ctxt, XPATH_MEMORY_ERROR); 717 goto fail_buffer_add; 718 } 719 720 src += slen[i_match]; 721 start = src; 722 } 723 } 724 725 if (start < src && xmlBufferAdd(buf, start, src - start)) { 726 xmlXPathSetError(ctxt, XPATH_MEMORY_ERROR); 727 goto fail_buffer_add; 728 } 729 730 /* create result node set */ 731 732 exsltStrReturnString(ctxt, xmlBufferContent(buf), xmlBufferLength(buf)); 733 734 /* clean up */ 735 736 fail_buffer_add: 737 xmlBufferFree(buf); 738 739 fail_buffer: 740 fail_process_args: 741 if (search_set != NULL) { 742 for (i=0; i<n; ++i) 743 xmlFree(search[i]); 744 } 745 if (replace_set != NULL) { 746 for (i=0; i<n; ++i) { 747 if (replace[i] != NULL) 748 xmlFree(replace[i]); 749 } 750 } 751 752 if (mem != NULL) 753 xmlFree(mem); 754 755 fail_malloc: 756 done_empty_search: 757 xmlFree(string); 758 759 fail_string: 760 if (search_set != NULL) 761 xmlXPathFreeNodeSet(search_set); 762 else 763 xmlFree(search_str); 764 765 fail_search: 766 if (replace_set != NULL) 767 xmlXPathFreeNodeSet(replace_set); 768 else 769 xmlFree(replace_str); 770 771 fail_replace: 772 return; 773 } 774 775 /** 776 * exsltStrRegister: 777 * 778 * Registers the EXSLT - Strings module 779 */ 780 781 void 782 exsltStrRegister (void) { 783 xsltRegisterExtModuleFunction ((const xmlChar *) "tokenize", 784 EXSLT_STRINGS_NAMESPACE, 785 exsltStrTokenizeFunction); 786 xsltRegisterExtModuleFunction ((const xmlChar *) "split", 787 EXSLT_STRINGS_NAMESPACE, 788 exsltStrSplitFunction); 789 xsltRegisterExtModuleFunction ((const xmlChar *) "encode-uri", 790 EXSLT_STRINGS_NAMESPACE, 791 exsltStrEncodeUriFunction); 792 xsltRegisterExtModuleFunction ((const xmlChar *) "decode-uri", 793 EXSLT_STRINGS_NAMESPACE, 794 exsltStrDecodeUriFunction); 795 xsltRegisterExtModuleFunction ((const xmlChar *) "padding", 796 EXSLT_STRINGS_NAMESPACE, 797 exsltStrPaddingFunction); 798 xsltRegisterExtModuleFunction ((const xmlChar *) "align", 799 EXSLT_STRINGS_NAMESPACE, 800 exsltStrAlignFunction); 801 xsltRegisterExtModuleFunction ((const xmlChar *) "concat", 802 EXSLT_STRINGS_NAMESPACE, 803 exsltStrConcatFunction); 804 xsltRegisterExtModuleFunction ((const xmlChar *) "replace", 805 EXSLT_STRINGS_NAMESPACE, 806 exsltStrReplaceFunction); 807 } 808 809 /** 810 * exsltStrXpathCtxtRegister: 811 * 812 * Registers the EXSLT - Strings module for use outside XSLT 813 */ 814 int 815 exsltStrXpathCtxtRegister (xmlXPathContextPtr ctxt, const xmlChar *prefix) 816 { 817 if (ctxt 818 && prefix 819 && !xmlXPathRegisterNs(ctxt, 820 prefix, 821 (const xmlChar *) EXSLT_STRINGS_NAMESPACE) 822 && !xmlXPathRegisterFuncNS(ctxt, 823 (const xmlChar *) "encode-uri", 824 (const xmlChar *) EXSLT_STRINGS_NAMESPACE, 825 exsltStrEncodeUriFunction) 826 && !xmlXPathRegisterFuncNS(ctxt, 827 (const xmlChar *) "decode-uri", 828 (const xmlChar *) EXSLT_STRINGS_NAMESPACE, 829 exsltStrDecodeUriFunction) 830 && !xmlXPathRegisterFuncNS(ctxt, 831 (const xmlChar *) "padding", 832 (const xmlChar *) EXSLT_STRINGS_NAMESPACE, 833 exsltStrPaddingFunction) 834 && !xmlXPathRegisterFuncNS(ctxt, 835 (const xmlChar *) "align", 836 (const xmlChar *) EXSLT_STRINGS_NAMESPACE, 837 exsltStrAlignFunction) 838 && !xmlXPathRegisterFuncNS(ctxt, 839 (const xmlChar *) "concat", 840 (const xmlChar *) EXSLT_STRINGS_NAMESPACE, 841 exsltStrConcatFunction) 842 && !xmlXPathRegisterFuncNS(ctxt, 843 (const xmlChar *) "replace", 844 (const xmlChar *) EXSLT_STRINGS_NAMESPACE, 845 exsltStrReplaceFunction)) { 846 return 0; 847 } 848 return -1; 849 }