ReactOS 0.4.16-dev-340-g0540c21
functions.c
Go to the documentation of this file.
1/*
2 * functions.c: Implementation of the XSLT extra functions
3 *
4 * Reference:
5 * http://www.w3.org/TR/1999/REC-xslt-19991116
6 *
7 * See Copyright for the status of this software.
8 *
9 * daniel@veillard.com
10 * Bjorn Reese <breese@users.sourceforge.net> for number formatting
11 */
12
13#include "precomp.h"
14
15#include <libxml/xpointer.h>
16
17#ifdef WITH_XSLT_DEBUG
18#define WITH_XSLT_DEBUG_FUNCTION
19#endif
20
21/*
22 * Some versions of DocBook XSL use the vendor string to detect
23 * supporting chunking, this is a workaround to be considered
24 * in the list of decent XSLT processors <grin/>
25 */
26#define DOCBOOK_XSL_HACK
27
39xmlXPathFunction
41 const xmlChar *name, const xmlChar *ns_uri) {
42 xmlXPathContextPtr ctxt = (xmlXPathContextPtr) vctxt;
43 xmlXPathFunction ret;
44
45 if ((ctxt == NULL) || (name == NULL) || (ns_uri == NULL))
46 return (NULL);
47
48#ifdef WITH_XSLT_DEBUG_FUNCTION
50 "Lookup function {%s}%s\n", ns_uri, name);
51#endif
52
53 /* give priority to context-level functions */
54 /*
55 ret = (xmlXPathFunction) xmlHashLookup2(ctxt->funcHash, name, ns_uri);
56 */
57 XML_CAST_FPTR(ret) = xmlHashLookup2(ctxt->funcHash, name, ns_uri);
58
59 if (ret == NULL)
61
62#ifdef WITH_XSLT_DEBUG_FUNCTION
63 if (ret != NULL)
65 "found function %s\n", name);
66#endif
67 return(ret);
68}
69
70
71/************************************************************************
72 * *
73 * Module interfaces *
74 * *
75 ************************************************************************/
76
77static void
78xsltDocumentFunctionLoadDocument(xmlXPathParserContextPtr ctxt, xmlChar* URI)
79{
82 xmlChar *fragment;
83 xsltDocumentPtr idoc; /* document info */
84 xmlDocPtr doc;
85 xmlXPathContextPtr xptrctxt = NULL;
86 xmlXPathObjectPtr resObj = NULL;
87
88 tctxt = xsltXPathGetTransformContext(ctxt);
89 if (tctxt == NULL) {
91 "document() : internal error tctxt == NULL\n");
92 valuePush(ctxt, xmlXPathNewNodeSet(NULL));
93 return;
94 }
95
96 uri = xmlParseURI((const char *) URI);
97 if (uri == NULL) {
99 "document() : failed to parse URI\n");
100 valuePush(ctxt, xmlXPathNewNodeSet(NULL));
101 return;
102 }
103
104 /*
105 * check for and remove fragment identifier
106 */
107 fragment = (xmlChar *)uri->fragment;
108 if (fragment != NULL) {
109 xmlChar *newURI;
110 uri->fragment = NULL;
111 newURI = xmlSaveUri(uri);
112 idoc = xsltLoadDocument(tctxt, newURI);
113 xmlFree(newURI);
114 } else
115 idoc = xsltLoadDocument(tctxt, URI);
117
118 if (idoc == NULL) {
119 if ((URI == NULL) ||
120 (URI[0] == '#') ||
121 ((tctxt->style->doc != NULL) &&
122 (xmlStrEqual(tctxt->style->doc->URL, URI))))
123 {
124 /*
125 * This selects the stylesheet's doc itself.
126 */
127 doc = tctxt->style->doc;
128 } else {
129 valuePush(ctxt, xmlXPathNewNodeSet(NULL));
130
131 if (fragment != NULL)
132 xmlFree(fragment);
133
134 return;
135 }
136 } else
137 doc = idoc->doc;
138
139 if (fragment == NULL) {
140 valuePush(ctxt, xmlXPathNewNodeSet((xmlNodePtr) doc));
141 return;
142 }
143
144 /* use XPointer of HTML location for fragment ID */
145#ifdef LIBXML_XPTR_ENABLED
146 xptrctxt = xmlXPtrNewContext(doc, NULL, NULL);
147 if (xptrctxt == NULL) {
149 "document() : internal error xptrctxt == NULL\n");
150 goto out_fragment;
151 }
152
153#if LIBXML_VERSION >= 20911 || \
154 defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
155 xptrctxt->opLimit = ctxt->context->opLimit;
156 xptrctxt->opCount = ctxt->context->opCount;
157 xptrctxt->depth = ctxt->context->depth;
158
159 resObj = xmlXPtrEval(fragment, xptrctxt);
160
161 ctxt->context->opCount = xptrctxt->opCount;
162#else
163 resObj = xmlXPtrEval(fragment, xptrctxt);
164#endif
165
166 xmlXPathFreeContext(xptrctxt);
167#endif /* LIBXML_XPTR_ENABLED */
168
169 if ((resObj != NULL) && (resObj->type != XPATH_NODESET)) {
171 "document() : XPointer does not select a node set: #%s\n",
172 fragment);
173 xmlXPathFreeObject(resObj);
174 resObj = NULL;
175 }
176
177out_fragment:
178 if (resObj == NULL)
179 resObj = xmlXPathNewNodeSet(NULL);
180 valuePush(ctxt, resObj);
181 xmlFree(fragment);
182}
183
192void
193xsltDocumentFunction(xmlXPathParserContextPtr ctxt, int nargs)
194{
195 xmlXPathObjectPtr obj, obj2 = NULL;
196 xmlChar *base = NULL, *URI;
197
198
199 if ((nargs < 1) || (nargs > 2)) {
201 "document() : invalid number of args %d\n",
202 nargs);
203 ctxt->error = XPATH_INVALID_ARITY;
204 return;
205 }
206 if (ctxt->value == NULL) {
208 "document() : invalid arg value\n");
209 ctxt->error = XPATH_INVALID_TYPE;
210 return;
211 }
212
213 if (nargs == 2) {
214 if (ctxt->value->type != XPATH_NODESET) {
216 "document() : invalid arg expecting a nodeset\n");
217 ctxt->error = XPATH_INVALID_TYPE;
218 return;
219 }
220
221 obj2 = valuePop(ctxt);
222 }
223
224 if (ctxt->value->type == XPATH_NODESET) {
225 int i;
226 xmlXPathObjectPtr newobj, ret;
227
228 obj = valuePop(ctxt);
229 ret = xmlXPathNewNodeSet(NULL);
230
231 if ((obj != NULL) && obj->nodesetval) {
232 for (i = 0; i < obj->nodesetval->nodeNr; i++) {
233 valuePush(ctxt,
234 xmlXPathNewNodeSet(obj->nodesetval->nodeTab[i]));
235 xmlXPathStringFunction(ctxt, 1);
236 if (nargs == 2) {
237 valuePush(ctxt, xmlXPathObjectCopy(obj2));
238 } else {
239 valuePush(ctxt,
240 xmlXPathNewNodeSet(obj->nodesetval->
241 nodeTab[i]));
242 }
243 xsltDocumentFunction(ctxt, 2);
244 newobj = valuePop(ctxt);
245 ret->nodesetval = xmlXPathNodeSetMerge(ret->nodesetval,
246 newobj->nodesetval);
247 xmlXPathFreeObject(newobj);
248 }
249 }
250
251 if (obj != NULL)
252 xmlXPathFreeObject(obj);
253 if (obj2 != NULL)
254 xmlXPathFreeObject(obj2);
255 valuePush(ctxt, ret);
256 return;
257 }
258 /*
259 * Make sure it's converted to a string
260 */
261 xmlXPathStringFunction(ctxt, 1);
262 if (ctxt->value->type != XPATH_STRING) {
264 "document() : invalid arg expecting a string\n");
265 ctxt->error = XPATH_INVALID_TYPE;
266 if (obj2 != NULL)
267 xmlXPathFreeObject(obj2);
268 return;
269 }
270 obj = valuePop(ctxt);
271 if (obj->stringval == NULL) {
272 valuePush(ctxt, xmlXPathNewNodeSet(NULL));
273 } else {
275 tctxt = xsltXPathGetTransformContext(ctxt);
276 if ((obj2 != NULL) && (obj2->nodesetval != NULL) &&
277 (obj2->nodesetval->nodeNr > 0) &&
278 IS_XSLT_REAL_NODE(obj2->nodesetval->nodeTab[0])) {
280
281 target = obj2->nodesetval->nodeTab[0];
282 if ((target->type == XML_ATTRIBUTE_NODE) ||
283 (target->type == XML_PI_NODE)) {
284 target = ((xmlAttrPtr) target)->parent;
285 }
287 } else {
288 if ((tctxt != NULL) && (tctxt->inst != NULL)) {
289 base = xmlNodeGetBase(tctxt->inst->doc, tctxt->inst);
290 } else if ((tctxt != NULL) && (tctxt->style != NULL) &&
291 (tctxt->style->doc != NULL)) {
292 base = xmlNodeGetBase(tctxt->style->doc,
293 (xmlNodePtr) tctxt->style->doc);
294 }
295 }
296 URI = xmlBuildURI(obj->stringval, base);
297 if (base != NULL)
298 xmlFree(base);
299 if (URI == NULL) {
300 if ((tctxt != NULL) && (tctxt->style != NULL) &&
301 (tctxt->style->doc != NULL) &&
302 (xmlStrEqual(URI, tctxt->style->doc->URL))) {
303 /* This selects the stylesheet's doc itself. */
304 valuePush(ctxt, xmlXPathNewNodeSet((xmlNodePtr) tctxt->style->doc));
305 } else {
306 valuePush(ctxt, xmlXPathNewNodeSet(NULL));
307 }
308 } else {
310 xmlFree(URI);
311 }
312 }
313 xmlXPathFreeObject(obj);
314 if (obj2 != NULL)
315 xmlXPathFreeObject(obj2);
316}
317
326void
327xsltKeyFunction(xmlXPathParserContextPtr ctxt, int nargs){
328 xmlXPathObjectPtr obj1, obj2;
329
330 if (nargs != 2) {
332 "key() : expects two arguments\n");
333 ctxt->error = XPATH_INVALID_ARITY;
334 return;
335 }
336
337 /*
338 * Get the key's value.
339 */
340 obj2 = valuePop(ctxt);
341 xmlXPathStringFunction(ctxt, 1);
342 if ((obj2 == NULL) ||
343 (ctxt->value == NULL) || (ctxt->value->type != XPATH_STRING)) {
345 "key() : invalid arg expecting a string\n");
346 ctxt->error = XPATH_INVALID_TYPE;
347 xmlXPathFreeObject(obj2);
348
349 return;
350 }
351 /*
352 * Get the key's name.
353 */
354 obj1 = valuePop(ctxt);
355
356 if ((obj2->type == XPATH_NODESET) || (obj2->type == XPATH_XSLT_TREE)) {
357 int i;
358 xmlXPathObjectPtr newobj, ret;
359
360 ret = xmlXPathNewNodeSet(NULL);
361
362 if (obj2->nodesetval != NULL) {
363 for (i = 0; i < obj2->nodesetval->nodeNr; i++) {
364 valuePush(ctxt, xmlXPathObjectCopy(obj1));
365 valuePush(ctxt,
366 xmlXPathNewNodeSet(obj2->nodesetval->nodeTab[i]));
367 xmlXPathStringFunction(ctxt, 1);
368 xsltKeyFunction(ctxt, 2);
369 newobj = valuePop(ctxt);
370 ret->nodesetval = xmlXPathNodeSetMerge(ret->nodesetval,
371 newobj->nodesetval);
372 xmlXPathFreeObject(newobj);
373 }
374 }
375 valuePush(ctxt, ret);
376 } else {
377 xmlNodeSetPtr nodelist = NULL;
378 xmlChar *key = NULL, *value;
379 const xmlChar *keyURI;
381 xmlChar *qname, *prefix;
382 xmlXPathContextPtr xpctxt = ctxt->context;
383 xmlNodePtr tmpNode = NULL;
384 xsltDocumentPtr oldDocInfo;
385
386 tctxt = xsltXPathGetTransformContext(ctxt);
387
388 oldDocInfo = tctxt->document;
389
390 if (xpctxt->node == NULL) {
391 xsltTransformError(tctxt, NULL, tctxt->inst,
392 "Internal error in xsltKeyFunction(): "
393 "The context node is not set on the XPath context.\n");
394 tctxt->state = XSLT_STATE_STOPPED;
395 goto error;
396 }
397 /*
398 * Get the associated namespace URI if qualified name
399 */
400 qname = obj1->stringval;
401 key = xmlSplitQName2(qname, &prefix);
402 if (key == NULL) {
403 key = xmlStrdup(obj1->stringval);
404 keyURI = NULL;
405 if (prefix != NULL)
406 xmlFree(prefix);
407 } else {
408 if (prefix != NULL) {
409 keyURI = xmlXPathNsLookup(xpctxt, prefix);
410 if (keyURI == NULL) {
411 xsltTransformError(tctxt, NULL, tctxt->inst,
412 "key() : prefix %s is not bound\n", prefix);
413 /*
414 * TODO: Shouldn't we stop here?
415 */
416 }
417 xmlFree(prefix);
418 } else {
419 keyURI = NULL;
420 }
421 }
422
423 /*
424 * Force conversion of first arg to string
425 */
426 valuePush(ctxt, obj2);
427 xmlXPathStringFunction(ctxt, 1);
428 if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_STRING)) {
429 xsltTransformError(tctxt, NULL, tctxt->inst,
430 "key() : invalid arg expecting a string\n");
431 ctxt->error = XPATH_INVALID_TYPE;
432 goto error;
433 }
434 obj2 = valuePop(ctxt);
435 value = obj2->stringval;
436
437 /*
438 * We need to ensure that ctxt->document is available for
439 * xsltGetKey().
440 * First find the relevant doc, which is the context node's
441 * owner doc; using context->doc is not safe, since
442 * the doc could have been acquired via the document() function,
443 * or the doc might be a Result Tree Fragment.
444 * FUTURE INFO: In XSLT 2.0 the key() function takes an additional
445 * argument indicating the doc to use.
446 */
447 if (xpctxt->node->type == XML_NAMESPACE_DECL) {
448 /*
449 * REVISIT: This is a libxml hack! Check xpath.c for details.
450 * The XPath module sets the owner element of a ns-node on
451 * the ns->next field.
452 */
453 if ((((xmlNsPtr) xpctxt->node)->next != NULL) &&
454 (((xmlNsPtr) xpctxt->node)->next->type == XML_ELEMENT_NODE))
455 {
456 tmpNode = (xmlNodePtr) ((xmlNsPtr) xpctxt->node)->next;
457 }
458 } else
459 tmpNode = xpctxt->node;
460
461 if ((tmpNode == NULL) || (tmpNode->doc == NULL)) {
462 xsltTransformError(tctxt, NULL, tctxt->inst,
463 "Internal error in xsltKeyFunction(): "
464 "Couldn't get the doc of the XPath context node.\n");
465 goto error;
466 }
467
468 if ((tctxt->document == NULL) ||
469 (tctxt->document->doc != tmpNode->doc))
470 {
471 if (tmpNode->doc->name && (tmpNode->doc->name[0] == ' ')) {
472 /*
473 * This is a Result Tree Fragment.
474 */
475 if (tmpNode->doc->_private == NULL) {
476 tmpNode->doc->_private = xsltNewDocument(tctxt, tmpNode->doc);
477 if (tmpNode->doc->_private == NULL)
478 goto error;
479 }
480 tctxt->document = (xsltDocumentPtr) tmpNode->doc->_private;
481 } else {
482 /*
483 * May be the initial source doc or a doc acquired via the
484 * document() function.
485 */
486 tctxt->document = xsltFindDocument(tctxt, tmpNode->doc);
487 }
488 if (tctxt->document == NULL) {
489 xsltTransformError(tctxt, NULL, tctxt->inst,
490 "Internal error in xsltKeyFunction(): "
491 "Could not get the document info of a context doc.\n");
492 tctxt->state = XSLT_STATE_STOPPED;
493 goto error;
494 }
495 }
496 /*
497 * Get/compute the key value.
498 */
499 nodelist = xsltGetKey(tctxt, key, keyURI, value);
500
501error:
502 tctxt->document = oldDocInfo;
503 valuePush(ctxt, xmlXPathWrapNodeSet(
504 xmlXPathNodeSetMerge(NULL, nodelist)));
505 if (key != NULL)
506 xmlFree(key);
507 }
508
509 if (obj1 != NULL)
510 xmlXPathFreeObject(obj1);
511 if (obj2 != NULL)
512 xmlXPathFreeObject(obj2);
513}
514
523void
524xsltUnparsedEntityURIFunction(xmlXPathParserContextPtr ctxt, int nargs){
525 xmlXPathObjectPtr obj;
526 xmlChar *str;
527
528 if ((nargs != 1) || (ctxt->value == NULL)) {
530 "unparsed-entity-uri() : expects one string arg\n");
531 ctxt->error = XPATH_INVALID_ARITY;
532 return;
533 }
534 obj = valuePop(ctxt);
535 if (obj->type != XPATH_STRING) {
536 obj = xmlXPathConvertString(obj);
537 }
538
539 str = obj->stringval;
540 if (str == NULL) {
541 valuePush(ctxt, xmlXPathNewString((const xmlChar *)""));
542 } else {
544
545 entity = xmlGetDocEntity(ctxt->context->doc, str);
546 if (entity == NULL) {
547 valuePush(ctxt, xmlXPathNewString((const xmlChar *)""));
548 } else {
549 if (entity->URI != NULL)
550 valuePush(ctxt, xmlXPathNewString(entity->URI));
551 else
552 valuePush(ctxt, xmlXPathNewString((const xmlChar *)""));
553 }
554 }
555 xmlXPathFreeObject(obj);
556}
557
566void
567xsltFormatNumberFunction(xmlXPathParserContextPtr ctxt, int nargs)
568{
569 xmlXPathObjectPtr numberObj = NULL;
570 xmlXPathObjectPtr formatObj = NULL;
571 xmlXPathObjectPtr decimalObj = NULL;
572 xsltStylesheetPtr sheet;
573 xsltDecimalFormatPtr formatValues = NULL;
575 const xmlChar *ncname;
576 const xmlChar *prefix = NULL;
577 const xmlChar *nsUri = NULL;
579
580 tctxt = xsltXPathGetTransformContext(ctxt);
581 if ((tctxt == NULL) || (tctxt->inst == NULL))
582 return;
583 sheet = tctxt->style;
584 if (sheet == NULL)
585 return;
586 formatValues = sheet->decimalFormat;
587
588 switch (nargs) {
589 case 3:
590 if ((ctxt->value != NULL) && (ctxt->value->type != XPATH_STRING))
591 xmlXPathStringFunction(ctxt, 1);
592 decimalObj = valuePop(ctxt);
593 ncname = xsltSplitQName(sheet->dict, decimalObj->stringval, &prefix);
594 if (prefix != NULL) {
595 xmlNsPtr ns = xmlSearchNs(tctxt->inst->doc, tctxt->inst, prefix);
596 if (ns == NULL) {
598 "format-number : No namespace found for QName '%s:%s'\n",
599 prefix, ncname);
600 sheet->errors++;
601 ncname = NULL;
602 }
603 else {
604 nsUri = ns->href;
605 }
606 }
607 if (ncname != NULL) {
608 formatValues = xsltDecimalFormatGetByQName(sheet, nsUri, ncname);
609 }
610 if (formatValues == NULL) {
612 "format-number() : undeclared decimal format '%s'\n",
613 decimalObj->stringval);
614 }
615 /* Intentional fall-through */
616 case 2:
617 if ((ctxt->value != NULL) && (ctxt->value->type != XPATH_STRING))
618 xmlXPathStringFunction(ctxt, 1);
619 formatObj = valuePop(ctxt);
620 if ((ctxt->value != NULL) && (ctxt->value->type != XPATH_NUMBER))
621 xmlXPathNumberFunction(ctxt, 1);
622 numberObj = valuePop(ctxt);
623 break;
624 default:
625 xmlXPathErr(ctxt, XPATH_INVALID_ARITY);
626 return;
627 }
628
629 if (formatValues != NULL) {
630 if (xsltFormatNumberConversion(formatValues,
631 formatObj->stringval,
632 numberObj->floatval,
633 &result) == XPATH_EXPRESSION_OK) {
634 valuePush(ctxt, xmlXPathNewString(result));
636 }
637 }
638
639 xmlXPathFreeObject(numberObj);
640 xmlXPathFreeObject(formatObj);
641 xmlXPathFreeObject(decimalObj);
642}
643
652void
653xsltGenerateIdFunction(xmlXPathParserContextPtr ctxt, int nargs){
654 static char base_address;
656 xmlXPathObjectPtr obj = NULL;
657 long val;
658 xmlChar str[30];
659
660 if (nargs == 0) {
661 cur = ctxt->context->node;
662 } else if (nargs == 1) {
663 xmlNodeSetPtr nodelist;
664 int i, ret;
665
666 if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_NODESET)) {
667 ctxt->error = XPATH_INVALID_TYPE;
669 "generate-id() : invalid arg expecting a node-set\n");
670 return;
671 }
672 obj = valuePop(ctxt);
673 nodelist = obj->nodesetval;
674 if ((nodelist == NULL) || (nodelist->nodeNr <= 0)) {
675 xmlXPathFreeObject(obj);
676 valuePush(ctxt, xmlXPathNewCString(""));
677 return;
678 }
679 cur = nodelist->nodeTab[0];
680 for (i = 1;i < nodelist->nodeNr;i++) {
681 ret = xmlXPathCmpNodes(cur, nodelist->nodeTab[i]);
682 if (ret == -1)
683 cur = nodelist->nodeTab[i];
684 }
685 } else {
687 "generate-id() : invalid number of args %d\n", nargs);
688 ctxt->error = XPATH_INVALID_ARITY;
689 return;
690 }
691
692 if (obj)
693 xmlXPathFreeObject(obj);
694
695 val = (long)((char *)cur - (char *)&base_address);
696 if (val >= 0) {
697 snprintf((char *)str, sizeof(str), "idp%ld", val);
698 } else {
699 snprintf((char *)str, sizeof(str), "idm%ld", -val);
700 }
701 valuePush(ctxt, xmlXPathNewString(str));
702}
703
712void
713xsltSystemPropertyFunction(xmlXPathParserContextPtr ctxt, int nargs){
714 xmlXPathObjectPtr obj;
715 xmlChar *prefix, *name;
716 const xmlChar *nsURI = NULL;
717
718 if (nargs != 1) {
720 "system-property() : expects one string arg\n");
721 ctxt->error = XPATH_INVALID_ARITY;
722 return;
723 }
724 if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_STRING)) {
726 "system-property() : invalid arg expecting a string\n");
727 ctxt->error = XPATH_INVALID_TYPE;
728 return;
729 }
730 obj = valuePop(ctxt);
731 if (obj->stringval == NULL) {
732 valuePush(ctxt, xmlXPathNewString((const xmlChar *)""));
733 } else {
734 name = xmlSplitQName2(obj->stringval, &prefix);
735 if (name == NULL) {
736 name = xmlStrdup(obj->stringval);
737 } else {
738 nsURI = xmlXPathNsLookup(ctxt->context, prefix);
739 if (nsURI == NULL) {
741 "system-property() : prefix %s is not bound\n", prefix);
742 }
743 }
744
745 if (xmlStrEqual(nsURI, XSLT_NAMESPACE)) {
746#ifdef DOCBOOK_XSL_HACK
747 if (xmlStrEqual(name, (const xmlChar *)"vendor")) {
748 xsltStylesheetPtr sheet;
750
751 tctxt = xsltXPathGetTransformContext(ctxt);
752 if ((tctxt != NULL) && (tctxt->inst != NULL) &&
753 (xmlStrEqual(tctxt->inst->name, BAD_CAST "variable")) &&
754 (tctxt->inst->parent != NULL) &&
755 (xmlStrEqual(tctxt->inst->parent->name,
756 BAD_CAST "template")))
757 sheet = tctxt->style;
758 else
759 sheet = NULL;
760 if ((sheet != NULL) && (sheet->doc != NULL) &&
761 (sheet->doc->URL != NULL) &&
762 (xmlStrstr(sheet->doc->URL,
763 (const xmlChar *)"chunk") != NULL)) {
764 valuePush(ctxt, xmlXPathNewString(
765 (const xmlChar *)"libxslt (SAXON 6.2 compatible)"));
766
767 } else {
768 valuePush(ctxt, xmlXPathNewString(
769 (const xmlChar *)XSLT_DEFAULT_VENDOR));
770 }
771 } else
772#else
773 if (xmlStrEqual(name, (const xmlChar *)"vendor")) {
774 valuePush(ctxt, xmlXPathNewString(
775 (const xmlChar *)XSLT_DEFAULT_VENDOR));
776 } else
777#endif
778 if (xmlStrEqual(name, (const xmlChar *)"version")) {
779 valuePush(ctxt, xmlXPathNewString(
780 (const xmlChar *)XSLT_DEFAULT_VERSION));
781 } else if (xmlStrEqual(name, (const xmlChar *)"vendor-url")) {
782 valuePush(ctxt, xmlXPathNewString(
783 (const xmlChar *)XSLT_DEFAULT_URL));
784 } else {
785 valuePush(ctxt, xmlXPathNewString((const xmlChar *)""));
786 }
787 } else {
788 valuePush(ctxt, xmlXPathNewString((const xmlChar *)""));
789 }
790 if (name != NULL)
791 xmlFree(name);
792 if (prefix != NULL)
793 xmlFree(prefix);
794 }
795 xmlXPathFreeObject(obj);
796}
797
806void
807xsltElementAvailableFunction(xmlXPathParserContextPtr ctxt, int nargs){
808 xmlXPathObjectPtr obj;
809 xmlChar *prefix, *name;
810 const xmlChar *nsURI = NULL;
812
813 if (nargs != 1) {
815 "element-available() : expects one string arg\n");
816 ctxt->error = XPATH_INVALID_ARITY;
817 return;
818 }
819 xmlXPathStringFunction(ctxt, 1);
820 if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_STRING)) {
822 "element-available() : invalid arg expecting a string\n");
823 ctxt->error = XPATH_INVALID_TYPE;
824 return;
825 }
826 obj = valuePop(ctxt);
827 tctxt = xsltXPathGetTransformContext(ctxt);
828 if ((tctxt == NULL) || (tctxt->inst == NULL)) {
830 "element-available() : internal error tctxt == NULL\n");
831 xmlXPathFreeObject(obj);
832 valuePush(ctxt, xmlXPathNewBoolean(0));
833 return;
834 }
835
836
837 name = xmlSplitQName2(obj->stringval, &prefix);
838 if (name == NULL) {
839 xmlNsPtr ns;
840
841 name = xmlStrdup(obj->stringval);
842 ns = xmlSearchNs(tctxt->inst->doc, tctxt->inst, NULL);
843 if (ns != NULL) nsURI = ns->href;
844 } else {
845 nsURI = xmlXPathNsLookup(ctxt->context, prefix);
846 if (nsURI == NULL) {
848 "element-available() : prefix %s is not bound\n", prefix);
849 }
850 }
851
852 if (xsltExtElementLookup(tctxt, name, nsURI) != NULL) {
853 valuePush(ctxt, xmlXPathNewBoolean(1));
854 } else {
855 valuePush(ctxt, xmlXPathNewBoolean(0));
856 }
857
858 xmlXPathFreeObject(obj);
859 if (name != NULL)
860 xmlFree(name);
861 if (prefix != NULL)
862 xmlFree(prefix);
863}
864
873void
874xsltFunctionAvailableFunction(xmlXPathParserContextPtr ctxt, int nargs){
875 xmlXPathObjectPtr obj;
876 xmlChar *prefix, *name;
877 const xmlChar *nsURI = NULL;
878
879 if (nargs != 1) {
881 "function-available() : expects one string arg\n");
882 ctxt->error = XPATH_INVALID_ARITY;
883 return;
884 }
885 xmlXPathStringFunction(ctxt, 1);
886 if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_STRING)) {
888 "function-available() : invalid arg expecting a string\n");
889 ctxt->error = XPATH_INVALID_TYPE;
890 return;
891 }
892 obj = valuePop(ctxt);
893
894 name = xmlSplitQName2(obj->stringval, &prefix);
895 if (name == NULL) {
896 name = xmlStrdup(obj->stringval);
897 } else {
898 nsURI = xmlXPathNsLookup(ctxt->context, prefix);
899 if (nsURI == NULL) {
901 "function-available() : prefix %s is not bound\n", prefix);
902 }
903 }
904
905 if (xmlXPathFunctionLookupNS(ctxt->context, name, nsURI) != NULL) {
906 valuePush(ctxt, xmlXPathNewBoolean(1));
907 } else {
908 valuePush(ctxt, xmlXPathNewBoolean(0));
909 }
910
911 xmlXPathFreeObject(obj);
912 if (name != NULL)
913 xmlFree(name);
914 if (prefix != NULL)
915 xmlFree(prefix);
916}
917
926static void
927xsltCurrentFunction(xmlXPathParserContextPtr ctxt, int nargs){
929
930 if (nargs != 0) {
932 "current() : function uses no argument\n");
933 ctxt->error = XPATH_INVALID_ARITY;
934 return;
935 }
936 tctxt = xsltXPathGetTransformContext(ctxt);
937 if (tctxt == NULL) {
939 "current() : internal error tctxt == NULL\n");
940 valuePush(ctxt, xmlXPathNewNodeSet(NULL));
941 } else {
942 valuePush(ctxt, xmlXPathNewNodeSet(tctxt->node)); /* current */
943 }
944}
945
946/************************************************************************
947 * *
948 * Registration of XSLT and libxslt functions *
949 * *
950 ************************************************************************/
951
958void
959xsltRegisterAllFunctions(xmlXPathContextPtr ctxt)
960{
961 xmlXPathRegisterFunc(ctxt, (const xmlChar *) "current",
963 xmlXPathRegisterFunc(ctxt, (const xmlChar *) "document",
965 xmlXPathRegisterFunc(ctxt, (const xmlChar *) "key", xsltKeyFunction);
966 xmlXPathRegisterFunc(ctxt, (const xmlChar *) "unparsed-entity-uri",
968 xmlXPathRegisterFunc(ctxt, (const xmlChar *) "format-number",
970 xmlXPathRegisterFunc(ctxt, (const xmlChar *) "generate-id",
972 xmlXPathRegisterFunc(ctxt, (const xmlChar *) "system-property",
974 xmlXPathRegisterFunc(ctxt, (const xmlChar *) "element-available",
976 xmlXPathRegisterFunc(ctxt, (const xmlChar *) "function-available",
978}
xsltTransformContextPtr xsltXPathGetTransformContext(xmlXPathParserContextPtr ctxt)
Definition: extensions.c:1367
xmlXPathFunction xsltExtModuleFunctionLookup(const xmlChar *name, const xmlChar *URI)
Definition: extensions.c:1416
xsltTransformFunction xsltExtElementLookup(xsltTransformContextPtr ctxt, const xmlChar *name, const xmlChar *URI)
Definition: extensions.c:1668
xmlXPathError xsltFormatNumberConversion(xsltDecimalFormatPtr self, xmlChar *format, double number, xmlChar **result)
Definition: numbers.c:941
#define NULL
Definition: types.h:112
xsltDocumentPtr xsltNewDocument(xsltTransformContextPtr ctxt, xmlDocPtr doc)
Definition: documents.c:127
xsltDocumentPtr xsltFindDocument(xsltTransformContextPtr ctxt, xmlDocPtr doc)
Definition: documents.c:400
xsltDocumentPtr xsltLoadDocument(xsltTransformContextPtr ctxt, const xmlChar *URI)
Definition: documents.c:268
XMLPUBFUN xmlEntityPtr XMLCALL xmlGetDocEntity(const xmlDoc *doc, const xmlChar *name)
void xsltSystemPropertyFunction(xmlXPathParserContextPtr ctxt, int nargs)
Definition: functions.c:713
void xsltDocumentFunction(xmlXPathParserContextPtr ctxt, int nargs)
Definition: functions.c:193
void xsltGenerateIdFunction(xmlXPathParserContextPtr ctxt, int nargs)
Definition: functions.c:653
void xsltRegisterAllFunctions(xmlXPathContextPtr ctxt)
Definition: functions.c:959
void xsltFormatNumberFunction(xmlXPathParserContextPtr ctxt, int nargs)
Definition: functions.c:567
xmlXPathFunction xsltXPathFunctionLookup(void *vctxt, const xmlChar *name, const xmlChar *ns_uri)
Definition: functions.c:40
void xsltElementAvailableFunction(xmlXPathParserContextPtr ctxt, int nargs)
Definition: functions.c:807
void xsltKeyFunction(xmlXPathParserContextPtr ctxt, int nargs)
Definition: functions.c:327
void xsltUnparsedEntityURIFunction(xmlXPathParserContextPtr ctxt, int nargs)
Definition: functions.c:524
void xsltFunctionAvailableFunction(xmlXPathParserContextPtr ctxt, int nargs)
Definition: functions.c:874
static void xsltDocumentFunctionLoadDocument(xmlXPathParserContextPtr ctxt, xmlChar *URI)
Definition: functions.c:78
static void xsltCurrentFunction(xmlXPathParserContextPtr ctxt, int nargs)
Definition: functions.c:927
FxCollectionEntry * cur
GLuint GLfloat * val
Definition: glext.h:7180
GLuint64EXT * result
Definition: glext.h:11304
GLenum target
Definition: glext.h:7315
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
xmlNodeSetPtr xsltGetKey(xsltTransformContextPtr ctxt, const xmlChar *name, const xmlChar *nameURI, const xmlChar *value)
Definition: keys.c:417
if(dx< 0)
Definition: linetemp.h:194
#define error(str)
Definition: mkdosfs.c:1605
const char * uri
Definition: sec_mgr.c:1588
#define long
Definition: qsort.c:33
static unsigned __int64 next
Definition: rand_nt.c:6
const WCHAR * str
XMLPUBVAR xmlFreeFunc xmlFree
Definition: globals.h:251
#define XML_CAST_FPTR(fptr)
Definition: hash.h:56
XMLPUBFUN void *XMLCALL xmlHashLookup2(xmlHashTablePtr table, const xmlChar *name, const xmlChar *name2)
Definition: hash.c:476
XMLPUBFUN xmlNsPtr XMLCALL xmlSearchNs(xmlDocPtr doc, xmlNodePtr node, const xmlChar *nameSpace)
xmlNode * xmlNodePtr
Definition: tree.h:488
@ XML_ATTRIBUTE_NODE
Definition: tree.h:161
@ XML_PI_NODE
Definition: tree.h:166
@ XML_NAMESPACE_DECL
Definition: tree.h:177
@ XML_ELEMENT_NODE
Definition: tree.h:160
xmlAttr * xmlAttrPtr
Definition: tree.h:433
XMLPUBFUN xmlChar *XMLCALL xmlNodeGetBase(const xmlDoc *doc, const xmlNode *cur)
XMLPUBFUN xmlChar *XMLCALL xmlSplitQName2(const xmlChar *name, xmlChar **prefix)
Definition: tree.h:551
const xmlChar * URL
Definition: tree.h:577
Definition: tree.h:489
struct _xmlDoc * doc
Definition: tree.h:498
const xmlChar * name
Definition: tree.h:492
struct _xmlNode * parent
Definition: tree.h:495
Definition: tree.h:389
Definition: uri.h:33
xmlDocPtr doc
xsltDecimalFormatPtr decimalFormat
xsltTransformState state
xsltDocumentPtr document
xsltStylesheetPtr style
Definition: actctx.c:446
Definition: copy.c:22
Definition: name.c:39
Definition: mxnamespace.c:45
Definition: pdh_main.c:94
XMLPUBFUN xmlURIPtr XMLCALL xmlParseURI(const char *str)
Definition: uri.c:940
XMLPUBFUN xmlChar *XMLCALL xmlSaveUri(xmlURIPtr uri)
Definition: uri.c:1066
XMLPUBFUN void XMLCALL xmlFreeURI(xmlURIPtr uri)
Definition: uri.c:1387
XMLPUBFUN xmlChar *XMLCALL xmlBuildURI(const xmlChar *URI, const xmlChar *base)
Definition: uri.c:1892
int ret
#define snprintf
Definition: wintirpc.h:48
XMLPUBFUN const xmlChar *XMLCALL xmlStrstr(const xmlChar *str, const xmlChar *val)
Definition: xmlstring.c:345
XMLPUBFUN xmlChar *XMLCALL xmlStrdup(const xmlChar *cur)
Definition: xmlstring.c:67
#define BAD_CAST
Definition: xmlstring.h:35
XMLPUBFUN int XMLCALL xmlStrEqual(const xmlChar *str1, const xmlChar *str2)
Definition: xmlstring.c:160
unsigned char xmlChar
Definition: xmlstring.h:28
@ XSLT_STATE_STOPPED
xsltDocument * xsltDocumentPtr
xsltDecimalFormatPtr xsltDecimalFormatGetByQName(xsltStylesheetPtr style, const xmlChar *nsUri, const xmlChar *name)
Definition: xslt.c:364
#define XSLT_DEFAULT_VENDOR
Definition: xslt.h:32
#define XSLT_DEFAULT_URL
Definition: xslt.h:39
#define XSLT_NAMESPACE
Definition: xslt.h:46
#define XSLT_DEFAULT_VERSION
Definition: xslt.h:25
void xsltTransformError(xsltTransformContextPtr ctxt, xsltStylesheetPtr style, xmlNodePtr node, const char *msg,...)
Definition: xsltutils.c:678
xmlGenericErrorFunc xsltGenericError
Definition: xsltutils.c:502
xmlGenericErrorFunc xsltGenericDebug
Definition: xsltutils.c:548
void * xsltGenericDebugContext
Definition: xsltutils.c:549
void * xsltGenericErrorContext
Definition: xsltutils.c:503
const xmlChar * xsltSplitQName(xmlDictPtr dict, const xmlChar *name, const xmlChar **prefix)
Definition: xsltutils.c:720
#define IS_XSLT_REAL_NODE(n)
Definition: xsltutils.h:68