ReactOS 0.4.16-dev-2206-gc56950d
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#define IN_LIBXSLT
14#include "libxslt.h"
15
16#include <string.h>
17
18#include <libxml/xmlmemory.h>
19#include <libxml/parser.h>
20#include <libxml/tree.h>
21#include <libxml/valid.h>
22#include <libxml/hash.h>
23#include <libxml/xmlerror.h>
24#include <libxml/xpath.h>
27#include <libxml/uri.h>
28#include <libxml/xpointer.h>
29#include "xslt.h"
30#include "xsltInternals.h"
31#include "xsltutils.h"
32#include "functions.h"
33#include "extensions.h"
34#include "numbersInternals.h"
35#include "keys.h"
36#include "documents.h"
37
38#ifdef WITH_XSLT_DEBUG
39#define WITH_XSLT_DEBUG_FUNCTION
40#endif
41
42/*
43 * Some versions of DocBook XSL use the vendor string to detect
44 * supporting chunking, this is a workaround to be considered
45 * in the list of decent XSLT processors <grin/>
46 */
47#define DOCBOOK_XSL_HACK
48
60xmlXPathFunction
62 const xmlChar *name, const xmlChar *ns_uri) {
63 xmlXPathContextPtr ctxt = (xmlXPathContextPtr) vctxt;
64 xmlXPathFunction ret;
65
66 if ((ctxt == NULL) || (name == NULL) || (ns_uri == NULL))
67 return (NULL);
68
69#ifdef WITH_XSLT_DEBUG_FUNCTION
71 "Lookup function {%s}%s\n", ns_uri, name);
72#endif
73
74 /* give priority to context-level functions */
75 /*
76 ret = (xmlXPathFunction) xmlHashLookup2(ctxt->funcHash, name, ns_uri);
77 */
78 XML_CAST_FPTR(ret) = xmlHashLookup2(ctxt->funcHash, name, ns_uri);
79
80 if (ret == NULL)
82
83#ifdef WITH_XSLT_DEBUG_FUNCTION
84 if (ret != NULL)
86 "found function %s\n", name);
87#endif
88 return(ret);
89}
90
91
92/************************************************************************
93 * *
94 * Module interfaces *
95 * *
96 ************************************************************************/
97
98static void
99xsltDocumentFunctionLoadDocument(xmlXPathParserContextPtr ctxt,
100 const xmlChar* URI, const xmlChar *fragment)
101{
103 xsltDocumentPtr idoc; /* document info */
104 xmlDocPtr doc;
105 xmlXPathContextPtr xptrctxt = NULL;
106 xmlXPathObjectPtr resObj = NULL;
107
108 (void) xptrctxt;
109
110 tctxt = xsltXPathGetTransformContext(ctxt);
111 if (tctxt == NULL) {
113 "document() : internal error tctxt == NULL\n");
114 goto out_fragment;
115 }
116
117 idoc = xsltLoadDocument(tctxt, URI);
118
119 if (idoc == NULL) {
120 if ((URI == NULL) ||
121 (URI[0] == '#') ||
122 ((tctxt->style->doc != NULL) &&
123 (xmlStrEqual(tctxt->style->doc->URL, URI))))
124 {
125 /*
126 * This selects the stylesheet's doc itself.
127 */
128 doc = tctxt->style->doc;
129 } else {
130 goto out_fragment;
131 }
132 } else
133 doc = idoc->doc;
134
135 if (fragment == NULL) {
136 valuePush(ctxt, xmlXPathNewNodeSet((xmlNodePtr) doc));
137 return;
138 }
139
140 /* use XPointer of HTML location for fragment ID */
141#ifdef LIBXML_XPTR_ENABLED
142 xptrctxt = xmlXPathNewContext(doc);
143 if (xptrctxt == NULL) {
145 "document() : internal error xptrctxt == NULL\n");
146 goto out_fragment;
147 }
148
149#if LIBXML_VERSION >= 20911 || \
150 defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
151 xptrctxt->opLimit = ctxt->context->opLimit;
152 xptrctxt->opCount = ctxt->context->opCount;
153 xptrctxt->depth = ctxt->context->depth;
154
155 resObj = xmlXPtrEval(fragment, xptrctxt);
156
157 ctxt->context->opCount = xptrctxt->opCount;
158#else
159 resObj = xmlXPtrEval(fragment, xptrctxt);
160#endif
161
162 xmlXPathFreeContext(xptrctxt);
163#endif /* LIBXML_XPTR_ENABLED */
164
165 if ((resObj != NULL) && (resObj->type != XPATH_NODESET)) {
167 "document() : XPointer does not select a node set: #%s\n",
168 fragment);
169 xmlXPathFreeObject(resObj);
170 resObj = NULL;
171 }
172
173out_fragment:
174 if (resObj == NULL)
175 resObj = xmlXPathNewNodeSet(NULL);
176 valuePush(ctxt, resObj);
177}
178
187void
188xsltDocumentFunction(xmlXPathParserContextPtr ctxt, int nargs)
189{
190 xmlXPathObjectPtr obj, obj2 = NULL;
191 xmlChar *base = NULL, *URI;
192 xmlChar *newURI = NULL;
193 xmlChar *fragment = NULL;
194
195 if ((nargs < 1) || (nargs > 2)) {
197 "document() : invalid number of args %d\n",
198 nargs);
199 ctxt->error = XPATH_INVALID_ARITY;
200 return;
201 }
202 if (ctxt->value == NULL) {
204 "document() : invalid arg value\n");
205 ctxt->error = XPATH_INVALID_TYPE;
206 return;
207 }
208
209 if (nargs == 2) {
210 if (ctxt->value->type != XPATH_NODESET) {
212 "document() : invalid arg expecting a nodeset\n");
213 ctxt->error = XPATH_INVALID_TYPE;
214 return;
215 }
216
217 obj2 = valuePop(ctxt);
218 }
219
220 if ((ctxt->value != NULL) && (ctxt->value->type == XPATH_NODESET)) {
221 int i;
222 xmlXPathObjectPtr newobj, ret;
223
224 obj = valuePop(ctxt);
225 ret = xmlXPathNewNodeSet(NULL);
226
227 if ((obj != NULL) && (obj->nodesetval != NULL) && (ret != NULL)) {
228 for (i = 0; i < obj->nodesetval->nodeNr; i++) {
229 valuePush(ctxt,
230 xmlXPathNewNodeSet(obj->nodesetval->nodeTab[i]));
231 xmlXPathStringFunction(ctxt, 1);
232 if (nargs == 2) {
233 valuePush(ctxt, xmlXPathObjectCopy(obj2));
234 } else {
235 valuePush(ctxt,
236 xmlXPathNewNodeSet(obj->nodesetval->
237 nodeTab[i]));
238 }
239 if (ctxt->error)
240 break;
241 xsltDocumentFunction(ctxt, 2);
242 newobj = valuePop(ctxt);
243 if (newobj != NULL) {
244 ret->nodesetval = xmlXPathNodeSetMerge(ret->nodesetval,
245 newobj->nodesetval);
246 xmlXPathFreeObject(newobj);
247 }
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 == NULL) || (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 {
276 const xmlChar *url;
277
278 tctxt = xsltXPathGetTransformContext(ctxt);
279
280 url = obj->stringval;
281
282 uri = xmlParseURI((const char *) url);
283 if (uri == NULL) {
285 "document() : failed to parse URI '%s'\n", url);
286 valuePush(ctxt, xmlXPathNewNodeSet(NULL));
287 goto error;
288 }
289
290 /*
291 * check for and remove fragment identifier
292 */
293 fragment = (xmlChar *)uri->fragment;
294 if (fragment != NULL) {
295 uri->fragment = NULL;
296 newURI = xmlSaveUri(uri);
297 url = newURI;
298 }
300
301 if ((obj2 != NULL) && (obj2->nodesetval != NULL) &&
302 (obj2->nodesetval->nodeNr > 0) &&
303 IS_XSLT_REAL_NODE(obj2->nodesetval->nodeTab[0])) {
304 xmlNodePtr target;
305
306 target = obj2->nodesetval->nodeTab[0];
307 if ((target->type == XML_ATTRIBUTE_NODE) ||
308 (target->type == XML_PI_NODE)) {
309 target = ((xmlAttrPtr) target)->parent;
310 }
311 base = xmlNodeGetBase(target->doc, target);
312 } else {
313 if ((tctxt != NULL) && (tctxt->inst != NULL)) {
314 base = xmlNodeGetBase(tctxt->inst->doc, tctxt->inst);
315 } else if ((tctxt != NULL) && (tctxt->style != NULL) &&
316 (tctxt->style->doc != NULL)) {
317 base = xmlNodeGetBase(tctxt->style->doc,
318 (xmlNodePtr) tctxt->style->doc);
319 }
320 }
321
322 URI = xmlBuildURI(url, base);
323 if (base != NULL)
324 xmlFree(base);
325 if (URI == NULL) {
326 if ((tctxt != NULL) && (tctxt->style != NULL) &&
327 (tctxt->style->doc != NULL) &&
328 (xmlStrEqual(URI, tctxt->style->doc->URL))) {
329 /* This selects the stylesheet's doc itself. */
330 valuePush(ctxt, xmlXPathNewNodeSet((xmlNodePtr) tctxt->style->doc));
331 } else {
332 valuePush(ctxt, xmlXPathNewNodeSet(NULL));
333 }
334 } else {
335 xsltDocumentFunctionLoadDocument(ctxt, URI, fragment);
336 xmlFree(URI);
337 }
338 }
339
340error:
341 xmlFree(newURI);
342 xmlFree(fragment);
343 xmlXPathFreeObject(obj);
344 if (obj2 != NULL)
345 xmlXPathFreeObject(obj2);
346}
347
356void
357xsltKeyFunction(xmlXPathParserContextPtr ctxt, int nargs){
358 xmlXPathObjectPtr obj1, obj2;
359
360 if (nargs != 2) {
362 "key() : expects two arguments\n");
363 ctxt->error = XPATH_INVALID_ARITY;
364 return;
365 }
366
367 /*
368 * Get the key's value.
369 */
370 obj2 = valuePop(ctxt);
371 xmlXPathStringFunction(ctxt, 1);
372 if ((obj2 == NULL) ||
373 (ctxt->value == NULL) || (ctxt->value->type != XPATH_STRING)) {
375 "key() : invalid arg expecting a string\n");
376 ctxt->error = XPATH_INVALID_TYPE;
377 xmlXPathFreeObject(obj2);
378
379 return;
380 }
381 /*
382 * Get the key's name.
383 */
384 obj1 = valuePop(ctxt);
385
386 if ((obj2->type == XPATH_NODESET) || (obj2->type == XPATH_XSLT_TREE)) {
387 int i;
388 xmlXPathObjectPtr newobj, ret;
389
390 ret = xmlXPathNewNodeSet(NULL);
391 if (ret == NULL) {
392 ctxt->error = XPATH_MEMORY_ERROR;
393 xmlXPathFreeObject(obj1);
394 xmlXPathFreeObject(obj2);
395 return;
396 }
397
398 if (obj2->nodesetval != NULL) {
399 for (i = 0; i < obj2->nodesetval->nodeNr; i++) {
400 valuePush(ctxt, xmlXPathObjectCopy(obj1));
401 valuePush(ctxt,
402 xmlXPathNewNodeSet(obj2->nodesetval->nodeTab[i]));
403 xmlXPathStringFunction(ctxt, 1);
404 xsltKeyFunction(ctxt, 2);
405 newobj = valuePop(ctxt);
406 if (newobj != NULL)
407 ret->nodesetval = xmlXPathNodeSetMerge(ret->nodesetval,
408 newobj->nodesetval);
409 xmlXPathFreeObject(newobj);
410 }
411 }
412 valuePush(ctxt, ret);
413 } else {
414 xmlNodeSetPtr nodelist = NULL;
415 xmlChar *key = NULL, *value;
416 const xmlChar *keyURI;
418 xmlChar *qname, *prefix;
419 xmlXPathContextPtr xpctxt = ctxt->context;
420 xmlNodePtr tmpNode = NULL;
421 xsltDocumentPtr oldDocInfo;
422
423 tctxt = xsltXPathGetTransformContext(ctxt);
424
425 oldDocInfo = tctxt->document;
426
427 if (xpctxt->node == NULL) {
428 xsltTransformError(tctxt, NULL, tctxt->inst,
429 "Internal error in xsltKeyFunction(): "
430 "The context node is not set on the XPath context.\n");
431 tctxt->state = XSLT_STATE_STOPPED;
432 goto error;
433 }
434 /*
435 * Get the associated namespace URI if qualified name
436 */
437 qname = obj1->stringval;
438 key = xmlSplitQName2(qname, &prefix);
439 if (key == NULL) {
440 key = xmlStrdup(obj1->stringval);
441 keyURI = NULL;
442 if (prefix != NULL)
444 } else {
445 if (prefix != NULL) {
446 keyURI = xmlXPathNsLookup(xpctxt, prefix);
447 if (keyURI == NULL) {
448 xsltTransformError(tctxt, NULL, tctxt->inst,
449 "key() : prefix %s is not bound\n", prefix);
450 /*
451 * TODO: Shouldn't we stop here?
452 */
453 }
455 } else {
456 keyURI = NULL;
457 }
458 }
459
460 /*
461 * Force conversion of first arg to string
462 */
463 valuePush(ctxt, obj2);
464 xmlXPathStringFunction(ctxt, 1);
465 obj2 = valuePop(ctxt);
466 if ((obj2 == NULL) || (obj2->type != XPATH_STRING)) {
467 xsltTransformError(tctxt, NULL, tctxt->inst,
468 "key() : invalid arg expecting a string\n");
469 ctxt->error = XPATH_INVALID_TYPE;
470 goto error;
471 }
472 value = obj2->stringval;
473
474 /*
475 * We need to ensure that ctxt->document is available for
476 * xsltGetKey().
477 * First find the relevant doc, which is the context node's
478 * owner doc; using context->doc is not safe, since
479 * the doc could have been acquired via the document() function,
480 * or the doc might be a Result Tree Fragment.
481 * FUTURE INFO: In XSLT 2.0 the key() function takes an additional
482 * argument indicating the doc to use.
483 */
484 if (xpctxt->node->type == XML_NAMESPACE_DECL) {
485 /*
486 * REVISIT: This is a libxml hack! Check xpath.c for details.
487 * The XPath module sets the owner element of a ns-node on
488 * the ns->next field.
489 */
490 if ((((xmlNsPtr) xpctxt->node)->next != NULL) &&
491 (((xmlNsPtr) xpctxt->node)->next->type == XML_ELEMENT_NODE))
492 {
493 tmpNode = (xmlNodePtr) ((xmlNsPtr) xpctxt->node)->next;
494 }
495 } else
496 tmpNode = xpctxt->node;
497
498 if ((tmpNode == NULL) || (tmpNode->doc == NULL)) {
499 xsltTransformError(tctxt, NULL, tctxt->inst,
500 "Internal error in xsltKeyFunction(): "
501 "Couldn't get the doc of the XPath context node.\n");
502 goto error;
503 }
504
505 if ((tctxt->document == NULL) ||
506 (tctxt->document->doc != tmpNode->doc))
507 {
508 if (tmpNode->doc->name && (tmpNode->doc->name[0] == ' ')) {
509 /*
510 * This is a Result Tree Fragment.
511 */
512 if (tmpNode->doc->_private == NULL) {
513 tmpNode->doc->_private = xsltNewDocument(tctxt, tmpNode->doc);
514 if (tmpNode->doc->_private == NULL)
515 goto error;
516 }
517 tctxt->document = (xsltDocumentPtr) tmpNode->doc->_private;
518 } else {
519 /*
520 * May be the initial source doc or a doc acquired via the
521 * document() function.
522 */
523 tctxt->document = xsltFindDocument(tctxt, tmpNode->doc);
524 }
525 if (tctxt->document == NULL) {
526 xsltTransformError(tctxt, NULL, tctxt->inst,
527 "Internal error in xsltKeyFunction(): "
528 "Could not get the document info of a context doc.\n");
529 tctxt->state = XSLT_STATE_STOPPED;
530 goto error;
531 }
532 }
533 /*
534 * Get/compute the key value.
535 */
536 nodelist = xsltGetKey(tctxt, key, keyURI, value);
537
538error:
539 tctxt->document = oldDocInfo;
540 valuePush(ctxt, xmlXPathWrapNodeSet(
541 xmlXPathNodeSetMerge(NULL, nodelist)));
542 if (key != NULL)
543 xmlFree(key);
544 }
545
546 if (obj1 != NULL)
547 xmlXPathFreeObject(obj1);
548 if (obj2 != NULL)
549 xmlXPathFreeObject(obj2);
550}
551
560void
561xsltUnparsedEntityURIFunction(xmlXPathParserContextPtr ctxt, int nargs){
562 xmlXPathObjectPtr obj;
563 xmlChar *str;
564
565 if ((nargs != 1) || (ctxt->value == NULL)) {
567 "unparsed-entity-uri() : expects one string arg\n");
568 ctxt->error = XPATH_INVALID_ARITY;
569 return;
570 }
571 obj = valuePop(ctxt);
572 if (obj->type != XPATH_STRING) {
573 obj = xmlXPathConvertString(obj);
574 if (obj == NULL) {
575 xmlXPathErr(ctxt, XPATH_MEMORY_ERROR);
576 return;
577 }
578 }
579
580 str = obj->stringval;
581 if (str == NULL) {
582 valuePush(ctxt, xmlXPathNewString((const xmlChar *)""));
583 } else {
584 xmlEntityPtr entity;
585
586 entity = xmlGetDocEntity(ctxt->context->doc, str);
587 if (entity == NULL) {
588 valuePush(ctxt, xmlXPathNewString((const xmlChar *)""));
589 } else {
590 if (entity->URI != NULL)
591 valuePush(ctxt, xmlXPathNewString(entity->URI));
592 else
593 valuePush(ctxt, xmlXPathNewString((const xmlChar *)""));
594 }
595 }
596 xmlXPathFreeObject(obj);
597}
598
607void
608xsltFormatNumberFunction(xmlXPathParserContextPtr ctxt, int nargs)
609{
610 xmlXPathObjectPtr numberObj = NULL;
611 xmlXPathObjectPtr formatObj = NULL;
612 xmlXPathObjectPtr decimalObj = NULL;
613 xsltStylesheetPtr sheet;
614 xsltDecimalFormatPtr formatValues = NULL;
616 const xmlChar *ncname;
617 const xmlChar *prefix = NULL;
618 const xmlChar *nsUri = NULL;
620
621 tctxt = xsltXPathGetTransformContext(ctxt);
622 if ((tctxt == NULL) || (tctxt->inst == NULL))
623 return;
624 sheet = tctxt->style;
625 if (sheet == NULL)
626 return;
627 formatValues = sheet->decimalFormat;
628
629 switch (nargs) {
630 case 3:
631 if ((ctxt->value != NULL) && (ctxt->value->type != XPATH_STRING))
632 xmlXPathStringFunction(ctxt, 1);
633 decimalObj = valuePop(ctxt);
634 ncname = xsltSplitQName(sheet->dict, decimalObj->stringval, &prefix);
635 if (prefix != NULL) {
636 xmlNsPtr ns = xmlSearchNs(tctxt->inst->doc, tctxt->inst, prefix);
637 if (ns == NULL) {
639 "format-number : No namespace found for QName '%s:%s'\n",
640 prefix, ncname);
641 sheet->errors++;
642 ncname = NULL;
643 }
644 else {
645 nsUri = ns->href;
646 }
647 }
648 if (ncname != NULL) {
649 formatValues = xsltDecimalFormatGetByQName(sheet, nsUri, ncname);
650 }
651 if (formatValues == NULL) {
653 "format-number() : undeclared decimal format '%s'\n",
654 decimalObj->stringval);
655 }
656 /* Intentional fall-through */
657 case 2:
658 if ((ctxt->value != NULL) && (ctxt->value->type != XPATH_STRING))
659 xmlXPathStringFunction(ctxt, 1);
660 formatObj = valuePop(ctxt);
661 if ((ctxt->value != NULL) && (ctxt->value->type != XPATH_NUMBER))
662 xmlXPathNumberFunction(ctxt, 1);
663 numberObj = valuePop(ctxt);
664 break;
665 default:
666 xmlXPathErr(ctxt, XPATH_INVALID_ARITY);
667 return;
668 }
669
670 if ((ctxt->error == 0) &&
671 (formatValues != NULL) && (formatObj != NULL) && (numberObj != NULL)) {
672 if (xsltFormatNumberConversion(formatValues,
673 formatObj->stringval,
674 numberObj->floatval,
675 &result) == XPATH_EXPRESSION_OK) {
676 valuePush(ctxt, xmlXPathNewString(result));
678 }
679 }
680
681 xmlXPathFreeObject(numberObj);
682 xmlXPathFreeObject(formatObj);
683 xmlXPathFreeObject(decimalObj);
684}
685
694void
695xsltGenerateIdFunction(xmlXPathParserContextPtr ctxt, int nargs){
697 xmlNodePtr cur = NULL;
698 xmlXPathObjectPtr obj = NULL;
699 char *str;
700 const xmlChar *nsPrefix = NULL;
701 void **psviPtr;
702 unsigned long id;
703 size_t size, nsPrefixSize = 0;
704
705 tctxt = xsltXPathGetTransformContext(ctxt);
706
707 if (nargs == 0) {
708 cur = ctxt->context->node;
709 } else if (nargs == 1) {
710 xmlNodeSetPtr nodelist;
711 int i, ret;
712
713 if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_NODESET)) {
714 ctxt->error = XPATH_INVALID_TYPE;
716 "generate-id() : invalid arg expecting a node-set\n");
717 goto out;
718 }
719 obj = valuePop(ctxt);
720 nodelist = obj->nodesetval;
721 if ((nodelist == NULL) || (nodelist->nodeNr <= 0)) {
722 valuePush(ctxt, xmlXPathNewCString(""));
723 goto out;
724 }
725 cur = nodelist->nodeTab[0];
726 for (i = 1;i < nodelist->nodeNr;i++) {
727 ret = xmlXPathCmpNodes(cur, nodelist->nodeTab[i]);
728 if (ret == -1)
729 cur = nodelist->nodeTab[i];
730 }
731 } else {
733 "generate-id() : invalid number of args %d\n", nargs);
734 ctxt->error = XPATH_INVALID_ARITY;
735 goto out;
736 }
737
738 size = 30; /* for "id%lu" */
739
740 if (cur->type == XML_NAMESPACE_DECL) {
741 xmlNsPtr ns = (xmlNsPtr) cur;
742
743 nsPrefix = ns->prefix;
744 if (nsPrefix == NULL)
745 nsPrefix = BAD_CAST "";
746 nsPrefixSize = xmlStrlen(nsPrefix);
747 /* For "ns" and hex-encoded string */
748 size += nsPrefixSize * 2 + 2;
749
750 /* Parent is stored in 'next'. */
751 cur = (xmlNodePtr) ns->next;
752 }
753
754 psviPtr = xsltGetPSVIPtr(cur);
755 if (psviPtr == NULL) {
757 "generate-id(): invalid node type %d\n", cur->type);
758 ctxt->error = XPATH_INVALID_TYPE;
759 goto out;
760 }
761
762 if (xsltGetSourceNodeFlags(cur) & XSLT_SOURCE_NODE_HAS_ID) {
763 id = (unsigned long) (size_t) *psviPtr;
764 } else {
765 if (cur->type == XML_TEXT_NODE && cur->line == USHRT_MAX) {
766 /* Text nodes store big line numbers in psvi. */
767 cur->line = 0;
768 } else if (*psviPtr != NULL) {
770 "generate-id(): psvi already set\n");
771 ctxt->error = XPATH_MEMORY_ERROR;
772 goto out;
773 }
774
775 if (tctxt->currentId == ULONG_MAX) {
777 "generate-id(): id overflow\n");
778 ctxt->error = XPATH_MEMORY_ERROR;
779 goto out;
780 }
781
782 id = ++tctxt->currentId;
783 *psviPtr = (void *) (size_t) id;
784 xsltSetSourceNodeFlags(tctxt, cur, XSLT_SOURCE_NODE_HAS_ID);
785 }
786
787 str = xmlMalloc(size);
788 if (str == NULL) {
790 "generate-id(): out of memory\n");
791 ctxt->error = XPATH_MEMORY_ERROR;
792 goto out;
793 }
794 if (nsPrefix == NULL) {
795 snprintf(str, size, "id%lu", id);
796 } else {
797 size_t i, j;
798
799 snprintf(str, size, "id%luns", id);
800
801 /*
802 * Only ASCII alphanumerics are allowed, so we hex-encode the prefix.
803 */
804 j = strlen(str);
805 for (i = 0; i < nsPrefixSize; i++) {
806 int v;
807
808 v = nsPrefix[i] >> 4;
809 str[j++] = v < 10 ? '0' + v : 'A' + (v - 10);
810 v = nsPrefix[i] & 15;
811 str[j++] = v < 10 ? '0' + v : 'A' + (v - 10);
812 }
813 str[j] = '\0';
814 }
815 valuePush(ctxt, xmlXPathWrapString(BAD_CAST str));
816
817out:
818 xmlXPathFreeObject(obj);
819}
820
829void
830xsltSystemPropertyFunction(xmlXPathParserContextPtr ctxt, int nargs){
831 xmlXPathObjectPtr obj;
833 const xmlChar *nsURI = NULL;
834
835 if (nargs != 1) {
837 "system-property() : expects one string arg\n");
838 ctxt->error = XPATH_INVALID_ARITY;
839 return;
840 }
841 if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_STRING)) {
843 "system-property() : invalid arg expecting a string\n");
844 ctxt->error = XPATH_INVALID_TYPE;
845 return;
846 }
847 obj = valuePop(ctxt);
848 if (obj->stringval == NULL) {
849 valuePush(ctxt, xmlXPathNewString((const xmlChar *)""));
850 } else {
851 name = xmlSplitQName2(obj->stringval, &prefix);
852 if (name == NULL) {
853 name = xmlStrdup(obj->stringval);
854 } else {
855 nsURI = xmlXPathNsLookup(ctxt->context, prefix);
856 if (nsURI == NULL) {
858 "system-property() : prefix %s is not bound\n", prefix);
859 }
860 }
861
862 if (xmlStrEqual(nsURI, XSLT_NAMESPACE)) {
863#ifdef DOCBOOK_XSL_HACK
864 if (xmlStrEqual(name, (const xmlChar *)"vendor")) {
865 xsltStylesheetPtr sheet;
867
868 tctxt = xsltXPathGetTransformContext(ctxt);
869 if ((tctxt != NULL) && (tctxt->inst != NULL) &&
870 (xmlStrEqual(tctxt->inst->name, BAD_CAST "variable")) &&
871 (tctxt->inst->parent != NULL) &&
872 (xmlStrEqual(tctxt->inst->parent->name,
873 BAD_CAST "template")))
874 sheet = tctxt->style;
875 else
876 sheet = NULL;
877 if ((sheet != NULL) && (sheet->doc != NULL) &&
878 (sheet->doc->URL != NULL) &&
879 (xmlStrstr(sheet->doc->URL,
880 (const xmlChar *)"chunk") != NULL)) {
881 valuePush(ctxt, xmlXPathNewString(
882 (const xmlChar *)"libxslt (SAXON 6.2 compatible)"));
883
884 } else {
885 valuePush(ctxt, xmlXPathNewString(
886 (const xmlChar *)XSLT_DEFAULT_VENDOR));
887 }
888 } else
889#else
890 if (xmlStrEqual(name, (const xmlChar *)"vendor")) {
891 valuePush(ctxt, xmlXPathNewString(
892 (const xmlChar *)XSLT_DEFAULT_VENDOR));
893 } else
894#endif
895 if (xmlStrEqual(name, (const xmlChar *)"version")) {
896 valuePush(ctxt, xmlXPathNewString(
897 (const xmlChar *)XSLT_DEFAULT_VERSION));
898 } else if (xmlStrEqual(name, (const xmlChar *)"vendor-url")) {
899 valuePush(ctxt, xmlXPathNewString(
900 (const xmlChar *)XSLT_DEFAULT_URL));
901 } else {
902 valuePush(ctxt, xmlXPathNewString((const xmlChar *)""));
903 }
904 } else {
905 valuePush(ctxt, xmlXPathNewString((const xmlChar *)""));
906 }
907 if (name != NULL)
908 xmlFree(name);
909 if (prefix != NULL)
911 }
912 xmlXPathFreeObject(obj);
913}
914
923void
924xsltElementAvailableFunction(xmlXPathParserContextPtr ctxt, int nargs){
925 xmlXPathObjectPtr obj;
927 const xmlChar *nsURI = NULL;
929
930 if (nargs != 1) {
932 "element-available() : expects one string arg\n");
933 ctxt->error = XPATH_INVALID_ARITY;
934 return;
935 }
936 xmlXPathStringFunction(ctxt, 1);
937 if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_STRING)) {
939 "element-available() : invalid arg expecting a string\n");
940 ctxt->error = XPATH_INVALID_TYPE;
941 return;
942 }
943 obj = valuePop(ctxt);
944 tctxt = xsltXPathGetTransformContext(ctxt);
945 if ((tctxt == NULL) || (tctxt->inst == NULL)) {
947 "element-available() : internal error tctxt == NULL\n");
948 xmlXPathFreeObject(obj);
949 valuePush(ctxt, xmlXPathNewBoolean(0));
950 return;
951 }
952
953
954 name = xmlSplitQName2(obj->stringval, &prefix);
955 if (name == NULL) {
956 xmlNsPtr ns;
957
958 name = xmlStrdup(obj->stringval);
959 ns = xmlSearchNs(tctxt->inst->doc, tctxt->inst, NULL);
960 if (ns != NULL) nsURI = ns->href;
961 } else {
962 nsURI = xmlXPathNsLookup(ctxt->context, prefix);
963 if (nsURI == NULL) {
965 "element-available() : prefix %s is not bound\n", prefix);
966 }
967 }
968
969 if (xsltExtElementLookup(tctxt, name, nsURI) != NULL) {
970 valuePush(ctxt, xmlXPathNewBoolean(1));
971 } else {
972 valuePush(ctxt, xmlXPathNewBoolean(0));
973 }
974
975 xmlXPathFreeObject(obj);
976 if (name != NULL)
977 xmlFree(name);
978 if (prefix != NULL)
980}
981
990void
991xsltFunctionAvailableFunction(xmlXPathParserContextPtr ctxt, int nargs){
992 xmlXPathObjectPtr obj;
994 const xmlChar *nsURI = NULL;
995
996 if (nargs != 1) {
998 "function-available() : expects one string arg\n");
999 ctxt->error = XPATH_INVALID_ARITY;
1000 return;
1001 }
1002 xmlXPathStringFunction(ctxt, 1);
1003 if ((ctxt->value == NULL) || (ctxt->value->type != XPATH_STRING)) {
1005 "function-available() : invalid arg expecting a string\n");
1006 ctxt->error = XPATH_INVALID_TYPE;
1007 return;
1008 }
1009 obj = valuePop(ctxt);
1010
1011 name = xmlSplitQName2(obj->stringval, &prefix);
1012 if (name == NULL) {
1013 name = xmlStrdup(obj->stringval);
1014 } else {
1015 nsURI = xmlXPathNsLookup(ctxt->context, prefix);
1016 if (nsURI == NULL) {
1018 "function-available() : prefix %s is not bound\n", prefix);
1019 }
1020 }
1021
1022 if (xmlXPathFunctionLookupNS(ctxt->context, name, nsURI) != NULL) {
1023 valuePush(ctxt, xmlXPathNewBoolean(1));
1024 } else {
1025 valuePush(ctxt, xmlXPathNewBoolean(0));
1026 }
1027
1028 xmlXPathFreeObject(obj);
1029 if (name != NULL)
1030 xmlFree(name);
1031 if (prefix != NULL)
1032 xmlFree(prefix);
1033}
1034
1043static void
1044xsltCurrentFunction(xmlXPathParserContextPtr ctxt, int nargs){
1046
1047 if (nargs != 0) {
1049 "current() : function uses no argument\n");
1050 ctxt->error = XPATH_INVALID_ARITY;
1051 return;
1052 }
1053 tctxt = xsltXPathGetTransformContext(ctxt);
1054 if (tctxt == NULL) {
1056 "current() : internal error tctxt == NULL\n");
1057 valuePush(ctxt, xmlXPathNewNodeSet(NULL));
1058 } else {
1059 valuePush(ctxt, xmlXPathNewNodeSet(tctxt->node)); /* current */
1060 }
1061}
1062
1063/************************************************************************
1064 * *
1065 * Registration of XSLT and libxslt functions *
1066 * *
1067 ************************************************************************/
1068
1075void
1076xsltRegisterAllFunctions(xmlXPathContextPtr ctxt)
1077{
1078 xmlXPathRegisterFunc(ctxt, (const xmlChar *) "current",
1080 xmlXPathRegisterFunc(ctxt, (const xmlChar *) "document",
1082 xmlXPathRegisterFunc(ctxt, (const xmlChar *) "key", xsltKeyFunction);
1083 xmlXPathRegisterFunc(ctxt, (const xmlChar *) "unparsed-entity-uri",
1085 xmlXPathRegisterFunc(ctxt, (const xmlChar *) "format-number",
1087 xmlXPathRegisterFunc(ctxt, (const xmlChar *) "generate-id",
1089 xmlXPathRegisterFunc(ctxt, (const xmlChar *) "system-property",
1091 xmlXPathRegisterFunc(ctxt, (const xmlChar *) "element-available",
1093 xmlXPathRegisterFunc(ctxt, (const xmlChar *) "function-available",
1095}
xsltTransformContextPtr xsltXPathGetTransformContext(xmlXPathParserContextPtr ctxt)
Definition: extensions.c:1392
xmlXPathFunction xsltExtModuleFunctionLookup(const xmlChar *name, const xmlChar *URI)
Definition: extensions.c:1441
xsltTransformFunction xsltExtElementLookup(xsltTransformContextPtr ctxt, const xmlChar *name, const xmlChar *URI)
Definition: extensions.c:1693
xmlXPathError xsltFormatNumberConversion(xsltDecimalFormatPtr self, xmlChar *format, double number, xmlChar **result)
Definition: numbers.c:957
#define NULL
Definition: types.h:112
#define ULONG_MAX
Definition: limits.h:31
#define USHRT_MAX
Definition: limits.h:23
_ACRTIMP size_t __cdecl strlen(const char *)
Definition: string.c:1592
xsltDocumentPtr xsltNewDocument(xsltTransformContextPtr ctxt, xmlDocPtr doc)
Definition: documents.c:142
xsltDocumentPtr xsltFindDocument(xsltTransformContextPtr ctxt, xmlDocPtr doc)
Definition: documents.c:417
xsltDocumentPtr xsltLoadDocument(xsltTransformContextPtr ctxt, const xmlChar *URI)
Definition: documents.c:283
return ret
Definition: mutex.c:146
void xsltSystemPropertyFunction(xmlXPathParserContextPtr ctxt, int nargs)
Definition: functions.c:830
void xsltDocumentFunction(xmlXPathParserContextPtr ctxt, int nargs)
Definition: functions.c:188
void xsltGenerateIdFunction(xmlXPathParserContextPtr ctxt, int nargs)
Definition: functions.c:695
void xsltRegisterAllFunctions(xmlXPathContextPtr ctxt)
Definition: functions.c:1076
void xsltFormatNumberFunction(xmlXPathParserContextPtr ctxt, int nargs)
Definition: functions.c:608
xmlXPathFunction xsltXPathFunctionLookup(void *vctxt, const xmlChar *name, const xmlChar *ns_uri)
Definition: functions.c:61
void xsltElementAvailableFunction(xmlXPathParserContextPtr ctxt, int nargs)
Definition: functions.c:924
void xsltKeyFunction(xmlXPathParserContextPtr ctxt, int nargs)
Definition: functions.c:357
void xsltUnparsedEntityURIFunction(xmlXPathParserContextPtr ctxt, int nargs)
Definition: functions.c:561
void xsltFunctionAvailableFunction(xmlXPathParserContextPtr ctxt, int nargs)
Definition: functions.c:991
static void xsltCurrentFunction(xmlXPathParserContextPtr ctxt, int nargs)
Definition: functions.c:1044
static void xsltDocumentFunctionLoadDocument(xmlXPathParserContextPtr ctxt, const xmlChar *URI, const xmlChar *fragment)
Definition: functions.c:99
FxCollectionEntry * cur
const GLdouble * v
Definition: gl.h:2040
GLsizeiptr size
Definition: glext.h:5919
GLuint64EXT * result
Definition: glext.h:11304
GLuint id
Definition: glext.h:5910
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
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 GLint GLint j
Definition: glfuncs.h:250
xmlNodeSetPtr xsltGetKey(xsltTransformContextPtr ctxt, const xmlChar *name, const xmlChar *nameURI, const xmlChar *value)
Definition: keys.c:437
XMLPUBFUN xmlEntityPtr xmlGetDocEntity(const xmlDoc *doc, const xmlChar *name)
if(dx< 0)
Definition: linetemp.h:194
#define error(str)
Definition: mkdosfs.c:1605
static const WCHAR url[]
Definition: encode.c:1384
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
xmlFreeFunc xmlFree
Definition: globals.c:184
xmlMallocFunc xmlMalloc
Definition: globals.c:193
void * xmlHashLookup2(xmlHashTablePtr hash, const xmlChar *key, const xmlChar *key2)
Definition: hash.c:754
Definition: uri.h:34
xmlDocPtr doc
xsltDecimalFormatPtr decimalFormat
xsltTransformState state
xsltDocumentPtr document
xsltStylesheetPtr style
unsigned long currentId
Definition: actctx.c:446
Definition: copy.c:22
Definition: name.c:39
Definition: mxnamespace.c:38
BSTR prefix
Definition: mxnamespace.c:39
Definition: tools.h:99
Character const *const prefix
Definition: tempnam.cpp:195
Definition: pdh_main.c:96
XMLPUBFUN xmlChar * xmlBuildURI(const xmlChar *URI, const xmlChar *base)
Definition: uri.c:1902
XMLPUBFUN void xmlFreeURI(xmlURIPtr uri)
Definition: uri.c:1396
XMLPUBFUN xmlURIPtr xmlParseURI(const char *str)
Definition: uri.c:947
XMLPUBFUN xmlChar * xmlSaveUri(xmlURIPtr uri)
Definition: uri.c:1074
wchar_t tm const _CrtWcstime_Writes_and_advances_ptr_ count wchar_t ** out
Definition: wcsftime.cpp:383
#define snprintf
Definition: wintirpc.h:48
XMLPUBFUN int xmlStrlen(const xmlChar *str)
Definition: xmlstring.c:428
XMLPUBFUN const xmlChar * xmlStrstr(const xmlChar *str, const xmlChar *val)
Definition: xmlstring.c:347
#define BAD_CAST
Definition: xmlstring.h:35
XMLPUBFUN int xmlStrEqual(const xmlChar *str1, const xmlChar *str2)
Definition: xmlstring.c:162
unsigned char xmlChar
Definition: xmlstring.h:28
XMLPUBFUN xmlChar * xmlStrdup(const xmlChar *cur)
Definition: xmlstring.c:69
#define XML_CAST_FPTR(fptr)
@ XSLT_STATE_STOPPED
xsltDocument * xsltDocumentPtr
xsltDecimalFormatPtr xsltDecimalFormatGetByQName(xsltStylesheetPtr style, const xmlChar *nsUri, const xmlChar *name)
Definition: xslt.c:379
#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:762
xmlGenericErrorFunc xsltGenericError
Definition: xsltutils.c:586
int xsltSetSourceNodeFlags(xsltTransformContextPtr ctxt, xmlNodePtr node, int flags)
Definition: xsltutils.c:1961
int xsltGetSourceNodeFlags(xmlNodePtr node)
Definition: xsltutils.c:1923
xmlGenericErrorFunc xsltGenericDebug
Definition: xsltutils.c:632
void ** xsltGetPSVIPtr(xmlNodePtr cur)
Definition: xsltutils.c:2030
void * xsltGenericDebugContext
Definition: xsltutils.c:633
void * xsltGenericErrorContext
Definition: xsltutils.c:587
const xmlChar * xsltSplitQName(xmlDictPtr dict, const xmlChar *name, const xmlChar **prefix)
Definition: xsltutils.c:804
#define IS_XSLT_REAL_NODE(n)
Definition: xsltutils.h:68