ReactOS 0.4.16-dev-2206-gc56950d
transform.c
Go to the documentation of this file.
1/*
2 * transform.c: Implementation of the XSL Transformation 1.0 engine
3 * transform part, i.e. applying a Stylesheet to a document
4 *
5 * References:
6 * http://www.w3.org/TR/1999/REC-xslt-19991116
7 *
8 * Michael Kay "XSLT Programmer's Reference" pp 637-643
9 * Writing Multiple Output Files
10 *
11 * XSLT-1.1 Working Draft
12 * http://www.w3.org/TR/xslt11#multiple-output
13 *
14 * See Copyright for the status of this software.
15 *
16 * daniel@veillard.com
17 */
18
19#define IN_LIBXSLT
20#include "libxslt.h"
21
22#include <limits.h>
23#include <string.h>
24#include <stdio.h>
25#include <stddef.h>
26
27#include <libxml/xmlmemory.h>
28#include <libxml/parser.h>
29#include <libxml/tree.h>
30#include <libxml/valid.h>
31#include <libxml/hash.h>
32#include <libxml/encoding.h>
33#include <libxml/xmlerror.h>
34#include <libxml/xpath.h>
37#include <libxml/HTMLtree.h>
38#include <libxml/debugXML.h>
39#include <libxml/uri.h>
40#include "xslt.h"
41#include "xsltInternals.h"
42#include "xsltutils.h"
43#include "xsltlocale.h"
44#include "pattern.h"
45#include "transform.h"
46#include "variables.h"
47#include "numbersInternals.h"
48#include "namespaces.h"
49#include "attributes.h"
50#include "templates.h"
51#include "imports.h"
52#include "keys.h"
53#include "documents.h"
54#include "extensions.h"
55#include "extra.h"
56#include "preproc.h"
57#include "security.h"
58
59#ifdef WITH_XSLT_DEBUG
60#define WITH_XSLT_DEBUG_EXTRA
61#define WITH_XSLT_DEBUG_PROCESS
62#define WITH_XSLT_DEBUG_VARIABLE
63#endif
64
65#define XSLT_GENERATE_HTML_DOCTYPE
66#ifdef XSLT_GENERATE_HTML_DOCTYPE
67static int xsltGetHTMLIDs(const xmlChar *version, const xmlChar **publicID,
68 const xmlChar **systemID);
69#endif
70
71int xsltMaxDepth = 3000;
72int xsltMaxVars = 15000;
73
74/*
75 * Useful macros
76 */
77
78#ifndef FALSE
79# define FALSE (0 == 1)
80# define TRUE (!FALSE)
81#endif
82
83#define IS_BLANK_NODE(n) \
84 (((n)->type == XML_TEXT_NODE) && (xsltIsBlank((n)->content)))
85
86
87/*
88* Forward declarations
89*/
90
91static xmlNsPtr
92xsltCopyNamespaceListInternal(xmlNodePtr node, xmlNsPtr cur);
93
94static xmlNodePtr
95xsltCopyTree(xsltTransformContextPtr ctxt, xmlNodePtr invocNode,
96 xmlNodePtr node, xmlNodePtr insert, int isLRE,
97 int topElemVisited);
98
99static void
101 xmlNodePtr contextNode, xmlNodePtr list,
102 xsltTemplatePtr templ);
103
104static void
106 xmlNodePtr contextNode,
107 xmlNodePtr list,
108 xsltTemplatePtr templ,
109 xsltStackElemPtr withParams);
110
120static int
122{
123 if (ctxt->templNr >= ctxt->templMax) {
124 xsltTemplatePtr *tmp;
125 int newMax = ctxt->templMax == 0 ? 4 : ctxt->templMax * 2;
126
127 tmp = (xsltTemplatePtr *) xmlRealloc(ctxt->templTab,
128 newMax * sizeof(*tmp));
129 if (tmp == NULL) {
130 xmlGenericError(xmlGenericErrorContext, "realloc failed !\n");
131 return (0);
132 }
133 ctxt->templTab = tmp;
134 ctxt->templMax = newMax;
135 }
136 ctxt->templTab[ctxt->templNr] = value;
137 ctxt->templ = value;
138 return (ctxt->templNr++);
139}
148static xsltTemplatePtr
150{
152
153 if (ctxt->templNr <= 0)
154 return (0);
155 ctxt->templNr--;
156 if (ctxt->templNr > 0)
157 ctxt->templ = ctxt->templTab[ctxt->templNr - 1];
158 else
159 ctxt->templ = (xsltTemplatePtr) 0;
160 ret = ctxt->templTab[ctxt->templNr];
161 ctxt->templTab[ctxt->templNr] = 0;
162 return (ret);
163}
164
177void
179{
181
182 if (ctxt->varsNr <= 0)
183 return;
184
185 do {
186 if (ctxt->varsNr <= limitNr)
187 break;
188 variable = ctxt->varsTab[ctxt->varsNr - 1];
189 if (variable->level <= level)
190 break;
191 if (variable->level >= 0)
193 ctxt->varsNr--;
194 } while (ctxt->varsNr != 0);
195 if (ctxt->varsNr > 0)
196 ctxt->vars = ctxt->varsTab[ctxt->varsNr - 1];
197 else
198 ctxt->vars = NULL;
199}
200
207static void
209{
211
212 for (; ctxt->varsNr > ctxt->varsBase; ctxt->varsNr--) {
213 param = ctxt->varsTab[ctxt->varsNr -1];
214 /*
215 * Free xsl:param items.
216 * xsl:with-param items will have a level of -1 or -2.
217 */
218 if (param->level >= 0) {
220 }
221 }
222 if (ctxt->varsNr > 0)
223 ctxt->vars = ctxt->varsTab[ctxt->varsNr - 1];
224 else
225 ctxt->vars = NULL;
226}
227
228#ifdef WITH_PROFILER
229
239static int
240profPush(xsltTransformContextPtr ctxt, long value)
241{
242 if (ctxt->profMax == 0) {
243 ctxt->profMax = 4;
244 ctxt->profTab =
245 (long *) xmlMalloc(ctxt->profMax * sizeof(ctxt->profTab[0]));
246 if (ctxt->profTab == NULL) {
247 xmlGenericError(xmlGenericErrorContext, "malloc failed !\n");
248 return (0);
249 }
250 }
251 else if (ctxt->profNr >= ctxt->profMax) {
252 ctxt->profMax *= 2;
253 ctxt->profTab =
254 (long *) xmlRealloc(ctxt->profTab,
255 ctxt->profMax * sizeof(ctxt->profTab[0]));
256 if (ctxt->profTab == NULL) {
257 xmlGenericError(xmlGenericErrorContext, "realloc failed !\n");
258 return (0);
259 }
260 }
261 ctxt->profTab[ctxt->profNr] = value;
262 ctxt->prof = value;
263 return (ctxt->profNr++);
264}
273static long
274profPop(xsltTransformContextPtr ctxt)
275{
276 long ret;
277
278 if (ctxt->profNr <= 0)
279 return (0);
280 ctxt->profNr--;
281 if (ctxt->profNr > 0)
282 ctxt->prof = ctxt->profTab[ctxt->profNr - 1];
283 else
284 ctxt->prof = (long) 0;
285 ret = ctxt->profTab[ctxt->profNr];
286 ctxt->profTab[ctxt->profNr] = 0;
287 return (ret);
288}
289
290static void
291profCallgraphAdd(xsltTemplatePtr templ, xsltTemplatePtr parent)
292{
293 int i;
294
295 if (templ->templMax == 0) {
296 templ->templMax = 4;
297 templ->templCalledTab =
299 sizeof(templ->templCalledTab[0]));
300 templ->templCountTab =
301 (int *) xmlMalloc(templ->templMax *
302 sizeof(templ->templCountTab[0]));
303 if (templ->templCalledTab == NULL || templ->templCountTab == NULL) {
304 xmlGenericError(xmlGenericErrorContext, "malloc failed !\n");
305 return;
306 }
307 }
308 else if (templ->templNr >= templ->templMax) {
309 templ->templMax *= 2;
310 templ->templCalledTab =
312 templ->templMax *
313 sizeof(templ->templCalledTab[0]));
314 templ->templCountTab =
315 (int *) xmlRealloc(templ->templCountTab,
316 templ->templMax *
317 sizeof(templ->templCountTab[0]));
318 if (templ->templCalledTab == NULL || templ->templCountTab == NULL) {
319 xmlGenericError(xmlGenericErrorContext, "realloc failed !\n");
320 return;
321 }
322 }
323
324 for (i = 0; i < templ->templNr; i++) {
325 if (templ->templCalledTab[i] == parent) {
326 templ->templCountTab[i]++;
327 break;
328 }
329 }
330 if (i == templ->templNr) {
331 /* not found, add new one */
332 templ->templCalledTab[templ->templNr] = parent;
333 templ->templCountTab[templ->templNr] = 1;
334 templ->templNr++;
335 }
336}
337
338#endif /* WITH_PROFILER */
339
348static xmlXPathObjectPtr
350 xsltStylePreCompPtr comp) {
351 xmlXPathObjectPtr res;
352 xmlXPathContextPtr xpctxt;
353 xmlNodePtr oldXPContextNode;
354 xmlNsPtr *oldXPNamespaces;
355 int oldXPProximityPosition, oldXPContextSize, oldXPNsNr;
356
357 xpctxt = ctxt->xpathCtxt;
358 oldXPContextNode = xpctxt->node;
359 oldXPProximityPosition = xpctxt->proximityPosition;
360 oldXPContextSize = xpctxt->contextSize;
361 oldXPNsNr = xpctxt->nsNr;
362 oldXPNamespaces = xpctxt->namespaces;
363
364 xpctxt->node = node;
365#ifdef XSLT_REFACTORED
366 if (comp->inScopeNs != NULL) {
367 xpctxt->namespaces = comp->inScopeNs->list;
368 xpctxt->nsNr = comp->inScopeNs->xpathNumber;
369 } else {
370 xpctxt->namespaces = NULL;
371 xpctxt->nsNr = 0;
372 }
373#else
374 xpctxt->namespaces = comp->nsList;
375 xpctxt->nsNr = comp->nsNr;
376#endif
377
378 res = xmlXPathCompiledEval(comp->comp, xpctxt);
379
380 xpctxt->node = oldXPContextNode;
381 xpctxt->proximityPosition = oldXPProximityPosition;
382 xpctxt->contextSize = oldXPContextSize;
383 xpctxt->nsNr = oldXPNsNr;
384 xpctxt->namespaces = oldXPNamespaces;
385
386 return(res);
387}
388
397static int
399 xsltStylePreCompPtr comp) {
400 int res;
401 xmlXPathContextPtr xpctxt;
402 xmlNodePtr oldXPContextNode;
403 xmlNsPtr *oldXPNamespaces;
404 int oldXPProximityPosition, oldXPContextSize, oldXPNsNr;
405
406 xpctxt = ctxt->xpathCtxt;
407 oldXPContextNode = xpctxt->node;
408 oldXPProximityPosition = xpctxt->proximityPosition;
409 oldXPContextSize = xpctxt->contextSize;
410 oldXPNsNr = xpctxt->nsNr;
411 oldXPNamespaces = xpctxt->namespaces;
412
413 xpctxt->node = node;
414#ifdef XSLT_REFACTORED
415 if (comp->inScopeNs != NULL) {
416 xpctxt->namespaces = comp->inScopeNs->list;
417 xpctxt->nsNr = comp->inScopeNs->xpathNumber;
418 } else {
419 xpctxt->namespaces = NULL;
420 xpctxt->nsNr = 0;
421 }
422#else
423 xpctxt->namespaces = comp->nsList;
424 xpctxt->nsNr = comp->nsNr;
425#endif
426
427 res = xmlXPathCompiledEvalToBoolean(comp->comp, xpctxt);
428
429 xpctxt->node = oldXPContextNode;
430 xpctxt->proximityPosition = oldXPProximityPosition;
431 xpctxt->contextSize = oldXPContextSize;
432 xpctxt->nsNr = oldXPNsNr;
433 xpctxt->namespaces = oldXPNamespaces;
434
435 return(res);
436}
437
438/************************************************************************
439 * *
440 * XInclude default settings *
441 * *
442 ************************************************************************/
443
445
452void
454 xsltDoXIncludeDefault = (xinclude != 0);
455}
456
464int
466 return(xsltDoXIncludeDefault);
467}
468
469static unsigned long xsltDefaultTrace = (unsigned long) XSLT_TRACE_ALL;
470
479}
480
489 return xsltDefaultTrace;
490}
491
492/************************************************************************
493 * *
494 * Handling of Transformation Contexts *
495 * *
496 ************************************************************************/
497
500{
502
504 if (ret == NULL) {
506 "xsltTransformCacheCreate : malloc failed\n");
507 return(NULL);
508 }
509 memset(ret, 0, sizeof(xsltTransformCache));
510 return(ret);
511}
512
513static void
515{
516 if (cache == NULL)
517 return;
518 /*
519 * Free tree fragments.
520 */
521 if (cache->RVT) {
522 xmlDocPtr tmp, cur = cache->RVT;
523 while (cur) {
524 tmp = cur;
525 cur = (xmlDocPtr) cur->next;
526 if (tmp->_private != NULL) {
527 /*
528 * Tree the document info.
529 */
530 xsltFreeDocumentKeys((xsltDocumentPtr) tmp->_private);
531 xmlFree(tmp->_private);
532 }
533 xmlFreeDoc(tmp);
534 }
535 }
536 /*
537 * Free vars/params.
538 */
539 if (cache->stackItems) {
540 xsltStackElemPtr tmp, cur = cache->stackItems;
541 while (cur) {
542 tmp = cur;
543 cur = cur->next;
544 /*
545 * REVISIT TODO: Should be call a destruction-function
546 * instead?
547 */
548 xmlFree(tmp);
549 }
550 }
551 xmlFree(cache);
552}
553
566 xsltDocumentPtr docu;
567 int i;
568
570
572 if (cur == NULL) {
573 xsltTransformError(NULL, NULL, (xmlNodePtr)doc,
574 "xsltNewTransformContext : malloc failed\n");
575 return(NULL);
576 }
577 memset(cur, 0, sizeof(xsltTransformContext));
578
579 cur->cache = xsltTransformCacheCreate();
580 if (cur->cache == NULL)
581 goto internal_err;
582 /*
583 * setup of the dictionary must be done early as some of the
584 * processing later like key handling may need it.
585 */
586 cur->dict = xmlDictCreateSub(style->dict);
587 cur->internalized = ((style->internalized) && (cur->dict != NULL));
588#ifdef WITH_XSLT_DEBUG
590 "Creating sub-dictionary from stylesheet for transformation\n");
591#endif
592
593 /*
594 * initialize the template stack
595 */
596 cur->templTab = (xsltTemplatePtr *)
597 xmlMalloc(10 * sizeof(xsltTemplatePtr));
598 if (cur->templTab == NULL) {
599 xsltTransformError(NULL, NULL, (xmlNodePtr) doc,
600 "xsltNewTransformContext: out of memory\n");
601 goto internal_err;
602 }
603 cur->templNr = 0;
604 cur->templMax = 5;
605 cur->templ = NULL;
606 cur->maxTemplateDepth = xsltMaxDepth;
607
608 /*
609 * initialize the variables stack
610 */
611 cur->varsTab = (xsltStackElemPtr *)
612 xmlMalloc(10 * sizeof(xsltStackElemPtr));
613 if (cur->varsTab == NULL) {
615 "xsltNewTransformContext: out of memory\n");
616 goto internal_err;
617 }
618 cur->varsNr = 0;
619 cur->varsMax = 10;
620 cur->vars = NULL;
621 cur->varsBase = 0;
622 cur->maxTemplateVars = xsltMaxVars;
623
624 /*
625 * the profiling stack is not initialized by default
626 */
627 cur->profTab = NULL;
628 cur->profNr = 0;
629 cur->profMax = 0;
630 cur->prof = 0;
631
632 cur->style = style;
633 cur->xpathCtxt = xmlXPathNewContext(doc);
634 if (cur->xpathCtxt == NULL) {
635 xsltTransformError(NULL, NULL, (xmlNodePtr) doc,
636 "xsltNewTransformContext : xmlXPathNewContext failed\n");
637 goto internal_err;
638 }
639 /*
640 * Create an XPath cache.
641 */
642 if (xmlXPathContextSetCache(cur->xpathCtxt, 1, -1, 0) == -1)
643 goto internal_err;
644 /*
645 * Initialize the extras array
646 */
647 if (style->extrasNr != 0) {
648 cur->extrasMax = style->extrasNr + 20;
649 cur->extras = (xsltRuntimeExtraPtr)
650 xmlMalloc(cur->extrasMax * sizeof(xsltRuntimeExtra));
651 if (cur->extras == NULL) {
653 "xsltNewTransformContext: out of memory\n");
654 goto internal_err;
655 }
656 cur->extrasNr = style->extrasNr;
657 for (i = 0;i < cur->extrasMax;i++) {
658 cur->extras[i].info = NULL;
659 cur->extras[i].deallocate = NULL;
660 cur->extras[i].val.ptr = NULL;
661 }
662 } else {
663 cur->extras = NULL;
664 cur->extrasNr = 0;
665 cur->extrasMax = 0;
666 }
667
670 cur->xpathCtxt->nsHash = style->nsHash;
671 /*
672 * Initialize the registered external modules
673 */
675 /*
676 * Setup document element ordering for later efficiencies
677 * (bug 133289)
678 */
680 xmlXPathOrderDocElems(doc);
681 /*
682 * Must set parserOptions before calling xsltNewDocument
683 * (bug 164530)
684 */
685 cur->parserOptions = XSLT_PARSE_OPTIONS;
686 docu = xsltNewDocument(cur, doc);
687 if (docu == NULL) {
688 xsltTransformError(cur, NULL, (xmlNodePtr)doc,
689 "xsltNewTransformContext : xsltNewDocument failed\n");
690 goto internal_err;
691 }
692 docu->main = 1;
693 cur->document = docu;
694 cur->inst = NULL;
695 cur->outputFile = NULL;
697 cur->debugStatus = xslDebugStatus;
698 cur->traceCode = (unsigned long*) &xsltDefaultTrace;
699 cur->xinclude = xsltGetXIncludeDefault();
700 cur->keyInitLevel = 0;
701
702 cur->newLocale = xsltNewLocale;
703 cur->freeLocale = xsltFreeLocale;
704 cur->genSortKey = xsltStrxfrm;
705
706 return(cur);
707
708internal_err:
709 if (cur != NULL)
711 return(NULL);
712}
713
720void
722 if (ctxt == NULL)
723 return;
724
725 /*
726 * Shutdown the extension modules associated to the stylesheet
727 * used if needed.
728 */
730
731 if (ctxt->xpathCtxt != NULL) {
732 ctxt->xpathCtxt->nsHash = NULL;
733 xmlXPathFreeContext(ctxt->xpathCtxt);
734 }
735 if (ctxt->templTab != NULL)
736 xmlFree(ctxt->templTab);
737 if (ctxt->varsTab != NULL)
738 xmlFree(ctxt->varsTab);
739 if (ctxt->profTab != NULL)
740 xmlFree(ctxt->profTab);
741 if ((ctxt->extrasNr > 0) && (ctxt->extras != NULL)) {
742 int i;
743
744 for (i = 0;i < ctxt->extrasNr;i++) {
745 if ((ctxt->extras[i].deallocate != NULL) &&
746 (ctxt->extras[i].info != NULL))
747 ctxt->extras[i].deallocate(ctxt->extras[i].info);
748 }
749 xmlFree(ctxt->extras);
750 }
752 xsltFreeDocuments(ctxt);
753 xsltFreeCtxtExts(ctxt);
754 xsltFreeRVTs(ctxt);
756 xmlDictFree(ctxt->dict);
757#ifdef WITH_XSLT_DEBUG
759 "freeing transformation dictionary\n");
760#endif
761 memset(ctxt, -1, sizeof(xsltTransformContext));
762 xmlFree(ctxt);
763}
764
765/************************************************************************
766 * *
767 * Copy of Nodes in an XSLT fashion *
768 * *
769 ************************************************************************/
770
782static xmlNodePtr
783xsltAddChild(xmlNodePtr parent, xmlNodePtr cur) {
784 xmlNodePtr ret;
785
786 if (cur == NULL)
787 return(NULL);
788 if (parent == NULL) {
789 xmlFreeNode(cur);
790 return(NULL);
791 }
792 ret = xmlAddChild(parent, cur);
793
794 return(ret);
795}
796
808static xmlNodePtr
810 const xmlChar *string, int len) {
811 /*
812 * optimization
813 */
814 if ((len <= 0) || (string == NULL) || (target == NULL))
815 return(target);
816
817 if (ctxt->lasttext == target->content) {
818 int minSize;
819
820 /* Check for integer overflow accounting for NUL terminator. */
821 if (len >= INT_MAX - ctxt->lasttuse) {
823 "xsltCopyText: text allocation failed\n");
824 return(NULL);
825 }
826 minSize = ctxt->lasttuse + len + 1;
827
828 if (ctxt->lasttsize < minSize) {
829 xmlChar *newbuf;
830 int size;
831 int extra;
832
833 /* Double buffer size but increase by at least 100 bytes. */
834 extra = minSize < 100 ? 100 : minSize;
835
836 /* Check for integer overflow. */
837 if (extra > INT_MAX - ctxt->lasttsize) {
838 size = INT_MAX;
839 }
840 else {
841 size = ctxt->lasttsize + extra;
842 }
843
844 newbuf = (xmlChar *) xmlRealloc(target->content,size);
845 if (newbuf == NULL) {
847 "xsltCopyText: text allocation failed\n");
848 return(NULL);
849 }
850 ctxt->lasttsize = size;
851 ctxt->lasttext = newbuf;
852 target->content = newbuf;
853 }
854 memcpy(&(target->content[ctxt->lasttuse]), string, len);
855 ctxt->lasttuse += len;
856 target->content[ctxt->lasttuse] = 0;
857 } else {
858 xmlNodeAddContent(target, string);
859 ctxt->lasttext = target->content;
860 len = xmlStrlen(target->content);
861 ctxt->lasttsize = len;
862 ctxt->lasttuse = len;
863 }
864 return(target);
865}
866
880xmlNodePtr
882 const xmlChar *string, int noescape)
883{
884 xmlNodePtr copy;
885 int len;
886
887 if (string == NULL)
888 return(NULL);
889
890#ifdef WITH_XSLT_DEBUG_PROCESS
892 "xsltCopyTextString: copy text %s\n",
893 string));
894#endif
895
896 /*
897 * Play safe and reset the merging mechanism for every new
898 * target node.
899 */
900 if ((target == NULL) || (target->children == NULL)) {
901 ctxt->lasttext = NULL;
902 }
903
904 /* handle coalescing of text nodes here */
905 len = xmlStrlen(string);
906 if ((ctxt->type == XSLT_OUTPUT_XML) &&
907 (ctxt->style->cdataSection != NULL) &&
908 (target != NULL) &&
909 (target->type == XML_ELEMENT_NODE) &&
910 (((target->ns == NULL) &&
912 target->name, NULL) != NULL)) ||
913 ((target->ns != NULL) &&
915 target->name, target->ns->href) != NULL))))
916 {
917 /*
918 * Process "cdata-section-elements".
919 */
920 if ((target->last != NULL) &&
921 (target->last->type == XML_CDATA_SECTION_NODE))
922 {
923 return(xsltAddTextString(ctxt, target->last, string, len));
924 }
925 copy = xmlNewCDataBlock(ctxt->output, string, len);
926 } else if (noescape) {
927 /*
928 * Process "disable-output-escaping".
929 */
930 if ((target != NULL) && (target->last != NULL) &&
931 (target->last->type == XML_TEXT_NODE) &&
932 (target->last->name == xmlStringTextNoenc))
933 {
934 return(xsltAddTextString(ctxt, target->last, string, len));
935 }
936 copy = xmlNewTextLen(string, len);
937 if (copy != NULL)
938 copy->name = xmlStringTextNoenc;
939 } else {
940 /*
941 * Default processing.
942 */
943 if ((target != NULL) && (target->last != NULL) &&
944 (target->last->type == XML_TEXT_NODE) &&
945 (target->last->name == xmlStringText)) {
946 return(xsltAddTextString(ctxt, target->last, string, len));
947 }
948 copy = xmlNewTextLen(string, len);
949 }
950 if (copy != NULL && target != NULL)
952 if (copy != NULL) {
953 ctxt->lasttext = copy->content;
954 ctxt->lasttsize = len;
955 ctxt->lasttuse = len;
956 } else {
958 "xsltCopyTextString: text copy failed\n");
959 ctxt->lasttext = NULL;
960 }
961 return(copy);
962}
963
976static xmlNodePtr
978 xmlNodePtr cur, int interned)
979{
980 xmlNodePtr copy;
981
982 if ((cur->type != XML_TEXT_NODE) &&
983 (cur->type != XML_CDATA_SECTION_NODE))
984 return(NULL);
985 if (cur->content == NULL)
986 return(NULL);
987
988#ifdef WITH_XSLT_DEBUG_PROCESS
989 if (cur->type == XML_CDATA_SECTION_NODE) {
991 "xsltCopyText: copy CDATA text %s\n",
992 cur->content));
993 } else if (cur->name == xmlStringTextNoenc) {
995 "xsltCopyText: copy unescaped text %s\n",
996 cur->content));
997 } else {
999 "xsltCopyText: copy text %s\n",
1000 cur->content));
1001 }
1002#endif
1003
1004 /*
1005 * Play save and reset the merging mechanism for every new
1006 * target node.
1007 */
1008 if ((target == NULL) || (target->children == NULL)) {
1009 ctxt->lasttext = NULL;
1010 }
1011
1012 if ((ctxt->style->cdataSection != NULL) &&
1013 (ctxt->type == XSLT_OUTPUT_XML) &&
1014 (target != NULL) &&
1015 (target->type == XML_ELEMENT_NODE) &&
1016 (((target->ns == NULL) &&
1018 target->name, NULL) != NULL)) ||
1019 ((target->ns != NULL) &&
1021 target->name, target->ns->href) != NULL))))
1022 {
1023 /*
1024 * Process "cdata-section-elements".
1025 */
1026 /*
1027 * OPTIMIZE TODO: xsltCopyText() is also used for attribute content.
1028 */
1029 /*
1030 * TODO: Since this doesn't merge adjacent CDATA-section nodes,
1031 * we'll get: <![CDATA[x]]><!CDATA[y]]>.
1032 * TODO: Reported in #321505.
1033 */
1034 if ((target->last != NULL) &&
1035 (target->last->type == XML_CDATA_SECTION_NODE))
1036 {
1037 /*
1038 * Append to existing CDATA-section node.
1039 */
1040 copy = xsltAddTextString(ctxt, target->last, cur->content,
1041 xmlStrlen(cur->content));
1042 goto exit;
1043 } else {
1044 unsigned int len;
1045
1046 len = xmlStrlen(cur->content);
1047 copy = xmlNewCDataBlock(ctxt->output, cur->content, len);
1048 if (copy == NULL)
1049 goto exit;
1050 ctxt->lasttext = copy->content;
1051 ctxt->lasttsize = len;
1052 ctxt->lasttuse = len;
1053 }
1054 } else if ((target != NULL) &&
1055 (target->last != NULL) &&
1056 /* both escaped or both non-escaped text-nodes */
1057 (((target->last->type == XML_TEXT_NODE) &&
1058 (target->last->name == cur->name)) ||
1059 /* non-escaped text nodes and CDATA-section nodes */
1060 (((target->last->type == XML_CDATA_SECTION_NODE) &&
1061 (cur->name == xmlStringTextNoenc)))))
1062 {
1063 /*
1064 * we are appending to an existing text node
1065 */
1066 copy = xsltAddTextString(ctxt, target->last, cur->content,
1067 xmlStrlen(cur->content));
1068 goto exit;
1069 } else if ((interned) && (target != NULL) &&
1070 (target->doc != NULL) &&
1071 (target->doc->dict == ctxt->dict))
1072 {
1073 /*
1074 * TODO: DO we want to use this also for "text" output?
1075 */
1076 copy = xmlNewTextLen(NULL, 0);
1077 if (copy == NULL)
1078 goto exit;
1079 if (cur->name == xmlStringTextNoenc)
1080 copy->name = xmlStringTextNoenc;
1081
1082 /*
1083 * Must confirm that content is in dict (bug 302821)
1084 * TODO: This check should be not needed for text coming
1085 * from the stylesheets
1086 */
1087 if (xmlDictOwns(ctxt->dict, cur->content))
1088 copy->content = cur->content;
1089 else {
1090 if ((copy->content = xmlStrdup(cur->content)) == NULL) {
1091 xmlFreeNode(copy);
1092 return NULL;
1093 }
1094 }
1095
1096 ctxt->lasttext = NULL;
1097 } else {
1098 /*
1099 * normal processing. keep counters to extend the text node
1100 * in xsltAddTextString if needed.
1101 */
1102 unsigned int len;
1103
1104 len = xmlStrlen(cur->content);
1105 copy = xmlNewTextLen(cur->content, len);
1106 if (copy == NULL)
1107 goto exit;
1108 if (cur->name == xmlStringTextNoenc)
1109 copy->name = xmlStringTextNoenc;
1110 ctxt->lasttext = copy->content;
1111 ctxt->lasttsize = len;
1112 ctxt->lasttuse = len;
1113 }
1114 if (copy != NULL) {
1115 if (target != NULL) {
1116 copy->doc = target->doc;
1117 /*
1118 * MAYBE TODO: Maybe we should reset the ctxt->lasttext here
1119 * to ensure that the optimized text-merging mechanism
1120 * won't interfere with normal node-merging in any case.
1121 */
1123 }
1124 } else {
1126 "xsltCopyText: text copy failed\n");
1127 }
1128
1129exit:
1130 if ((copy == NULL) || (copy->content == NULL)) {
1132 "Internal error in xsltCopyText(): "
1133 "Failed to copy the string.\n");
1134 ctxt->state = XSLT_STATE_STOPPED;
1135 }
1136 return(copy);
1137}
1138
1154static xmlAttrPtr
1156 xmlNodePtr target, xmlAttrPtr attr)
1157{
1158 xmlAttrPtr copy;
1159 xmlChar *value;
1160
1161 if (attr == NULL)
1162 return(NULL);
1163
1164 if (target->type != XML_ELEMENT_NODE) {
1165 xsltTransformError(ctxt, NULL, invocNode,
1166 "Cannot add an attribute node to a non-element node.\n");
1167 return(NULL);
1168 }
1169
1170 if (target->children != NULL) {
1171 xsltTransformError(ctxt, NULL, invocNode,
1172 "Attribute nodes must be added before "
1173 "any child nodes to an element.\n");
1174 return(NULL);
1175 }
1176
1177 value = xmlNodeListGetString(attr->doc, attr->children, 1);
1178 if (attr->ns != NULL) {
1179 xmlNsPtr ns;
1180
1181 ns = xsltGetSpecialNamespace(ctxt, invocNode,
1182 attr->ns->href, attr->ns->prefix, target);
1183 if (ns == NULL) {
1184 xsltTransformError(ctxt, NULL, invocNode,
1185 "Namespace fixup error: Failed to acquire an in-scope "
1186 "namespace binding of the copied attribute '{%s}%s'.\n",
1187 attr->ns->href, attr->name);
1188 /*
1189 * TODO: Should we just stop here?
1190 */
1191 }
1192 /*
1193 * Note that xmlSetNsProp() will take care of duplicates
1194 * and assigns the new namespace even to a duplicate.
1195 */
1196 copy = xmlSetNsProp(target, ns, attr->name, value);
1197 } else {
1198 copy = xmlSetNsProp(target, NULL, attr->name, value);
1199 }
1200 if (value != NULL)
1201 xmlFree(value);
1202
1203 if (copy == NULL)
1204 return(NULL);
1205
1206#if 0
1207 /*
1208 * NOTE: This was optimized according to bug #342695.
1209 * TODO: Can this further be optimized, if source and target
1210 * share the same dict and attr->children is just 1 text node
1211 * which is in the dict? How probable is such a case?
1212 */
1213 /*
1214 * TODO: Do we need to create an empty text node if the value
1215 * is the empty string?
1216 */
1217 value = xmlNodeListGetString(attr->doc, attr->children, 1);
1218 if (value != NULL) {
1219 txtNode = xmlNewDocText(target->doc, NULL);
1220 if (txtNode == NULL)
1221 return(NULL);
1222 if ((target->doc != NULL) &&
1223 (target->doc->dict != NULL))
1224 {
1225 txtNode->content =
1226 (xmlChar *) xmlDictLookup(target->doc->dict,
1227 BAD_CAST value, -1);
1228 xmlFree(value);
1229 } else
1230 txtNode->content = value;
1231 copy->children = txtNode;
1232 }
1233#endif
1234
1235 return(copy);
1236}
1237
1253static int
1255 xmlNodePtr invocNode,
1256 xmlNodePtr target, xmlAttrPtr attr)
1257{
1258 xmlAttrPtr copy;
1259 xmlNsPtr origNs = NULL, copyNs = NULL;
1260 xmlChar *value;
1261
1262 /*
1263 * Don't use xmlCopyProp() here, since it will try to
1264 * reconciliate namespaces.
1265 */
1266 while (attr != NULL) {
1267 /*
1268 * Find a namespace node in the tree of @target.
1269 * Avoid searching for the same ns.
1270 */
1271 if (attr->ns != origNs) {
1272 origNs = attr->ns;
1273 if (attr->ns != NULL) {
1274 copyNs = xsltGetSpecialNamespace(ctxt, invocNode,
1275 attr->ns->href, attr->ns->prefix, target);
1276 if (copyNs == NULL)
1277 return(-1);
1278 } else
1279 copyNs = NULL;
1280 }
1281 /*
1282 * If attribute has a value, we need to copy it (watching out
1283 * for possible entities)
1284 */
1285 if ((attr->children) && (attr->children->type == XML_TEXT_NODE) &&
1286 (attr->children->next == NULL)) {
1287 copy = xmlNewNsProp(target, copyNs, attr->name,
1288 attr->children->content);
1289 } else if (attr->children != NULL) {
1290 value = xmlNodeListGetString(attr->doc, attr->children, 1);
1291 copy = xmlNewNsProp(target, copyNs, attr->name, BAD_CAST value);
1292 xmlFree(value);
1293 } else {
1294 copy = xmlNewNsProp(target, copyNs, attr->name, NULL);
1295 }
1296
1297 if (copy == NULL)
1298 return(-1);
1299
1300 attr = attr->next;
1301 }
1302 return(0);
1303}
1304
1329static xmlNodePtr
1331 xmlNodePtr insert, int isLRE)
1332{
1333 xmlNodePtr copy;
1334
1335 if ((node->type == XML_DTD_NODE) || (insert == NULL))
1336 return(NULL);
1337 if ((node->type == XML_TEXT_NODE) ||
1338 (node->type == XML_CDATA_SECTION_NODE))
1339 return(xsltCopyText(ctxt, insert, node, 0));
1340
1341 copy = xmlDocCopyNode(node, insert->doc, 0);
1342 if (copy != NULL) {
1343 copy->doc = ctxt->output;
1344 copy = xsltAddChild(insert, copy);
1345 if (copy == NULL) {
1347 "xsltShallowCopyElem: copy failed\n");
1348 return (copy);
1349 }
1350
1351 if (node->type == XML_ELEMENT_NODE) {
1352 /*
1353 * Add namespaces as they are needed
1354 */
1355 if (node->nsDef != NULL) {
1356 /*
1357 * TODO: Remove the LRE case in the refactored code
1358 * gets enabled.
1359 */
1360 if (isLRE)
1361 xsltCopyNamespaceList(ctxt, copy, node->nsDef);
1362 else
1364 }
1365
1366 /*
1367 * URGENT TODO: The problem with this is that it does not
1368 * copy over all namespace nodes in scope.
1369 * The damn thing about this is, that we would need to
1370 * use the xmlGetNsList(), for every single node; this is
1371 * also done in xsltCopyTree(), but only for the top node.
1372 */
1373 if (node->ns != NULL) {
1374 if (isLRE) {
1375 /*
1376 * REVISIT TODO: Since the non-refactored code still does
1377 * ns-aliasing, we need to call xsltGetNamespace() here.
1378 * Remove this when ready.
1379 */
1380 copy->ns = xsltGetNamespace(ctxt, node, node->ns, copy);
1381 } else {
1382 copy->ns = xsltGetSpecialNamespace(ctxt,
1383 node, node->ns->href, node->ns->prefix, copy);
1384
1385 }
1386 } else if ((insert->type == XML_ELEMENT_NODE) &&
1387 (insert->ns != NULL))
1388 {
1389 /*
1390 * "Undeclare" the default namespace.
1391 */
1393 }
1394 }
1395 } else {
1397 "xsltShallowCopyElem: copy %s failed\n", node->name);
1398 }
1399 return(copy);
1400}
1401
1421static xmlNodePtr
1423 xmlNodePtr list,
1424 xmlNodePtr insert, int isLRE, int topElemVisited)
1425{
1426 xmlNodePtr copy, ret = NULL;
1427
1428 while (list != NULL) {
1429 copy = xsltCopyTree(ctxt, invocNode,
1430 list, insert, isLRE, topElemVisited);
1431 if (copy != NULL) {
1432 if (ret == NULL) {
1433 ret = copy;
1434 }
1435 }
1436 list = list->next;
1437 }
1438 return(ret);
1439}
1440
1457static xmlNsPtr
1459 xmlNsPtr ret = NULL;
1460 xmlNsPtr p = NULL, q, luNs;
1461
1462 if (ns == NULL)
1463 return(NULL);
1464 /*
1465 * One can add namespaces only on element nodes
1466 */
1467 if ((elem != NULL) && (elem->type != XML_ELEMENT_NODE))
1468 elem = NULL;
1469
1470 do {
1471 if (ns->type != XML_NAMESPACE_DECL)
1472 break;
1473 /*
1474 * Avoid duplicating namespace declarations on the tree.
1475 */
1476 if (elem != NULL) {
1477 if ((elem->ns != NULL) &&
1478 xmlStrEqual(elem->ns->prefix, ns->prefix) &&
1479 xmlStrEqual(elem->ns->href, ns->href))
1480 {
1481 ns = ns->next;
1482 continue;
1483 }
1484 luNs = xmlSearchNs(elem->doc, elem, ns->prefix);
1485 if ((luNs != NULL) && (xmlStrEqual(luNs->href, ns->href)))
1486 {
1487 ns = ns->next;
1488 continue;
1489 }
1490 }
1491 q = xmlNewNs(elem, ns->href, ns->prefix);
1492 if (p == NULL) {
1493 ret = p = q;
1494 } else if (q != NULL) {
1495 p->next = q;
1496 p = q;
1497 }
1498 ns = ns->next;
1499 } while (ns != NULL);
1500 return(ret);
1501}
1502
1514static xmlNsPtr
1516 xmlNodePtr invocNode,
1517 xmlNodePtr insert,
1518 xmlNsPtr ns)
1519{
1520 /*
1521 * TODO: Contrary to header comments, this is declared as int.
1522 * be modified to return a node pointer, or NULL if any error
1523 */
1524 xmlNsPtr tmpns;
1525
1526 if ((insert == NULL) || (insert->type != XML_ELEMENT_NODE))
1527 return(NULL);
1528
1529 if (insert->children != NULL) {
1530 xsltTransformError(ctxt, NULL, invocNode,
1531 "Namespace nodes must be added before "
1532 "any child nodes are added to an element.\n");
1533 return(NULL);
1534 }
1535 /*
1536 * BIG NOTE: Xalan-J simply overwrites any ns-decls with
1537 * an equal prefix. We definitively won't do that.
1538 *
1539 * MSXML 4.0 and the .NET ignores ns-decls for which an
1540 * equal prefix is already in use.
1541 *
1542 * Saxon raises an error like:
1543 * "net.sf.saxon.xpath.DynamicError: Cannot create two namespace
1544 * nodes with the same name".
1545 *
1546 * NOTE: We'll currently follow MSXML here.
1547 * REVISIT TODO: Check if it's better to follow Saxon here.
1548 */
1549 if (ns->prefix == NULL) {
1550 /*
1551 * If we are adding ns-nodes to an element using e.g.
1552 * <xsl:copy-of select="/foo/namespace::*">, then we need
1553 * to ensure that we don't incorrectly declare a default
1554 * namespace on an element in no namespace, which otherwise
1555 * would move the element incorrectly into a namespace, if
1556 * the node tree is serialized.
1557 */
1558 if (insert->ns == NULL)
1559 goto occupied;
1560 } else if ((ns->prefix[0] == 'x') &&
1561 xmlStrEqual(ns->prefix, BAD_CAST "xml"))
1562 {
1563 /*
1564 * The XML namespace is built in.
1565 */
1566 return(NULL);
1567 }
1568
1569 if (insert->nsDef != NULL) {
1570 tmpns = insert->nsDef;
1571 do {
1572 if ((tmpns->prefix == NULL) == (ns->prefix == NULL)) {
1573 if ((tmpns->prefix == ns->prefix) ||
1574 xmlStrEqual(tmpns->prefix, ns->prefix))
1575 {
1576 /*
1577 * Same prefix.
1578 */
1579 if (xmlStrEqual(tmpns->href, ns->href))
1580 return(NULL);
1581 goto occupied;
1582 }
1583 }
1584 tmpns = tmpns->next;
1585 } while (tmpns != NULL);
1586 }
1587 tmpns = xmlSearchNs(insert->doc, insert, ns->prefix);
1588 if ((tmpns != NULL) && xmlStrEqual(tmpns->href, ns->href))
1589 return(NULL);
1590 /*
1591 * Declare a new namespace.
1592 * TODO: The problem (wrt efficiency) with this xmlNewNs() is
1593 * that it will again search the already declared namespaces
1594 * for a duplicate :-/
1595 */
1596 return(xmlNewNs(insert, ns->href, ns->prefix));
1597
1598occupied:
1599 /*
1600 * TODO: We could as well raise an error here (like Saxon does),
1601 * or at least generate a warning.
1602 */
1603 return(NULL);
1604}
1605
1625static xmlNodePtr
1626xsltCopyTree(xsltTransformContextPtr ctxt, xmlNodePtr invocNode,
1627 xmlNodePtr node, xmlNodePtr insert, int isLRE,
1628 int topElemVisited)
1629{
1630 xmlNodePtr copy;
1631
1632 if (node == NULL)
1633 return(NULL);
1634 switch (node->type) {
1635 case XML_ELEMENT_NODE:
1636 case XML_ENTITY_REF_NODE:
1637 case XML_ENTITY_NODE:
1638 case XML_PI_NODE:
1639 case XML_COMMENT_NODE:
1640 case XML_DOCUMENT_NODE:
1641 case XML_HTML_DOCUMENT_NODE:
1642#ifdef LIBXML_DOCB_ENABLED
1643 case XML_DOCB_DOCUMENT_NODE:
1644#endif
1645 break;
1646 case XML_TEXT_NODE: {
1647 int noenc = (node->name == xmlStringTextNoenc);
1648 return(xsltCopyTextString(ctxt, insert, node->content, noenc));
1649 }
1650 case XML_CDATA_SECTION_NODE:
1651 return(xsltCopyTextString(ctxt, insert, node->content, 0));
1652 case XML_ATTRIBUTE_NODE:
1653 return((xmlNodePtr)
1654 xsltShallowCopyAttr(ctxt, invocNode, insert, (xmlAttrPtr) node));
1655 case XML_NAMESPACE_DECL:
1656 return((xmlNodePtr) xsltShallowCopyNsNode(ctxt, invocNode,
1657 insert, (xmlNsPtr) node));
1658
1659 case XML_DOCUMENT_TYPE_NODE:
1660 case XML_DOCUMENT_FRAG_NODE:
1661 case XML_NOTATION_NODE:
1662 case XML_DTD_NODE:
1663 case XML_ELEMENT_DECL:
1664 case XML_ATTRIBUTE_DECL:
1665 case XML_ENTITY_DECL:
1666 case XML_XINCLUDE_START:
1667 case XML_XINCLUDE_END:
1668 return(NULL);
1669 }
1671 if (node->children != NULL)
1672 copy = xsltCopyTreeList(ctxt, invocNode,
1673 node->children, insert, 0, 0);
1674 else
1675 copy = NULL;
1676 return(copy);
1677 }
1678 copy = xmlDocCopyNode(node, insert->doc, 0);
1679 if (copy != NULL) {
1680 copy->doc = ctxt->output;
1681 copy = xsltAddChild(insert, copy);
1682 if (copy == NULL) {
1683 xsltTransformError(ctxt, NULL, invocNode,
1684 "xsltCopyTree: Copying of '%s' failed.\n", node->name);
1685 return (copy);
1686 }
1687 /*
1688 * The node may have been coalesced into another text node.
1689 */
1690 if (insert->last != copy)
1691 return(insert->last);
1692 copy->next = NULL;
1693
1694 if (node->type == XML_ELEMENT_NODE) {
1695 /*
1696 * Copy in-scope namespace nodes.
1697 *
1698 * REVISIT: Since we try to reuse existing in-scope ns-decls by
1699 * using xmlSearchNsByHref(), this will eventually change
1700 * the prefix of an original ns-binding; thus it might
1701 * break QNames in element/attribute content.
1702 * OPTIMIZE TODO: If we had a xmlNsPtr * on the transformation
1703 * context, plus a ns-lookup function, which writes directly
1704 * to a given list, then we wouldn't need to create/free the
1705 * nsList every time.
1706 */
1707 if ((topElemVisited == 0) &&
1708 (node->parent != NULL) &&
1709 (node->parent->type != XML_DOCUMENT_NODE) &&
1710 (node->parent->type != XML_HTML_DOCUMENT_NODE))
1711 {
1712 xmlNsPtr *nsList, *curns, ns;
1713
1714 /*
1715 * If this is a top-most element in a tree to be
1716 * copied, then we need to ensure that all in-scope
1717 * namespaces are copied over. For nodes deeper in the
1718 * tree, it is sufficient to reconcile only the ns-decls
1719 * (node->nsDef entries).
1720 */
1721
1722 nsList = xmlGetNsList(node->doc, node);
1723 if (nsList != NULL) {
1724 curns = nsList;
1725 do {
1726 /*
1727 * Search by prefix first in order to break as less
1728 * QNames in element/attribute content as possible.
1729 */
1730 ns = xmlSearchNs(insert->doc, insert,
1731 (*curns)->prefix);
1732
1733 if ((ns == NULL) ||
1734 (! xmlStrEqual(ns->href, (*curns)->href)))
1735 {
1736 ns = NULL;
1737 /*
1738 * Search by namespace name.
1739 * REVISIT TODO: Currently disabled.
1740 */
1741#if 0
1742 ns = xmlSearchNsByHref(insert->doc,
1743 insert, (*curns)->href);
1744#endif
1745 }
1746 if (ns == NULL) {
1747 /*
1748 * Declare a new namespace on the copied element.
1749 */
1750 ns = xmlNewNs(copy, (*curns)->href,
1751 (*curns)->prefix);
1752 /* TODO: Handle errors */
1753 }
1754 if (node->ns == *curns) {
1755 /*
1756 * If this was the original's namespace then set
1757 * the generated counterpart on the copy.
1758 */
1759 copy->ns = ns;
1760 }
1761 curns++;
1762 } while (*curns != NULL);
1763 xmlFree(nsList);
1764 }
1765 } else if (node->nsDef != NULL) {
1766 /*
1767 * Copy over all namespace declaration attributes.
1768 */
1769 if (node->nsDef != NULL) {
1770 if (isLRE)
1771 xsltCopyNamespaceList(ctxt, copy, node->nsDef);
1772 else
1774 }
1775 }
1776 /*
1777 * Set the namespace.
1778 */
1779 if (node->ns != NULL) {
1780 if (copy->ns == NULL) {
1781 /*
1782 * This will map copy->ns to one of the newly created
1783 * in-scope ns-decls, OR create a new ns-decl on @copy.
1784 */
1785 copy->ns = xsltGetSpecialNamespace(ctxt, invocNode,
1786 node->ns->href, node->ns->prefix, copy);
1787 }
1788 } else if ((insert->type == XML_ELEMENT_NODE) &&
1789 (insert->ns != NULL))
1790 {
1791 /*
1792 * "Undeclare" the default namespace on @copy with xmlns="".
1793 */
1794 xsltGetSpecialNamespace(ctxt, invocNode, NULL, NULL, copy);
1795 }
1796 /*
1797 * Copy attribute nodes.
1798 */
1799 if (node->properties != NULL) {
1800 xsltCopyAttrListNoOverwrite(ctxt, invocNode,
1801 copy, node->properties);
1802 }
1803 if (topElemVisited == 0)
1804 topElemVisited = 1;
1805 }
1806 /*
1807 * Copy the subtree.
1808 */
1809 if (node->children != NULL) {
1810 xsltCopyTreeList(ctxt, invocNode,
1811 node->children, copy, isLRE, topElemVisited);
1812 }
1813 } else {
1814 xsltTransformError(ctxt, NULL, invocNode,
1815 "xsltCopyTree: Copying of '%s' failed.\n", node->name);
1816 }
1817 return(copy);
1818}
1819
1820/************************************************************************
1821 * *
1822 * Error/fallback processing *
1823 * *
1824 ************************************************************************/
1825
1836static int
1838 xmlNodePtr inst) {
1839
1840 xmlNodePtr child;
1841 int ret = 0;
1842
1843 if ((ctxt == NULL) || (node == NULL) || (inst == NULL) ||
1844 (inst->children == NULL))
1845 return(0);
1846
1847 child = inst->children;
1848 while (child != NULL) {
1849 if ((IS_XSLT_ELEM(child)) &&
1850 (xmlStrEqual(child->name, BAD_CAST "fallback"))) {
1851#ifdef WITH_XSLT_DEBUG_PARSING
1853 "applying xsl:fallback\n");
1854#endif
1855 ret++;
1856 xsltApplySequenceConstructor(ctxt, node, child->children,
1857 NULL);
1858 }
1859 child = child->next;
1860 }
1861 return(ret);
1862}
1863
1864/************************************************************************
1865 * *
1866 * Default processing *
1867 * *
1868 ************************************************************************/
1869
1892static void
1895 xmlNodePtr copy;
1896 xmlNodePtr cur;
1897 int nbchild = 0, oldSize;
1898 int childno = 0, oldPos;
1899 xsltTemplatePtr template;
1900
1902 /*
1903 * Handling of leaves
1904 */
1905 switch (node->type) {
1906 case XML_DOCUMENT_NODE:
1907 case XML_HTML_DOCUMENT_NODE:
1908 case XML_ELEMENT_NODE:
1909 break;
1910 case XML_CDATA_SECTION_NODE:
1911#ifdef WITH_XSLT_DEBUG_PROCESS
1913 "xsltDefaultProcessOneNode: copy CDATA %s\n",
1914 node->content));
1915#endif
1916 copy = xsltCopyText(ctxt, ctxt->insert, node, 0);
1917 if (copy == NULL) {
1919 "xsltDefaultProcessOneNode: cdata copy failed\n");
1920 }
1921 return;
1922 case XML_TEXT_NODE:
1923#ifdef WITH_XSLT_DEBUG_PROCESS
1924 if (node->content == NULL) {
1926 "xsltDefaultProcessOneNode: copy empty text\n"));
1927 return;
1928 } else {
1930 "xsltDefaultProcessOneNode: copy text %s\n",
1931 node->content));
1932 }
1933#endif
1934 copy = xsltCopyText(ctxt, ctxt->insert, node, 0);
1935 if (copy == NULL) {
1937 "xsltDefaultProcessOneNode: text copy failed\n");
1938 }
1939 return;
1940 case XML_ATTRIBUTE_NODE:
1941 cur = node->children;
1942 while ((cur != NULL) && (cur->type != XML_TEXT_NODE))
1943 cur = cur->next;
1944 if (cur == NULL) {
1946 "xsltDefaultProcessOneNode: no text for attribute\n");
1947 } else {
1948#ifdef WITH_XSLT_DEBUG_PROCESS
1949 if (cur->content == NULL) {
1951 "xsltDefaultProcessOneNode: copy empty text\n"));
1952 } else {
1954 "xsltDefaultProcessOneNode: copy text %s\n",
1955 cur->content));
1956 }
1957#endif
1958 copy = xsltCopyText(ctxt, ctxt->insert, cur, 0);
1959 if (copy == NULL) {
1961 "xsltDefaultProcessOneNode: text copy failed\n");
1962 }
1963 }
1964 return;
1965 default:
1966 return;
1967 }
1968 /*
1969 * Handling of Elements: first pass, counting
1970 */
1971 cur = node->children;
1972 while (cur != NULL) {
1974 nbchild++;
1975 cur = cur->next;
1976 }
1977
1978 /*
1979 * Handling of Elements: second pass, actual processing
1980 *
1981 * Note that params are passed to the next template. This matches
1982 * XSLT 2.0 behavior but doesn't conform to XSLT 1.0.
1983 */
1984 oldSize = ctxt->xpathCtxt->contextSize;
1985 oldPos = ctxt->xpathCtxt->proximityPosition;
1986 cur = node->children;
1987 while (cur != NULL) {
1988 childno++;
1989 switch (cur->type) {
1990 case XML_DOCUMENT_NODE:
1991 case XML_HTML_DOCUMENT_NODE:
1992 case XML_ELEMENT_NODE:
1993 ctxt->xpathCtxt->contextSize = nbchild;
1994 ctxt->xpathCtxt->proximityPosition = childno;
1995
1996 if (ctxt->depth >= ctxt->maxTemplateDepth) {
1998 "xsltDefaultProcessOneNode: Maximum template depth "
1999 "exceeded.\n"
2000 "You can adjust xsltMaxDepth (--maxdepth) in order to "
2001 "raise the maximum number of nested template calls and "
2002 "variables/params (currently set to %d).\n",
2003 ctxt->maxTemplateDepth);
2004 ctxt->state = XSLT_STATE_STOPPED;
2005 return;
2006 }
2007 ctxt->depth++;
2009 ctxt->depth--;
2010 break;
2011 case XML_CDATA_SECTION_NODE:
2012 template = xsltGetTemplate(ctxt, cur, NULL);
2013 if (template) {
2014#ifdef WITH_XSLT_DEBUG_PROCESS
2016 "xsltDefaultProcessOneNode: applying template for CDATA %s\n",
2017 cur->content));
2018#endif
2019 /*
2020 * Instantiate the xsl:template.
2021 */
2022 xsltApplyXSLTTemplate(ctxt, cur, template->content,
2023 template, params);
2024 } else /* if (ctxt->mode == NULL) */ {
2025#ifdef WITH_XSLT_DEBUG_PROCESS
2027 "xsltDefaultProcessOneNode: copy CDATA %s\n",
2028 cur->content));
2029#endif
2030 copy = xsltCopyText(ctxt, ctxt->insert, cur, 0);
2031 if (copy == NULL) {
2033 "xsltDefaultProcessOneNode: cdata copy failed\n");
2034 }
2035 }
2036 break;
2037 case XML_TEXT_NODE:
2038 template = xsltGetTemplate(ctxt, cur, NULL);
2039 if (template) {
2040#ifdef WITH_XSLT_DEBUG_PROCESS
2042 "xsltDefaultProcessOneNode: applying template for text %s\n",
2043 cur->content));
2044#endif
2045 ctxt->xpathCtxt->contextSize = nbchild;
2046 ctxt->xpathCtxt->proximityPosition = childno;
2047 /*
2048 * Instantiate the xsl:template.
2049 */
2050 xsltApplyXSLTTemplate(ctxt, cur, template->content,
2051 template, params);
2052 } else /* if (ctxt->mode == NULL) */ {
2053#ifdef WITH_XSLT_DEBUG_PROCESS
2054 if (cur->content == NULL) {
2056 "xsltDefaultProcessOneNode: copy empty text\n"));
2057 } else {
2059 "xsltDefaultProcessOneNode: copy text %s\n",
2060 cur->content));
2061 }
2062#endif
2063 copy = xsltCopyText(ctxt, ctxt->insert, cur, 0);
2064 if (copy == NULL) {
2066 "xsltDefaultProcessOneNode: text copy failed\n");
2067 }
2068 }
2069 break;
2070 case XML_PI_NODE:
2071 case XML_COMMENT_NODE:
2072 template = xsltGetTemplate(ctxt, cur, NULL);
2073 if (template) {
2074#ifdef WITH_XSLT_DEBUG_PROCESS
2075 if (cur->type == XML_PI_NODE) {
2077 "xsltDefaultProcessOneNode: template found for PI %s\n",
2078 cur->name));
2079 } else if (cur->type == XML_COMMENT_NODE) {
2081 "xsltDefaultProcessOneNode: template found for comment\n"));
2082 }
2083#endif
2084 ctxt->xpathCtxt->contextSize = nbchild;
2085 ctxt->xpathCtxt->proximityPosition = childno;
2086 /*
2087 * Instantiate the xsl:template.
2088 */
2089 xsltApplyXSLTTemplate(ctxt, cur, template->content,
2090 template, params);
2091 }
2092 break;
2093 default:
2094 break;
2095 }
2096 cur = cur->next;
2097 }
2098 ctxt->xpathCtxt->contextSize = oldSize;
2099 ctxt->xpathCtxt->proximityPosition = oldPos;
2100}
2101
2111void
2112xsltProcessOneNode(xsltTransformContextPtr ctxt, xmlNodePtr contextNode,
2113 xsltStackElemPtr withParams)
2114{
2115 xsltTemplatePtr templ;
2116 xmlNodePtr oldNode;
2117
2118 templ = xsltGetTemplate(ctxt, contextNode, NULL);
2119 /*
2120 * If no template is found, apply the default rule.
2121 */
2122 if (templ == NULL) {
2123#ifdef WITH_XSLT_DEBUG_PROCESS
2124 if (contextNode->type == XML_DOCUMENT_NODE) {
2126 "xsltProcessOneNode: no template found for /\n"));
2127 } else if (contextNode->type == XML_CDATA_SECTION_NODE) {
2129 "xsltProcessOneNode: no template found for CDATA\n"));
2130 } else if (contextNode->type == XML_ATTRIBUTE_NODE) {
2132 "xsltProcessOneNode: no template found for attribute %s\n",
2133 ((xmlAttrPtr) contextNode)->name));
2134 } else {
2136 "xsltProcessOneNode: no template found for %s\n", contextNode->name));
2137 }
2138#endif
2139 oldNode = ctxt->node;
2140 ctxt->node = contextNode;
2141 xsltDefaultProcessOneNode(ctxt, contextNode, withParams);
2142 ctxt->node = oldNode;
2143 return;
2144 }
2145
2146 if (contextNode->type == XML_ATTRIBUTE_NODE) {
2147 xsltTemplatePtr oldCurTempRule = ctxt->currentTemplateRule;
2148 /*
2149 * Set the "current template rule".
2150 */
2151 ctxt->currentTemplateRule = templ;
2152
2153#ifdef WITH_XSLT_DEBUG_PROCESS
2155 "xsltProcessOneNode: applying template '%s' for attribute %s\n",
2156 templ->match, contextNode->name));
2157#endif
2158 xsltApplyXSLTTemplate(ctxt, contextNode, templ->content, templ, withParams);
2159
2160 ctxt->currentTemplateRule = oldCurTempRule;
2161 } else {
2162 xsltTemplatePtr oldCurTempRule = ctxt->currentTemplateRule;
2163 /*
2164 * Set the "current template rule".
2165 */
2166 ctxt->currentTemplateRule = templ;
2167
2168#ifdef WITH_XSLT_DEBUG_PROCESS
2169 if (contextNode->type == XML_DOCUMENT_NODE) {
2171 "xsltProcessOneNode: applying template '%s' for /\n",
2172 templ->match));
2173 } else {
2175 "xsltProcessOneNode: applying template '%s' for %s\n",
2176 templ->match, contextNode->name));
2177 }
2178#endif
2179 xsltApplyXSLTTemplate(ctxt, contextNode, templ->content, templ, withParams);
2180
2181 ctxt->currentTemplateRule = oldCurTempRule;
2182 }
2183}
2184
2185#ifdef WITH_DEBUGGER
2186static xmlNodePtr
2187xsltDebuggerStartSequenceConstructor(xsltTransformContextPtr ctxt,
2188 xmlNodePtr contextNode,
2189 xmlNodePtr list,
2190 xsltTemplatePtr templ,
2191 int *addCallResult)
2192{
2193 xmlNodePtr debugedNode = NULL;
2194
2195 if (ctxt->debugStatus != XSLT_DEBUG_NONE) {
2196 if (templ) {
2197 *addCallResult = xslAddCall(templ, templ->elem);
2198 } else {
2199 *addCallResult = xslAddCall(NULL, list);
2200 }
2201 switch (ctxt->debugStatus) {
2203 case XSLT_DEBUG_QUIT:
2204 if (*addCallResult)
2205 xslDropCall();
2206 return(NULL);
2207 }
2208 if (templ) {
2209 xslHandleDebugger(templ->elem, contextNode, templ, ctxt);
2210 debugedNode = templ->elem;
2211 } else if (list) {
2212 xslHandleDebugger(list, contextNode, templ, ctxt);
2213 debugedNode = list;
2214 } else if (ctxt->inst) {
2215 xslHandleDebugger(ctxt->inst, contextNode, templ, ctxt);
2216 debugedNode = ctxt->inst;
2217 }
2218 }
2219 return(debugedNode);
2220}
2221#endif /* WITH_DEBUGGER */
2222
2235int
2238 int level)
2239{
2240 if (ctxt->varsNr >= ctxt->varsMax) {
2241 xsltStackElemPtr *tmp;
2242 int newMax = ctxt->varsMax == 0 ? 10 : 2 * ctxt->varsMax;
2243
2244 tmp = (xsltStackElemPtr *) xmlRealloc(ctxt->varsTab,
2245 newMax * sizeof(*tmp));
2246 if (tmp == NULL) {
2247 xmlGenericError(xmlGenericErrorContext, "realloc failed !\n");
2248 return (-1);
2249 }
2250 ctxt->varsTab = tmp;
2251 ctxt->varsMax = newMax;
2252 }
2253 ctxt->varsTab[ctxt->varsNr++] = variable;
2254 ctxt->vars = variable;
2255 variable->level = level;
2256 return(0);
2257}
2258
2265static void
2267{
2268 xmlDocPtr cur = ctxt->localRVT, tmp;
2269
2270 if (cur == base)
2271 return;
2272 if (cur->prev != NULL)
2273 xsltTransformError(ctxt, NULL, NULL, "localRVT not head of list\n");
2274
2275 /* Reset localRVT early because some RVTs might be registered again. */
2276 ctxt->localRVT = base;
2277 if (base != NULL)
2278 base->prev = NULL;
2279
2280 do {
2281 tmp = cur;
2282 cur = (xmlDocPtr) cur->next;
2283 if (tmp->compression == XSLT_RVT_LOCAL) {
2284 xsltReleaseRVT(ctxt, tmp);
2285 } else if (tmp->compression == XSLT_RVT_GLOBAL) {
2286 xsltRegisterPersistRVT(ctxt, tmp);
2287 } else if (tmp->compression == XSLT_RVT_FUNC_RESULT) {
2288 /*
2289 * This will either register the RVT again or move it to the
2290 * context variable.
2291 */
2292 xsltRegisterLocalRVT(ctxt, tmp);
2293 tmp->compression = XSLT_RVT_FUNC_RESULT;
2294 } else {
2296 "xsltReleaseLocalRVTs: Unexpected RVT flag %p\n",
2297 tmp->psvi);
2298 }
2299 } while (cur != base);
2300}
2301
2317static void
2319 xmlNodePtr contextNode, xmlNodePtr list,
2320 xsltTemplatePtr templ)
2321{
2322 xmlNodePtr oldInsert, oldInst, oldCurInst, oldContextNode;
2323 xmlNodePtr cur, insert, copy = NULL;
2324 int level = 0, oldVarsNr;
2325 xmlDocPtr oldLocalFragmentTop;
2326
2327#ifdef XSLT_REFACTORED
2329#endif
2330
2331#ifdef WITH_DEBUGGER
2332 int addCallResult = 0;
2333 xmlNodePtr debuggedNode = NULL;
2334#endif
2335
2336 if (ctxt == NULL)
2337 return;
2338
2339#ifdef WITH_DEBUGGER
2340 if (ctxt->debugStatus != XSLT_DEBUG_NONE) {
2341 debuggedNode =
2342 xsltDebuggerStartSequenceConstructor(ctxt, contextNode,
2343 list, templ, &addCallResult);
2344 if (debuggedNode == NULL)
2345 return;
2346 }
2347#endif
2348
2349 if (list == NULL)
2350 return;
2352
2353 /*
2354 * Check for infinite recursion: stop if the maximum of nested templates
2355 * is excceeded. Adjust xsltMaxDepth if you need more.
2356 */
2357 if (ctxt->depth >= ctxt->maxTemplateDepth) {
2359 "xsltApplySequenceConstructor: A potential infinite template "
2360 "recursion was detected.\n"
2361 "You can adjust xsltMaxDepth (--maxdepth) in order to "
2362 "raise the maximum number of nested template calls and "
2363 "variables/params (currently set to %d).\n",
2364 ctxt->maxTemplateDepth);
2365 xsltDebug(ctxt, contextNode, list, NULL);
2366 ctxt->state = XSLT_STATE_STOPPED;
2367 return;
2368 }
2369 ctxt->depth++;
2370
2371 oldLocalFragmentTop = ctxt->localRVT;
2372 oldInsert = insert = ctxt->insert;
2373 oldInst = oldCurInst = ctxt->inst;
2374 oldContextNode = ctxt->node;
2375 /*
2376 * Save current number of variables on the stack; new vars are popped when
2377 * exiting.
2378 */
2379 oldVarsNr = ctxt->varsNr;
2380 /*
2381 * Process the sequence constructor.
2382 */
2383 cur = list;
2384 while (cur != NULL) {
2385 if (ctxt->opLimit != 0) {
2386 if (ctxt->opCount >= ctxt->opLimit) {
2388 "xsltApplySequenceConstructor: "
2389 "Operation limit exceeded\n");
2390 ctxt->state = XSLT_STATE_STOPPED;
2391 goto error;
2392 }
2393 ctxt->opCount += 1;
2394 }
2395
2396 ctxt->inst = cur;
2397
2398#ifdef WITH_DEBUGGER
2399 switch (ctxt->debugStatus) {
2401 case XSLT_DEBUG_QUIT:
2402 break;
2403
2404 }
2405#endif
2406 /*
2407 * Test; we must have a valid insertion point.
2408 */
2409 if (insert == NULL) {
2410
2411#ifdef WITH_XSLT_DEBUG_PROCESS
2413 "xsltApplySequenceConstructor: insert == NULL !\n"));
2414#endif
2415 goto error;
2416 }
2417
2418#ifdef WITH_DEBUGGER
2419 if ((ctxt->debugStatus != XSLT_DEBUG_NONE) && (debuggedNode != cur))
2420 xslHandleDebugger(cur, contextNode, templ, ctxt);
2421#endif
2422
2423#ifdef XSLT_REFACTORED
2424 if (cur->type == XML_ELEMENT_NODE) {
2425 info = (xsltStylePreCompPtr) cur->psvi;
2426 /*
2427 * We expect a compiled representation on:
2428 * 1) XSLT instructions of this XSLT version (1.0)
2429 * (with a few exceptions)
2430 * 2) Literal result elements
2431 * 3) Extension instructions
2432 * 4) XSLT instructions of future XSLT versions
2433 * (forwards-compatible mode).
2434 */
2435 if (info == NULL) {
2436 /*
2437 * Handle the rare cases where we don't expect a compiled
2438 * representation on an XSLT element.
2439 */
2440 if (IS_XSLT_ELEM_FAST(cur) && IS_XSLT_NAME(cur, "message")) {
2441 xsltMessage(ctxt, contextNode, cur);
2442 goto skip_children;
2443 }
2444 /*
2445 * Something really went wrong:
2446 */
2448 "Internal error in xsltApplySequenceConstructor(): "
2449 "The element '%s' in the stylesheet has no compiled "
2450 "representation.\n",
2451 cur->name);
2452 goto skip_children;
2453 }
2454
2455 if (info->type == XSLT_FUNC_LITERAL_RESULT_ELEMENT) {
2456 xsltStyleItemLRElementInfoPtr lrInfo =
2457 (xsltStyleItemLRElementInfoPtr) info;
2458 /*
2459 * Literal result elements
2460 * --------------------------------------------------------
2461 */
2462#ifdef WITH_XSLT_DEBUG_PROCESS
2465 "xsltApplySequenceConstructor: copy literal result "
2466 "element '%s'\n", cur->name));
2467#endif
2468 /*
2469 * Copy the raw element-node.
2470 * OLD: if ((copy = xsltShallowCopyElem(ctxt, cur, insert))
2471 * == NULL)
2472 * goto error;
2473 */
2474 copy = xmlDocCopyNode(cur, insert->doc, 0);
2475 if (copy == NULL) {
2477 "Internal error in xsltApplySequenceConstructor(): "
2478 "Failed to copy literal result element '%s'.\n",
2479 cur->name);
2480 goto error;
2481 } else {
2482 /*
2483 * Add the element-node to the result tree.
2484 */
2485 copy->doc = ctxt->output;
2486 copy = xsltAddChild(insert, copy);
2487 /*
2488 * Create effective namespaces declarations.
2489 * OLD: xsltCopyNamespaceList(ctxt, copy, cur->nsDef);
2490 */
2491 if (lrInfo->effectiveNs != NULL) {
2492 xsltEffectiveNsPtr effNs = lrInfo->effectiveNs;
2493 xmlNsPtr ns, lastns = NULL;
2494
2495 while (effNs != NULL) {
2496 /*
2497 * Avoid generating redundant namespace
2498 * declarations; thus lookup if there is already
2499 * such a ns-decl in the result.
2500 */
2501 ns = xmlSearchNs(copy->doc, copy, effNs->prefix);
2502 if ((ns != NULL) &&
2503 (xmlStrEqual(ns->href, effNs->nsName)))
2504 {
2505 effNs = effNs->next;
2506 continue;
2507 }
2508 ns = xmlNewNs(copy, effNs->nsName, effNs->prefix);
2509 if (ns == NULL) {
2511 "Internal error in "
2512 "xsltApplySequenceConstructor(): "
2513 "Failed to copy a namespace "
2514 "declaration.\n");
2515 goto error;
2516 }
2517
2518 if (lastns == NULL)
2519 copy->nsDef = ns;
2520 else
2521 lastns->next =ns;
2522 lastns = ns;
2523
2524 effNs = effNs->next;
2525 }
2526
2527 }
2528 /*
2529 * NOTE that we don't need to apply ns-alising: this was
2530 * already done at compile-time.
2531 */
2532 if (cur->ns != NULL) {
2533 /*
2534 * If there's no such ns-decl in the result tree,
2535 * then xsltGetSpecialNamespace() will
2536 * create a ns-decl on the copied node.
2537 */
2538 copy->ns = xsltGetSpecialNamespace(ctxt, cur,
2539 cur->ns->href, cur->ns->prefix, copy);
2540 } else {
2541 /*
2542 * Undeclare the default namespace if needed.
2543 * This can be skipped, if the result element has
2544 * no ns-decls, in which case the result element
2545 * obviously does not declare a default namespace;
2546 * AND there's either no parent, or the parent
2547 * element is in no namespace; this means there's no
2548 * default namespace is scope to care about.
2549 *
2550 * REVISIT: This might result in massive
2551 * generation of ns-decls if nodes in a default
2552 * namespaces are mixed with nodes in no namespace.
2553 *
2554 */
2555 if (copy->nsDef ||
2556 ((insert != NULL) &&
2557 (insert->type == XML_ELEMENT_NODE) &&
2558 (insert->ns != NULL)))
2559 {
2561 NULL, NULL, copy);
2562 }
2563 }
2564 }
2565 /*
2566 * SPEC XSLT 2.0 "Each attribute of the literal result
2567 * element, other than an attribute in the XSLT namespace,
2568 * is processed to produce an attribute for the element in
2569 * the result tree."
2570 * NOTE: See bug #341325.
2571 */
2572 if (cur->properties != NULL) {
2573 xsltAttrListTemplateProcess(ctxt, copy, cur->properties);
2574 }
2575 } else if (IS_XSLT_ELEM_FAST(cur)) {
2576 /*
2577 * XSLT instructions
2578 * --------------------------------------------------------
2579 */
2580 if (info->type == XSLT_FUNC_UNKOWN_FORWARDS_COMPAT) {
2581 /*
2582 * We hit an unknown XSLT element.
2583 * Try to apply one of the fallback cases.
2584 */
2585 ctxt->insert = insert;
2586 if (!xsltApplyFallbacks(ctxt, contextNode, cur)) {
2588 "The is no fallback behaviour defined for "
2589 "the unknown XSLT element '%s'.\n",
2590 cur->name);
2591 }
2592 ctxt->insert = oldInsert;
2593 } else if (info->func != NULL) {
2594 /*
2595 * Execute the XSLT instruction.
2596 */
2597 ctxt->insert = insert;
2598
2599 info->func(ctxt, contextNode, cur,
2601
2602 /*
2603 * Cleanup temporary tree fragments.
2604 */
2605 if (oldLocalFragmentTop != ctxt->localRVT)
2606 xsltReleaseLocalRVTs(ctxt, oldLocalFragmentTop);
2607
2608 ctxt->insert = oldInsert;
2609 } else if (info->type == XSLT_FUNC_VARIABLE) {
2610 xsltStackElemPtr tmpvar = ctxt->vars;
2611
2613
2614 if (tmpvar != ctxt->vars) {
2615 /*
2616 * TODO: Using a @tmpvar is an annoying workaround, but
2617 * the current mechanisms do not provide any other way
2618 * of knowing if the var was really pushed onto the
2619 * stack.
2620 */
2621 ctxt->vars->level = level;
2622 }
2623 } else if (info->type == XSLT_FUNC_MESSAGE) {
2624 /*
2625 * TODO: Won't be hit, since we don't compile xsl:message.
2626 */
2627 xsltMessage(ctxt, contextNode, cur);
2628 } else {
2630 "Unexpected XSLT element '%s'.\n", cur->name);
2631 }
2632 goto skip_children;
2633
2634 } else {
2636 /*
2637 * Extension intructions (elements)
2638 * --------------------------------------------------------
2639 */
2640 if (cur->psvi == xsltExtMarker) {
2641 /*
2642 * The xsltExtMarker was set during the compilation
2643 * of extension instructions if there was no registered
2644 * handler for this specific extension function at
2645 * compile-time.
2646 * Libxslt will now lookup if a handler is
2647 * registered in the context of this transformation.
2648 */
2649 func = xsltExtElementLookup(ctxt, cur->name,
2650 cur->ns->href);
2651 } else
2652 func = ((xsltElemPreCompPtr) cur->psvi)->func;
2653
2654 if (func == NULL) {
2655 /*
2656 * No handler available.
2657 * Try to execute fallback behaviour via xsl:fallback.
2658 */
2659#ifdef WITH_XSLT_DEBUG_PROCESS
2662 "xsltApplySequenceConstructor: unknown extension %s\n",
2663 cur->name));
2664#endif
2665 ctxt->insert = insert;
2666 if (!xsltApplyFallbacks(ctxt, contextNode, cur)) {
2668 "Unknown extension instruction '{%s}%s'.\n",
2669 cur->ns->href, cur->name);
2670 }
2671 ctxt->insert = oldInsert;
2672 } else {
2673 /*
2674 * Execute the handler-callback.
2675 */
2676#ifdef WITH_XSLT_DEBUG_PROCESS
2678 "xsltApplySequenceConstructor: extension construct %s\n",
2679 cur->name));
2680#endif
2681 /*
2682 * Disable the xsltCopyTextString optimization for
2683 * extension elements. Extensions could append text using
2684 * xmlAddChild which will free the buffer pointed to by
2685 * 'lasttext'. This buffer could later be reallocated with
2686 * a different size than recorded in 'lasttsize'. See bug
2687 * #777432.
2688 */
2689 if (cur->psvi == xsltExtMarker) {
2690 ctxt->lasttext = NULL;
2691 }
2692
2693 ctxt->insert = insert;
2694
2695 func(ctxt, contextNode, cur, cur->psvi);
2696
2697 /*
2698 * Cleanup temporary tree fragments.
2699 */
2700 if (oldLocalFragmentTop != ctxt->localRVT)
2701 xsltReleaseLocalRVTs(ctxt, oldLocalFragmentTop);
2702
2703 ctxt->insert = oldInsert;
2704 }
2705 goto skip_children;
2706 }
2707
2708 } else if (XSLT_IS_TEXT_NODE(cur)) {
2709 /*
2710 * Text
2711 * ------------------------------------------------------------
2712 */
2713#ifdef WITH_XSLT_DEBUG_PROCESS
2714 if (cur->name == xmlStringTextNoenc) {
2717 "xsltApplySequenceConstructor: copy unescaped text '%s'\n",
2718 cur->content));
2719 } else {
2722 "xsltApplySequenceConstructor: copy text '%s'\n",
2723 cur->content));
2724 }
2725#endif
2726 if (xsltCopyText(ctxt, insert, cur, ctxt->internalized) == NULL)
2727 goto error;
2728 }
2729
2730#else /* XSLT_REFACTORED */
2731
2732 if (IS_XSLT_ELEM(cur)) {
2733 /*
2734 * This is an XSLT node
2735 */
2737
2738 if (info == NULL) {
2739 if (IS_XSLT_NAME(cur, "message")) {
2740 xsltMessage(ctxt, contextNode, cur);
2741 } else {
2742 /*
2743 * That's an error try to apply one of the fallback cases
2744 */
2745 ctxt->insert = insert;
2746 if (!xsltApplyFallbacks(ctxt, contextNode, cur)) {
2748 "xsltApplySequenceConstructor: %s was not compiled\n",
2749 cur->name);
2750 }
2751 ctxt->insert = oldInsert;
2752 }
2753 goto skip_children;
2754 }
2755
2756 if (info->func != NULL) {
2757 oldCurInst = ctxt->inst;
2758 ctxt->inst = cur;
2759 ctxt->insert = insert;
2760
2761 info->func(ctxt, contextNode, cur, (xsltElemPreCompPtr) info);
2762
2763 /*
2764 * Cleanup temporary tree fragments.
2765 */
2766 if (oldLocalFragmentTop != ctxt->localRVT)
2767 xsltReleaseLocalRVTs(ctxt, oldLocalFragmentTop);
2768
2769 ctxt->insert = oldInsert;
2770 ctxt->inst = oldCurInst;
2771 goto skip_children;
2772 }
2773
2774 if (IS_XSLT_NAME(cur, "variable")) {
2775 xsltStackElemPtr tmpvar = ctxt->vars;
2776
2777 oldCurInst = ctxt->inst;
2778 ctxt->inst = cur;
2779
2781
2782 ctxt->inst = oldCurInst;
2783
2784 if (tmpvar != ctxt->vars) {
2785 /*
2786 * TODO: Using a @tmpvar is an annoying workaround, but
2787 * the current mechanisms do not provide any other way
2788 * of knowing if the var was really pushed onto the
2789 * stack.
2790 */
2791 ctxt->vars->level = level;
2792 }
2793 } else if (IS_XSLT_NAME(cur, "message")) {
2794 xsltMessage(ctxt, contextNode, cur);
2795 } else {
2797 "Unexpected XSLT element '%s'.\n", cur->name);
2798 }
2799 goto skip_children;
2800 } else if ((cur->type == XML_TEXT_NODE) ||
2801 (cur->type == XML_CDATA_SECTION_NODE)) {
2802
2803 /*
2804 * This text comes from the stylesheet
2805 * For stylesheets, the set of whitespace-preserving
2806 * element names consists of just xsl:text.
2807 */
2808#ifdef WITH_XSLT_DEBUG_PROCESS
2809 if (cur->type == XML_CDATA_SECTION_NODE) {
2811 "xsltApplySequenceConstructor: copy CDATA text %s\n",
2812 cur->content));
2813 } else if (cur->name == xmlStringTextNoenc) {
2815 "xsltApplySequenceConstructor: copy unescaped text %s\n",
2816 cur->content));
2817 } else {
2819 "xsltApplySequenceConstructor: copy text %s\n",
2820 cur->content));
2821 }
2822#endif
2823 if (xsltCopyText(ctxt, insert, cur, ctxt->internalized) == NULL)
2824 goto error;
2825 } else if ((cur->type == XML_ELEMENT_NODE) &&
2826 (cur->ns != NULL) && (cur->psvi != NULL)) {
2827 xsltTransformFunction function;
2828
2829 oldCurInst = ctxt->inst;
2830 ctxt->inst = cur;
2831 /*
2832 * Flagged as an extension element
2833 */
2834 if (cur->psvi == xsltExtMarker)
2835 function = xsltExtElementLookup(ctxt, cur->name,
2836 cur->ns->href);
2837 else
2838 function = ((xsltElemPreCompPtr) cur->psvi)->func;
2839
2840 if (function == NULL) {
2841 xmlNodePtr child;
2842 int found = 0;
2843
2844#ifdef WITH_XSLT_DEBUG_PROCESS
2846 "xsltApplySequenceConstructor: unknown extension %s\n",
2847 cur->name));
2848#endif
2849 /*
2850 * Search if there are fallbacks
2851 */
2852 ctxt->insert = insert;
2853 child = cur->children;
2854 while (child != NULL) {
2855 if ((IS_XSLT_ELEM(child)) &&
2856 (IS_XSLT_NAME(child, "fallback")))
2857 {
2858 found = 1;
2859 xsltApplySequenceConstructor(ctxt, contextNode,
2860 child->children, NULL);
2861 }
2862 child = child->next;
2863 }
2864 ctxt->insert = oldInsert;
2865
2866 if (!found) {
2868 "xsltApplySequenceConstructor: failed to find extension %s\n",
2869 cur->name);
2870 }
2871 } else {
2872#ifdef WITH_XSLT_DEBUG_PROCESS
2874 "xsltApplySequenceConstructor: extension construct %s\n",
2875 cur->name));
2876#endif
2877
2878 /*
2879 * Disable the xsltCopyTextString optimization for
2880 * extension elements. Extensions could append text using
2881 * xmlAddChild which will free the buffer pointed to by
2882 * 'lasttext'. This buffer could later be reallocated with
2883 * a different size than recorded in 'lasttsize'. See bug
2884 * #777432.
2885 */
2886 if (cur->psvi == xsltExtMarker) {
2887 ctxt->lasttext = NULL;
2888 }
2889
2890 ctxt->insert = insert;
2891
2892 function(ctxt, contextNode, cur, cur->psvi);
2893 /*
2894 * Cleanup temporary tree fragments.
2895 */
2896 if (oldLocalFragmentTop != ctxt->localRVT)
2897 xsltReleaseLocalRVTs(ctxt, oldLocalFragmentTop);
2898
2899 ctxt->insert = oldInsert;
2900
2901 }
2902 ctxt->inst = oldCurInst;
2903 goto skip_children;
2904 } else if (cur->type == XML_ELEMENT_NODE) {
2905#ifdef WITH_XSLT_DEBUG_PROCESS
2907 "xsltApplySequenceConstructor: copy node %s\n",
2908 cur->name));
2909#endif
2910 oldCurInst = ctxt->inst;
2911 ctxt->inst = cur;
2912
2913 if ((copy = xsltShallowCopyElem(ctxt, cur, insert, 1)) == NULL)
2914 goto error;
2915 /*
2916 * Add extra namespaces inherited from the current template
2917 * if we are in the first level children and this is a
2918 * "real" template.
2919 */
2920 if ((templ != NULL) && (oldInsert == insert) &&
2921 (ctxt->templ != NULL) && (ctxt->templ->inheritedNs != NULL)) {
2922 int i;
2923 xmlNsPtr ns, ret;
2924
2925 for (i = 0; i < ctxt->templ->inheritedNsNr; i++) {
2926 const xmlChar *URI = NULL;
2928 ns = ctxt->templ->inheritedNs[i];
2929
2930 /* Note that the XSLT namespace was already excluded
2931 * in xsltGetInheritedNsList().
2932 */
2933#if 0
2934 if (xmlStrEqual(ns->href, XSLT_NAMESPACE))
2935 continue;
2936#endif
2937 style = ctxt->style;
2938 while (style != NULL) {
2939 if (style->nsAliases != NULL)
2940 URI = (const xmlChar *)
2941 xmlHashLookup(style->nsAliases, ns->href);
2942 if (URI != NULL)
2943 break;
2944
2946 }
2947 if (URI == UNDEFINED_DEFAULT_NS)
2948 continue;
2949 if (URI == NULL)
2950 URI = ns->href;
2951 /*
2952 * TODO: The following will still be buggy for the
2953 * non-refactored code.
2954 */
2955 ret = xmlSearchNs(copy->doc, copy, ns->prefix);
2956 if ((ret == NULL) || (!xmlStrEqual(ret->href, URI)))
2957 {
2958 xmlNewNs(copy, URI, ns->prefix);
2959 }
2960 }
2961 if (copy->ns != NULL) {
2962 /*
2963 * Fix the node namespace if needed
2964 */
2965 copy->ns = xsltGetNamespace(ctxt, cur, copy->ns, copy);
2966 }
2967 }
2968 /*
2969 * all the attributes are directly inherited
2970 */
2971 if (cur->properties != NULL) {
2972 xsltAttrListTemplateProcess(ctxt, copy, cur->properties);
2973 }
2974 ctxt->inst = oldCurInst;
2975 }
2976#endif /* else of XSLT_REFACTORED */
2977
2978 /*
2979 * Descend into content in document order.
2980 */
2981 if (cur->children != NULL) {
2982 if (cur->children->type != XML_ENTITY_DECL) {
2983 cur = cur->children;
2984 level++;
2985 if (copy != NULL)
2986 insert = copy;
2987 continue;
2988 }
2989 }
2990
2991skip_children:
2992 /*
2993 * If xslt:message was just processed, we might have hit a
2994 * terminate='yes'; if so, then break the loop and clean up.
2995 * TODO: Do we need to check this also before trying to descend
2996 * into the content?
2997 */
2998 if (ctxt->state == XSLT_STATE_STOPPED)
2999 break;
3000 if (cur->next != NULL) {
3001 cur = cur->next;
3002 continue;
3003 }
3004
3005 do {
3006 cur = cur->parent;
3007 level--;
3008 /*
3009 * Pop variables/params (xsl:variable and xsl:param).
3010 */
3011 if ((ctxt->varsNr > oldVarsNr) && (ctxt->vars->level > level)) {
3012 xsltLocalVariablePop(ctxt, oldVarsNr, level);
3013 }
3014
3015 insert = insert->parent;
3016 if (cur == NULL)
3017 break;
3018 if (cur == list->parent) {
3019 cur = NULL;
3020 break;
3021 }
3022 if (cur->next != NULL) {
3023 cur = cur->next;
3024 break;
3025 }
3026 } while (cur != NULL);
3027 }
3028
3029error:
3030 /*
3031 * In case of errors: pop remaining variables.
3032 */
3033 if (ctxt->varsNr > oldVarsNr)
3034 xsltLocalVariablePop(ctxt, oldVarsNr, -1);
3035
3036 ctxt->node = oldContextNode;
3037 ctxt->inst = oldInst;
3038 ctxt->insert = oldInsert;
3039
3040 ctxt->depth--;
3041
3042#ifdef WITH_DEBUGGER
3043 if ((ctxt->debugStatus != XSLT_DEBUG_NONE) && (addCallResult)) {
3044 xslDropCall();
3045 }
3046#endif
3047}
3048
3049/*
3050* xsltApplyXSLTTemplate:
3051* @ctxt: a XSLT transformation context
3052* @contextNode: the node in the source tree.
3053* @list: the nodes of a sequence constructor;
3054* (plus leading xsl:param elements)
3055* @templ: the compiled xsl:template declaration;
3056* NULL if a sequence constructor
3057* @withParams: a set of caller-parameters (xsl:with-param) or NULL
3058*
3059* Called by:
3060* - xsltApplyImports()
3061* - xsltCallTemplate()
3062* - xsltDefaultProcessOneNode()
3063* - xsltProcessOneNode()
3064*/
3065static void
3067 xmlNodePtr contextNode,
3068 xmlNodePtr list,
3069 xsltTemplatePtr templ,
3070 xsltStackElemPtr withParams)
3071{
3072 int oldVarsBase = 0;
3073 xmlNodePtr cur;
3074 xsltStackElemPtr tmpParam = NULL;
3075 xmlDocPtr oldUserFragmentTop;
3076#ifdef WITH_PROFILER
3077 long start = 0;
3078#endif
3079
3080#ifdef XSLT_REFACTORED
3081 xsltStyleItemParamPtr iparam;
3082#else
3083 xsltStylePreCompPtr iparam;
3084#endif
3085
3086#ifdef WITH_DEBUGGER
3087 int addCallResult = 0;
3088#endif
3089
3090 if (ctxt == NULL)
3091 return;
3092 if (templ == NULL) {
3094 "xsltApplyXSLTTemplate: Bad arguments; @templ is mandatory.\n");
3095 return;
3096 }
3097
3098#ifdef WITH_DEBUGGER
3099 if (ctxt->debugStatus != XSLT_DEBUG_NONE) {
3100 if (xsltDebuggerStartSequenceConstructor(ctxt, contextNode,
3101 list, templ, &addCallResult) == NULL)
3102 return;
3103 }
3104#endif
3105
3106 if (list == NULL)
3107 return;
3109
3110 if (ctxt->varsNr >= ctxt->maxTemplateVars)
3111 {
3113 "xsltApplyXSLTTemplate: A potential infinite template recursion "
3114 "was detected.\n"
3115 "You can adjust maxTemplateVars (--maxvars) in order to "
3116 "raise the maximum number of variables/params (currently set to %d).\n",
3117 ctxt->maxTemplateVars);
3118 xsltDebug(ctxt, contextNode, list, NULL);
3119 ctxt->state = XSLT_STATE_STOPPED;
3120 return;
3121 }
3122
3123 oldUserFragmentTop = ctxt->tmpRVT;
3124 ctxt->tmpRVT = NULL;
3125
3126 /*
3127 * Initiate a distinct scope of local params/variables.
3128 */
3129 oldVarsBase = ctxt->varsBase;
3130 ctxt->varsBase = ctxt->varsNr;
3131
3132 ctxt->node = contextNode;
3133
3134#ifdef WITH_PROFILER
3135 if (ctxt->profile) {
3136 templ->nbCalls++;
3137 start = xsltTimestamp();
3138 profPush(ctxt, 0);
3139 profCallgraphAdd(templ, ctxt->templ);
3140 }
3141#endif
3142
3143 /*
3144 * Push the xsl:template declaration onto the stack.
3145 */
3146 templPush(ctxt, templ);
3147
3148#ifdef WITH_XSLT_DEBUG_PROCESS
3149 if (templ->name != NULL)
3151 "applying xsl:template '%s'\n", templ->name));
3152#endif
3153 /*
3154 * Process xsl:param instructions and skip those elements for
3155 * further processing.
3156 */
3157 cur = list;
3158 do {
3159 if (cur->type == XML_TEXT_NODE) {
3160 cur = cur->next;
3161 continue;
3162 }
3163 if ((cur->type != XML_ELEMENT_NODE) ||
3164 (cur->name[0] != 'p') ||
3165 (cur->psvi == NULL) ||
3166 (! xmlStrEqual(cur->name, BAD_CAST "param")) ||
3167 (! IS_XSLT_ELEM(cur)))
3168 {
3169 break;
3170 }
3171
3172 list = cur->next;
3173
3174#ifdef XSLT_REFACTORED
3175 iparam = (xsltStyleItemParamPtr) cur->psvi;
3176#else
3177 iparam = (xsltStylePreCompPtr) cur->psvi;
3178#endif
3179
3180 /*
3181 * Substitute xsl:param for a given xsl:with-param.
3182 * Since the XPath expression will reference the params/vars
3183 * by index, we need to slot the xsl:with-params in the
3184 * order of encountered xsl:params to keep the sequence of
3185 * params/variables in the stack exactly as it was at
3186 * compile time,
3187 */
3188 tmpParam = NULL;
3189 if (withParams) {
3190 tmpParam = withParams;
3191 do {
3192 if ((tmpParam->name == (iparam->name)) &&
3193 (tmpParam->nameURI == (iparam->ns)))
3194 {
3195 /*
3196 * Push the caller-parameter.
3197 */
3198 xsltLocalVariablePush(ctxt, tmpParam, -1);
3199 break;
3200 }
3201 tmpParam = tmpParam->next;
3202 } while (tmpParam != NULL);
3203 }
3204 /*
3205 * Push the xsl:param.
3206 */
3207 if (tmpParam == NULL) {
3208 /*
3209 * Note that we must assume that the added parameter
3210 * has a @depth of 0.
3211 */
3213 }
3214 cur = cur->next;
3215 } while (cur != NULL);
3216 /*
3217 * Process the sequence constructor.
3218 */
3219 xsltApplySequenceConstructor(ctxt, contextNode, list, templ);
3220
3221 /*
3222 * Remove remaining xsl:param and xsl:with-param items from
3223 * the stack. Don't free xsl:with-param items.
3224 */
3225 if (ctxt->varsNr > ctxt->varsBase)
3227 ctxt->varsBase = oldVarsBase;
3228
3229 /*
3230 * Release user-created fragments stored in the scope
3231 * of xsl:template. Note that this mechanism is deprecated:
3232 * user code should now use xsltRegisterLocalRVT() instead
3233 * of the obsolete xsltRegisterTmpRVT().
3234 */
3235 if (ctxt->tmpRVT) {
3236 xmlDocPtr curdoc = ctxt->tmpRVT, tmp;
3237
3238 while (curdoc != NULL) {
3239 tmp = curdoc;
3240 curdoc = (xmlDocPtr) curdoc->next;
3241 xsltReleaseRVT(ctxt, tmp);
3242 }
3243 }
3244 ctxt->tmpRVT = oldUserFragmentTop;
3245
3246 /*
3247 * Pop the xsl:template declaration from the stack.
3248 */
3249 templPop(ctxt);
3250
3251#ifdef WITH_PROFILER
3252 if (ctxt->profile) {
3253 long spent, child, total, end;
3254
3255 end = xsltTimestamp();
3256 child = profPop(ctxt);
3257 total = end - start;
3258 spent = total - child;
3259 if (spent <= 0) {
3260 /*
3261 * Not possible unless the original calibration failed
3262 * we can try to correct it on the fly.
3263 */
3264 xsltCalibrateAdjust(spent);
3265 spent = 0;
3266 }
3267
3268 templ->time += spent;
3269 if (ctxt->profNr > 0)
3270 ctxt->profTab[ctxt->profNr - 1] += total;
3271 }
3272#endif
3273
3274#ifdef WITH_DEBUGGER
3275 if ((ctxt->debugStatus != XSLT_DEBUG_NONE) && (addCallResult)) {
3276 xslDropCall();
3277 }
3278#endif
3279}
3280
3281
3312void
3314 xmlNodePtr contextNode,
3315 xmlNodePtr list,
3318{
3319 if ((ctxt == NULL) || (list == NULL))
3320 return;
3322
3323 if (params) {
3324 /*
3325 * This code should be obsolete - was previously used
3326 * by libexslt/functions.c, but due to bug 381319 the
3327 * logic there was changed.
3328 */
3329 int oldVarsNr = ctxt->varsNr;
3330
3331 /*
3332 * Push the given xsl:param(s) onto the variable stack.
3333 */
3334 while (params != NULL) {
3335 xsltLocalVariablePush(ctxt, params, -1);
3336 params = params->next;
3337 }
3338 xsltApplySequenceConstructor(ctxt, contextNode, list, templ);
3339 /*
3340 * Pop the given xsl:param(s) from the stack but don't free them.
3341 */
3342 xsltLocalVariablePop(ctxt, oldVarsNr, -2);
3343 } else
3344 xsltApplySequenceConstructor(ctxt, contextNode, list, templ);
3345}
3346
3347/************************************************************************
3348 * *
3349 * XSLT-1.1 extensions *
3350 * *
3351 ************************************************************************/
3352
3362void
3364 xmlNodePtr inst, xsltElemPreCompPtr castedComp)
3365{
3366#ifdef XSLT_REFACTORED
3367 xsltStyleItemDocumentPtr comp = (xsltStyleItemDocumentPtr) castedComp;
3368#else
3369 xsltStylePreCompPtr comp = (xsltStylePreCompPtr) castedComp;
3370#endif
3372 int ret;
3373 xmlChar *filename = NULL, *prop, *elements;
3374 xmlChar *element, *end;
3375 xmlDocPtr res = NULL;
3376 xmlDocPtr oldOutput;
3377 xmlNodePtr oldInsert, root;
3378 const char *oldOutputFile;
3379 xsltOutputType oldType;
3380 xmlChar *URL = NULL;
3381 const xmlChar *method;
3382 const xmlChar *doctypePublic;
3383 const xmlChar *doctypeSystem;
3384 const xmlChar *version;
3385 const xmlChar *encoding;
3386 int redirect_write_append = 0;
3387
3388 if ((ctxt == NULL) || (node == NULL) || (inst == NULL) || (comp == NULL))
3389 return;
3390
3391 if (comp->filename == NULL) {
3392
3393 if (xmlStrEqual(inst->name, (const xmlChar *) "output")) {
3394 /*
3395 * The element "output" is in the namespace XSLT_SAXON_NAMESPACE
3396 * (http://icl.com/saxon)
3397 * The @file is in no namespace.
3398 */
3399#ifdef WITH_XSLT_DEBUG_EXTRA
3401 "Found saxon:output extension\n");
3402#endif
3403 URL = xsltEvalAttrValueTemplate(ctxt, inst,
3404 (const xmlChar *) "file",
3406
3407 if (URL == NULL)
3408 URL = xsltEvalAttrValueTemplate(ctxt, inst,
3409 (const xmlChar *) "href",
3411 } else if (xmlStrEqual(inst->name, (const xmlChar *) "write")) {
3412#ifdef WITH_XSLT_DEBUG_EXTRA
3414 "Found xalan:write extension\n");
3415#endif
3416 URL = xsltEvalAttrValueTemplate(ctxt, inst,
3417 (const xmlChar *)
3418 "select",
3420 if (URL != NULL) {
3421 xmlXPathCompExprPtr cmp;
3422 xmlChar *val;
3423
3424 /*
3425 * Trying to handle bug #59212
3426 * The value of the "select" attribute is an
3427 * XPath expression.
3428 * (see http://xml.apache.org/xalan-j/extensionslib.html#redirect)
3429 */
3430 cmp = xmlXPathCtxtCompile(ctxt->xpathCtxt, URL);
3431 val = xsltEvalXPathString(ctxt, cmp);
3432 xmlXPathFreeCompExpr(cmp);
3433 xmlFree(URL);
3434 URL = val;
3435 }
3436 if (URL == NULL)
3437 URL = xsltEvalAttrValueTemplate(ctxt, inst,
3438 (const xmlChar *)
3439 "file",
3441 if (URL == NULL)
3442 URL = xsltEvalAttrValueTemplate(ctxt, inst,
3443 (const xmlChar *)
3444 "href",
3446 } else if (xmlStrEqual(inst->name, (const xmlChar *) "document")) {
3447 URL = xsltEvalAttrValueTemplate(ctxt, inst,
3448 (const xmlChar *) "href",
3449 NULL);
3450 }
3451
3452 } else {
3453 URL = xmlStrdup(comp->filename);
3454 }
3455
3456 if (URL == NULL) {
3457 xsltTransformError(ctxt, NULL, inst,
3458 "xsltDocumentElem: href/URI-Reference not found\n");
3459 return;
3460 }
3461
3462 /*
3463 * If the computation failed, it's likely that the URL wasn't escaped
3464 */
3465 filename = xmlBuildURI(URL, (const xmlChar *) ctxt->outputFile);
3466 if (filename == NULL) {
3467 xmlChar *escURL;
3468
3469 escURL=xmlURIEscapeStr(URL, BAD_CAST ":/.?,");
3470 if (escURL != NULL) {
3471 filename = xmlBuildURI(escURL, (const xmlChar *) ctxt->outputFile);
3472 xmlFree(escURL);
3473 }
3474 }
3475
3476 if (filename == NULL) {
3477 xsltTransformError(ctxt, NULL, inst,
3478 "xsltDocumentElem: URL computation failed for %s\n",
3479 URL);
3480 xmlFree(URL);
3481 return;
3482 }
3483
3484 /*
3485 * Security checking: can we write to this resource
3486 */
3487 if (ctxt->sec != NULL) {
3488 ret = xsltCheckWrite(ctxt->sec, ctxt, filename);
3489 if (ret <= 0) {
3490 if (ret == 0)
3491 xsltTransformError(ctxt, NULL, inst,
3492 "xsltDocumentElem: write rights for %s denied\n",
3493 filename);
3494 xmlFree(URL);
3496 return;
3497 }
3498 }
3499
3500 oldOutputFile = ctxt->outputFile;
3501 oldOutput = ctxt->output;
3502 oldInsert = ctxt->insert;
3503 oldType = ctxt->type;
3504 ctxt->outputFile = (const char *) filename;
3505
3507 if (style == NULL) {
3508 xsltTransformError(ctxt, NULL, inst,
3509 "xsltDocumentElem: out of memory\n");
3510 goto error;
3511 }
3512
3513 /*
3514 * Version described in 1.1 draft allows full parameterization
3515 * of the output.
3516 */
3517 prop = xsltEvalAttrValueTemplate(ctxt, inst,
3518 (const xmlChar *) "version",
3519 NULL);
3520 if (prop != NULL) {
3521 if (style->version != NULL)
3522 xmlFree(style->version);
3523 style->version = prop;
3524 }
3525 prop = xsltEvalAttrValueTemplate(ctxt, inst,
3526 (const xmlChar *) "encoding",
3527 NULL);
3528 if (prop != NULL) {
3529 if (style->encoding != NULL)
3530 xmlFree(style->encoding);
3531 style->encoding = prop;
3532 }
3533 prop = xsltEvalAttrValueTemplate(ctxt, inst,
3534 (const xmlChar *) "method",
3535 NULL);
3536 if (prop != NULL) {
3537 const xmlChar *URI;
3538
3539 if (style->method != NULL)
3540 xmlFree(style->method);
3541 style->method = NULL;
3542 if (style->methodURI != NULL)
3543 xmlFree(style->methodURI);
3544 style->methodURI = NULL;
3545
3546 URI = xsltGetQNameURI(inst, &prop);
3547 if (prop == NULL) {
3548 if (style != NULL) style->errors++;
3549 } else if (URI == NULL) {
3550 if ((xmlStrEqual(prop, (const xmlChar *) "xml")) ||
3551 (xmlStrEqual(prop, (const xmlChar *) "html")) ||
3552 (xmlStrEqual(prop, (const xmlChar *) "text"))) {
3553 style->method = prop;
3554 } else {
3555 xsltTransformError(ctxt, NULL, inst,
3556 "invalid value for method: %s\n", prop);
3557 if (style != NULL) style->warnings++;
3558 }
3559 } else {
3560 style->method = prop;
3561 style->methodURI = xmlStrdup(URI);
3562 }
3563 }
3564 prop = xsltEvalAttrValueTemplate(ctxt, inst,
3565 (const xmlChar *)
3566 "doctype-system", NULL);
3567 if (prop != NULL) {
3568 if (style->doctypeSystem != NULL)
3569 xmlFree(style->doctypeSystem);
3570 style->doctypeSystem = prop;
3571 }
3572 prop = xsltEvalAttrValueTemplate(ctxt, inst,
3573 (const xmlChar *)
3574 "doctype-public", NULL);
3575 if (prop != NULL) {
3576 if (style->doctypePublic != NULL)
3577 xmlFree(style->doctypePublic);
3578 style->doctypePublic = prop;
3579 }
3580 prop = xsltEvalAttrValueTemplate(ctxt, inst,
3581 (const xmlChar *) "standalone",
3582 NULL);
3583 if (prop != NULL) {
3584 if (xmlStrEqual(prop, (const xmlChar *) "yes")) {
3585 style->standalone = 1;
3586 } else if (xmlStrEqual(prop, (const xmlChar *) "no")) {
3587 style->standalone = 0;
3588 } else {
3589 xsltTransformError(ctxt, NULL, inst,
3590 "invalid value for standalone: %s\n",
3591 prop);
3592 if (style != NULL) style->warnings++;
3593 }
3594 xmlFree(prop);
3595 }
3596
3597 prop = xsltEvalAttrValueTemplate(ctxt, inst,
3598 (const xmlChar *) "indent",
3599 NULL);
3600 if (prop != NULL) {
3601 if (xmlStrEqual(prop, (const xmlChar *) "yes")) {
3602 style->indent = 1;
3603 } else if (xmlStrEqual(prop, (const xmlChar *) "no")) {
3604 style->indent = 0;
3605 } else {
3606 xsltTransformError(ctxt, NULL, inst,
3607 "invalid value for indent: %s\n", prop);
3608 if (style != NULL) style->warnings++;
3609 }
3610 xmlFree(prop);
3611 }
3612
3613 prop = xsltEvalAttrValueTemplate(ctxt, inst,
3614 (const xmlChar *)
3615 "omit-xml-declaration",
3616 NULL);
3617 if (prop != NULL) {
3618 if (xmlStrEqual(prop, (const xmlChar *) "yes")) {
3619 style->omitXmlDeclaration = 1;
3620 } else if (xmlStrEqual(prop, (const xmlChar *) "no")) {
3621 style->omitXmlDeclaration = 0;
3622 } else {
3623 xsltTransformError(ctxt, NULL, inst,
3624 "invalid value for omit-xml-declaration: %s\n",
3625 prop);
3626 if (style != NULL) style->warnings++;
3627 }
3628 xmlFree(prop);
3629 }
3630
3631 elements = xsltEvalAttrValueTemplate(ctxt, inst,
3632 (const xmlChar *)
3633 "cdata-section-elements",
3634 NULL);
3635 if (elements != NULL) {
3636 if (style->stripSpaces == NULL)
3637 style->stripSpaces = xmlHashCreate(10);
3638 if (style->stripSpaces == NULL) {
3639 xmlFree(elements);
3640 return;
3641 }
3642
3643 element = elements;
3644 while (*element != 0) {
3645 while (xmlIsBlank_ch(*element))
3646 element++;
3647 if (*element == 0)
3648 break;
3649 end = element;
3650 while ((*end != 0) && (!xmlIsBlank_ch(*end)))
3651 end++;
3653 if (element) {
3654 const xmlChar *URI;
3655
3656#ifdef WITH_XSLT_DEBUG_PARSING
3658 "add cdata section output element %s\n",
3659 element);
3660#endif
3661 URI = xsltGetQNameURI(inst, &element);
3662
3663 xmlHashAddEntry2(style->stripSpaces, element, URI,
3664 (xmlChar *) "cdata");
3666 }
3667 element = end;
3668 }
3669 xmlFree(elements);
3670 }
3671
3672 /*
3673 * Create a new document tree and process the element template
3674 */
3676 XSLT_GET_IMPORT_PTR(doctypePublic, style, doctypePublic)
3677 XSLT_GET_IMPORT_PTR(doctypeSystem, style, doctypeSystem)
3679 XSLT_GET_IMPORT_PTR(encoding, style, encoding)
3680
3681 if ((method != NULL) &&
3682 (!xmlStrEqual(method, (const xmlChar *) "xml"))) {
3683 if (xmlStrEqual(method, (const xmlChar *) "html")) {
3684 ctxt->type = XSLT_OUTPUT_HTML;
3685 if (((doctypePublic != NULL) || (doctypeSystem != NULL)))
3686 res = htmlNewDoc(doctypeSystem, doctypePublic);
3687 else {
3688 if (version != NULL) {
3689#ifdef XSLT_GENERATE_HTML_DOCTYPE
3690 xsltGetHTMLIDs(version, &doctypePublic, &doctypeSystem);
3691#endif
3692 }
3693 res = htmlNewDocNoDtD(doctypeSystem, doctypePublic);
3694 }
3695 if (res == NULL)
3696 goto error;
3697 res->dict = ctxt->dict;
3698 xmlDictReference(res->dict);
3699 } else if (xmlStrEqual(method, (const xmlChar *) "xhtml")) {
3700 xsltTransformError(ctxt, NULL, inst,
3701 "xsltDocumentElem: unsupported method xhtml\n");
3702 ctxt->type = XSLT_OUTPUT_HTML;
3703 res = htmlNewDocNoDtD(doctypeSystem, doctypePublic);
3704 if (res == NULL)
3705 goto error;
3706 res->dict = ctxt->dict;
3707 xmlDictReference(res->dict);
3708 } else if (xmlStrEqual(method, (const xmlChar *) "text")) {
3709 ctxt->type = XSLT_OUTPUT_TEXT;
3710 res = xmlNewDoc(style->version);
3711 if (res == NULL)
3712 goto error;
3713 res->dict = ctxt->dict;
3714 xmlDictReference(res->dict);
3715#ifdef WITH_XSLT_DEBUG
3717 "reusing transformation dict for output\n");
3718#endif
3719 } else {
3720 xsltTransformError(ctxt, NULL, inst,
3721 "xsltDocumentElem: unsupported method (%s)\n",
3722 method);
3723 goto error;
3724 }
3725 } else {
3726 ctxt->type = XSLT_OUTPUT_XML;
3727 res = xmlNewDoc(style->version);
3728 if (res == NULL)
3729 goto error;
3730 res->dict = ctxt->dict;
3731 xmlDictReference(res->dict);
3732#ifdef WITH_XSLT_DEBUG
3734 "reusing transformation dict for output\n");
3735#endif
3736 }
3737 res->charset = XML_CHAR_ENCODING_UTF8;
3738 if (encoding != NULL)
3739 res->encoding = xmlStrdup(encoding);
3740 ctxt->output = res;
3741 ctxt->insert = (xmlNodePtr) res;
3742 xsltApplySequenceConstructor(ctxt, node, inst->children, NULL);
3743
3744 /*
3745 * Do some post processing work depending on the generated output
3746 */
3747 root = xmlDocGetRootElement(res);
3748 if (root != NULL) {
3749 const xmlChar *doctype = NULL;
3750
3751 if ((root->ns != NULL) && (root->ns->prefix != NULL))
3752 doctype = xmlDictQLookup(ctxt->dict, root->ns->prefix, root->name);
3753 if (doctype == NULL)
3754 doctype = root->name;
3755
3756 /*
3757 * Apply the default selection of the method
3758 */
3759 if ((method == NULL) &&
3760 (root->ns == NULL) &&
3761 (!xmlStrcasecmp(root->name, (const xmlChar *) "html"))) {
3762 xmlNodePtr tmp;
3763
3764 tmp = res->children;
3765 while ((tmp != NULL) && (tmp != root)) {
3766 if (tmp->type == XML_ELEMENT_NODE)
3767 break;
3768 if ((tmp->type == XML_TEXT_NODE) && (!xmlIsBlankNode(tmp)))
3769 break;
3770 tmp = tmp->next;
3771 }
3772 if (tmp == root) {
3773 ctxt->type = XSLT_OUTPUT_HTML;
3774 res->type = XML_HTML_DOCUMENT_NODE;
3775 if (((doctypePublic != NULL) || (doctypeSystem != NULL))) {
3776 res->intSubset = xmlCreateIntSubset(res, doctype,
3777 doctypePublic,
3778 doctypeSystem);
3779#ifdef XSLT_GENERATE_HTML_DOCTYPE
3780 } else if (version != NULL) {
3781 xsltGetHTMLIDs(version, &doctypePublic,
3782 &doctypeSystem);
3783 if (((doctypePublic != NULL) || (doctypeSystem != NULL)))
3784 res->intSubset =
3785 xmlCreateIntSubset(res, doctype,
3786 doctypePublic,
3787 doctypeSystem);
3788#endif
3789 }
3790 }
3791
3792 }
3793 if (ctxt->type == XSLT_OUTPUT_XML) {
3794 XSLT_GET_IMPORT_PTR(doctypePublic, style, doctypePublic)
3795 XSLT_GET_IMPORT_PTR(doctypeSystem, style, doctypeSystem)
3796 if (((doctypePublic != NULL) || (doctypeSystem != NULL)))
3797 res->intSubset = xmlCreateIntSubset(res, doctype,
3798 doctypePublic,
3799 doctypeSystem);
3800 }
3801 }
3802
3803 /*
3804 * Calls to redirect:write also take an optional attribute append.
3805 * Attribute append="true|yes" which will attempt to simply append
3806 * to an existing file instead of always opening a new file. The
3807 * default behavior of always overwriting the file still happens
3808 * if we do not specify append.
3809 * Note that append use will forbid use of remote URI target.
3810 */
3811 prop = xsltEvalAttrValueTemplate(ctxt, inst, (const xmlChar *)"append",
3812 NULL);
3813 if (prop != NULL) {
3814 if (xmlStrEqual(prop, (const xmlChar *) "true") ||
3815 xmlStrEqual(prop, (const xmlChar *) "yes")) {
3816 style->omitXmlDeclaration = 1;
3817 redirect_write_append = 1;
3818 } else
3819 style->omitXmlDeclaration = 0;
3820 xmlFree(prop);
3821 }
3822
3823 if (redirect_write_append) {
3824 FILE *f;
3825
3826 f = fopen((const char *) filename, "ab");
3827 if (f == NULL) {
3828 ret = -1;
3829 } else {
3831 fclose(f);
3832 }
3833 } else {
3834 ret = xsltSaveResultToFilename((const char *) filename, res, style, 0);
3835 }
3836 if (ret < 0) {
3837 xsltTransformError(ctxt, NULL, inst,
3838 "xsltDocumentElem: unable to save to %s\n",
3839 filename);
3840#ifdef WITH_XSLT_DEBUG_EXTRA
3841 } else {
3843 "Wrote %d bytes to %s\n", ret, filename);
3844#endif
3845 }
3846
3847 error:
3848 ctxt->output = oldOutput;
3849 ctxt->insert = oldInsert;
3850 ctxt->type = oldType;
3851 ctxt->outputFile = oldOutputFile;
3852 if (URL != NULL)
3853 xmlFree(URL);
3854 if (filename != NULL)
3856 if (style != NULL)
3858 if (res != NULL)
3859 xmlFreeDoc(res);
3860}
3861
3862/************************************************************************
3863 * *
3864 * Most of the XSLT-1.0 transformations *
3865 * *
3866 ************************************************************************/
3867
3878void
3880 xmlNodePtr node ATTRIBUTE_UNUSED, xmlNodePtr inst,
3881 xsltElemPreCompPtr comp) {
3882 if (comp == NULL) {
3883 xsltTransformError(ctxt, NULL, inst,
3884 "xsl:sort : compilation failed\n");
3885 return;
3886 }
3887 xsltTransformError(ctxt, NULL, inst,
3888 "xsl:sort : improper use this should not be reached\n");
3889}
3890
3900void
3902 xmlNodePtr inst, xsltElemPreCompPtr castedComp)
3903{
3904#ifdef XSLT_REFACTORED
3905 xsltStyleItemCopyPtr comp = (xsltStyleItemCopyPtr) castedComp;
3906#else
3907 xsltStylePreCompPtr comp = (xsltStylePreCompPtr) castedComp;
3908#endif
3909 xmlNodePtr copy, oldInsert;
3910
3911 oldInsert = ctxt->insert;
3912 if (ctxt->insert != NULL) {
3913 switch (node->type) {
3914 case XML_TEXT_NODE:
3915 case XML_CDATA_SECTION_NODE:
3916 /*
3917 * This text comes from the stylesheet
3918 * For stylesheets, the set of whitespace-preserving
3919 * element names consists of just xsl:text.
3920 */
3921#ifdef WITH_XSLT_DEBUG_PROCESS
3922 if (node->type == XML_CDATA_SECTION_NODE) {
3924 "xsltCopy: CDATA text %s\n", node->content));
3925 } else {
3927 "xsltCopy: text %s\n", node->content));
3928 }
3929#endif
3930 xsltCopyText(ctxt, ctxt->insert, node, 0);
3931 break;
3932 case XML_DOCUMENT_NODE:
3933 case XML_HTML_DOCUMENT_NODE:
3934 break;
3935 case XML_ELEMENT_NODE:
3936 /*
3937 * REVISIT NOTE: The "fake" is a doc-node, not an element node.
3938 * REMOVED:
3939 * if (xmlStrEqual(node->name, BAD_CAST " fake node libxslt"))
3940 * return;
3941 */
3942
3943#ifdef WITH_XSLT_DEBUG_PROCESS
3945 "xsltCopy: node %s\n", node->name));
3946#endif
3947 copy = xsltShallowCopyElem(ctxt, node, ctxt->insert, 0);
3948 ctxt->insert = copy;
3949 if (comp->use != NULL) {
3950 xsltApplyAttributeSet(ctxt, node, inst, comp->use);
3951 }
3952 break;
3953 case XML_ATTRIBUTE_NODE: {
3954#ifdef WITH_XSLT_DEBUG_PROCESS
3956 "xsltCopy: attribute %s\n", node->name));
3957#endif
3958 /*
3959 * REVISIT: We could also raise an error if the parent is not
3960 * an element node.
3961 * OPTIMIZE TODO: Can we set the value/children of the
3962 * attribute without an intermediate copy of the string value?
3963 */
3964 xsltShallowCopyAttr(ctxt, inst, ctxt->insert, (xmlAttrPtr) node);
3965 break;
3966 }
3967 case XML_PI_NODE:
3968#ifdef WITH_XSLT_DEBUG_PROCESS
3970 "xsltCopy: PI %s\n", node->name));
3971#endif
3972 copy = xmlNewDocPI(ctxt->insert->doc, node->name,
3973 node->content);
3974 copy = xsltAddChild(ctxt->insert, copy);
3975 break;
3976 case XML_COMMENT_NODE:
3977#ifdef WITH_XSLT_DEBUG_PROCESS
3979 "xsltCopy: comment\n"));
3980#endif
3981 copy = xmlNewComment(node->content);
3982 copy = xsltAddChild(ctxt->insert, copy);
3983 break;
3984 case XML_NAMESPACE_DECL:
3985#ifdef WITH_XSLT_DEBUG_PROCESS
3987 "xsltCopy: namespace declaration\n"));
3988#endif
3989 xsltShallowCopyNsNode(ctxt, inst, ctxt->insert, (xmlNsPtr)node);
3990 break;
3991 default:
3992 break;
3993
3994 }
3995 }
3996
3997 switch (node->type) {
3998 case XML_DOCUMENT_NODE:
3999 case XML_HTML_DOCUMENT_NODE:
4000 case XML_ELEMENT_NODE:
4001 xsltApplySequenceConstructor(ctxt, ctxt->node, inst->children,
4002 NULL);
4003 break;
4004 default:
4005 break;
4006 }
4007 ctxt->insert = oldInsert;
4008}
4009
4019void
4021 xmlNodePtr inst, xsltElemPreCompPtr comp ATTRIBUTE_UNUSED) {
4022 if ((inst->children != NULL) && (comp != NULL)) {
4023 xmlNodePtr text = inst->children;
4024 xmlNodePtr copy;
4025
4026 while (text != NULL) {
4027 if ((text->type != XML_TEXT_NODE) &&
4028 (text->type != XML_CDATA_SECTION_NODE)) {
4029 xsltTransformError(ctxt, NULL, inst,
4030 "xsl:text content problem\n");
4031 break;
4032 }
4033 copy = xmlNewDocText(ctxt->output, text->content);
4034 if (text->type != XML_CDATA_SECTION_NODE) {
4035#ifdef WITH_XSLT_DEBUG_PARSING
4037 "Disable escaping: %s\n", text->content);
4038#endif
4039 copy->name = xmlStringTextNoenc;
4040 }
4041 copy = xsltAddChild(ctxt->insert, copy);
4042 text = text->next;
4043 }
4044 }
4045}
4046
4056void
4058 xmlNodePtr inst, xsltElemPreCompPtr castedComp) {
4059#ifdef XSLT_REFACTORED
4060 xsltStyleItemElementPtr comp = (xsltStyleItemElementPtr) castedComp;
4061#else
4062 xsltStylePreCompPtr comp = (xsltStylePreCompPtr) castedComp;
4063#endif
4064 xmlChar *prop = NULL;
4065 const xmlChar *name, *prefix = NULL, *nsName = NULL;
4066 xmlNodePtr copy;
4067 xmlNodePtr oldInsert;
4068
4069 if (ctxt->insert == NULL)
4070 return;
4071
4072 /*
4073 * A comp->has_name == 0 indicates that we need to skip this instruction,
4074 * since it was evaluated to be invalid already during compilation.
4075 */
4076 if (!comp->has_name)
4077 return;
4078
4079 /*
4080 * stack and saves
4081 */
4082 oldInsert = ctxt->insert;
4083
4084 if (comp->name == NULL) {
4085 /* TODO: fix attr acquisition wrt to the XSLT namespace */
4086 prop = xsltEvalAttrValueTemplate(ctxt, inst,
4087 (const xmlChar *) "name", XSLT_NAMESPACE);
4088 if (prop == NULL) {
4089 xsltTransformError(ctxt, NULL, inst,
4090 "xsl:element: The attribute 'name' is missing.\n");
4091 goto error;
4092 }
4093 if (xmlValidateQName(prop, 0)) {
4094 xsltTransformError(ctxt, NULL, inst,
4095 "xsl:element: The effective name '%s' is not a "
4096 "valid QName.\n", prop);
4097 /* we fall through to catch any further errors, if possible */
4098 }
4099 name = xsltSplitQName(ctxt->dict, prop, &prefix);
4100 xmlFree(prop);
4101 } else {
4102 /*
4103 * The "name" value was static.
4104 */
4105#ifdef XSLT_REFACTORED
4106 prefix = comp->nsPrefix;
4107 name = comp->name;
4108#else
4109 name = xsltSplitQName(ctxt->dict, comp->name, &prefix);
4110#endif
4111 }
4112
4113 /*
4114 * Create the new element
4115 */
4116 if (ctxt->output->dict == ctxt->dict) {
4117 copy = xmlNewDocNodeEatName(ctxt->output, NULL, (xmlChar *)name, NULL);
4118 } else {
4119 copy = xmlNewDocNode(ctxt->output, NULL, (xmlChar *)name, NULL);
4120 }
4121 if (copy == NULL) {
4122 xsltTransformError(ctxt, NULL, inst,
4123 "xsl:element : creation of %s failed\n", name);
4124 return;
4125 }
4126 copy = xsltAddChild(ctxt->insert, copy);
4127 if (copy == NULL) {
4128 xsltTransformError(ctxt, NULL, inst,
4129 "xsl:element : xsltAddChild failed\n");
4130 return;
4131 }
4132
4133 /*
4134 * Namespace
4135 * ---------
4136 */
4137 if (comp->has_ns) {
4138 if (comp->ns != NULL) {
4139 /*
4140 * No AVT; just plain text for the namespace name.
4141 */
4142 if (comp->ns[0] != 0)
4143 nsName = comp->ns;
4144 } else {
4145 xmlChar *tmpNsName;
4146 /*
4147 * Eval the AVT.
4148 */
4149 /* TODO: check attr acquisition wrt to the XSLT namespace */
4150 tmpNsName = xsltEvalAttrValueTemplate(ctxt, inst,
4151 (const xmlChar *) "namespace", XSLT_NAMESPACE);
4152 /*
4153 * SPEC XSLT 1.0:
4154 * "If the string is empty, then the expanded-name of the
4155 * attribute has a null namespace URI."
4156 */
4157 if ((tmpNsName != NULL) && (tmpNsName[0] != 0))
4158 nsName = xmlDictLookup(ctxt->dict, BAD_CAST tmpNsName, -1);
4159 xmlFree(tmpNsName);
4160 }
4161
4162 if (xmlStrEqual(nsName, BAD_CAST "http://www.w3.org/2000/xmlns/")) {
4163 xsltTransformError(ctxt, NULL, inst,
4164 "xsl:attribute: Namespace http://www.w3.org/2000/xmlns/ "
4165 "forbidden.\n");
4166 goto error;
4167 }
4168 if (xmlStrEqual(nsName, XML_XML_NAMESPACE)) {
4169 prefix = BAD_CAST "xml";
4170 } else if (xmlStrEqual(prefix, BAD_CAST "xml")) {
4171 prefix = NULL;
4172 }
4173 } else {
4174 xmlNsPtr ns;
4175 /*
4176 * SPEC XSLT 1.0:
4177 * "If the namespace attribute is not present, then the QName is
4178 * expanded into an expanded-name using the namespace declarations
4179 * in effect for the xsl:element element, including any default
4180 * namespace declaration.
4181 */
4182 ns = xmlSearchNs(inst->doc, inst, prefix);
4183 if (ns == NULL) {
4184 /*
4185 * TODO: Check this in the compilation layer in case it's a
4186 * static value.
4187 */
4188 if (prefix != NULL) {
4189 xsltTransformError(ctxt, NULL, inst,
4190 "xsl:element: The QName '%s:%s' has no "
4191 "namespace binding in scope in the stylesheet; "
4192 "this is an error, since the namespace was not "
4193 "specified by the instruction itself.\n", prefix, name);
4194 }
4195 } else
4196 nsName = ns->href;
4197 }
4198 /*
4199 * Find/create a matching ns-decl in the result tree.
4200 */
4201 if (nsName != NULL) {
4202 if (xmlStrEqual(prefix, BAD_CAST "xmlns")) {
4203 /* Don't use a prefix of "xmlns" */
4204 xmlChar *pref = xmlStrdup(BAD_CAST "ns_1");
4205
4206 copy->ns = xsltGetSpecialNamespace(ctxt, inst, nsName, pref, copy);
4207
4208 xmlFree(pref);
4209 } else {
4210 copy->ns = xsltGetSpecialNamespace(ctxt, inst, nsName, prefix,
4211 copy);
4212 }
4213 } else if ((copy->parent != NULL) &&
4214 (copy->parent->type == XML_ELEMENT_NODE) &&
4215 (copy->parent->ns != NULL))
4216 {
4217 /*
4218 * "Undeclare" the default namespace.
4219 */
4220 xsltGetSpecialNamespace(ctxt, inst, NULL, NULL, copy);
4221 }
4222
4223 ctxt->insert = copy;
4224
4225 if (comp->has_use) {
4226 if (comp->use != NULL) {
4227 xsltApplyAttributeSet(ctxt, node, inst, comp->use);
4228 } else {
4229 xmlChar *attrSets = NULL;
4230 /*
4231 * BUG TODO: use-attribute-sets is not a value template.
4232 * use-attribute-sets = qnames
4233 */
4234 attrSets = xsltEvalAttrValueTemplate(ctxt, inst,
4235 (const xmlChar *)"use-attribute-sets", NULL);
4236 if (attrSets != NULL) {
4237 xsltApplyAttributeSet(ctxt, node, inst, attrSets);
4238 xmlFree(attrSets);
4239 }
4240 }
4241 }
4242 /*
4243 * Instantiate the sequence constructor.
4244 */
4245 if (inst->children != NULL)
4246 xsltApplySequenceConstructor(ctxt, ctxt->node, inst->children,
4247 NULL);
4248
4249error:
4250 ctxt->insert = oldInsert;
4251 return;
4252}
4253
4254
4264void
4266 xmlNodePtr inst, xsltElemPreCompPtr comp ATTRIBUTE_UNUSED) {
4267 xmlChar *value = NULL;
4268 xmlNodePtr commentNode;
4269 int len;
4270
4271 value = xsltEvalTemplateString(ctxt, node, inst);
4272 /* TODO: use or generate the compiled form */
4273 len = xmlStrlen(value);
4274 if (len > 0) {
4275 if ((value[len-1] == '-') ||
4276 (xmlStrstr(value, BAD_CAST "--"))) {
4277 xsltTransformError(ctxt, NULL, inst,
4278 "xsl:comment : '--' or ending '-' not allowed in comment\n");
4279 /* fall through to try to catch further errors */
4280 }
4281 }
4282#ifdef WITH_XSLT_DEBUG_PROCESS
4283 if (value == NULL) {
4285 "xsltComment: empty\n"));
4286 } else {
4288 "xsltComment: content %s\n", value));
4289 }
4290#endif
4291
4292 commentNode = xmlNewComment(value);
4293 commentNode = xsltAddChild(ctxt->insert, commentNode);
4294
4295 if (value != NULL)
4296 xmlFree(value);
4297}
4298
4308void
4310 xmlNodePtr inst, xsltElemPreCompPtr castedComp) {
4311#ifdef XSLT_REFACTORED
4312 xsltStyleItemPIPtr comp = (xsltStyleItemPIPtr) castedComp;
4313#else
4314 xsltStylePreCompPtr comp = (xsltStylePreCompPtr) castedComp;
4315#endif
4316 const xmlChar *name;
4317 xmlChar *value = NULL;
4318 xmlNodePtr pi;
4319
4320
4321 if (ctxt->insert == NULL)
4322 return;
4323 if (comp->has_name == 0)
4324 return;
4325 if (comp->name == NULL) {
4326 name = xsltEvalAttrValueTemplate(ctxt, inst,
4327 (const xmlChar *)"name", NULL);
4328 if (name == NULL) {
4329 xsltTransformError(ctxt, NULL, inst,
4330 "xsl:processing-instruction : name is missing\n");
4331 goto error;
4332 }
4333 } else {
4334 name = comp->name;
4335 }
4336 /* TODO: check that it's both an an NCName and a PITarget. */
4337
4338
4339 value = xsltEvalTemplateString(ctxt, node, inst);
4340 if (xmlStrstr(value, BAD_CAST "?>") != NULL) {
4341 xsltTransformError(ctxt, NULL, inst,
4342 "xsl:processing-instruction: '?>' not allowed within PI content\n");
4343 goto error;
4344 }
4345#ifdef WITH_XSLT_DEBUG_PROCESS
4346 if (value == NULL) {
4348 "xsltProcessingInstruction: %s empty\n", name));
4349 } else {
4351 "xsltProcessingInstruction: %s content %s\n", name, value));
4352 }
4353#endif
4354
4355 pi = xmlNewDocPI(ctxt->insert->doc, name, value);
4356 pi = xsltAddChild(ctxt->insert, pi);
4357
4358error:
4359 if ((name != NULL) && (name != comp->name))
4360 xmlFree((xmlChar *) name);
4361 if (value != NULL)
4362 xmlFree(value);
4363}
4364
4374void
4376 xmlNodePtr inst, xsltElemPreCompPtr castedComp) {
4377#ifdef XSLT_REFACTORED
4378 xsltStyleItemCopyOfPtr comp = (xsltStyleItemCopyOfPtr) castedComp;
4379#else
4380 xsltStylePreCompPtr comp = (xsltStylePreCompPtr) castedComp;
4381#endif
4382 xmlXPathObjectPtr res = NULL;
4383 xmlNodeSetPtr list = NULL;
4384 int i;
4385
4386 if ((ctxt == NULL) || (node == NULL) || (inst == NULL))
4387 return;
4388 if ((comp == NULL) || (comp->select == NULL) || (comp->comp == NULL)) {
4389 xsltTransformError(ctxt, NULL, inst,
4390 "xsl:copy-of : compilation failed\n");
4391 return;
4392 }
4393
4394 /*
4395 * SPEC XSLT 1.0:
4396 * "The xsl:copy-of element can be used to insert a result tree
4397 * fragment into the result tree, without first converting it to
4398 * a string as xsl:value-of does (see [7.6.1 Generating Text with
4399 * xsl:value-of]). The required select attribute contains an
4400 * expression. When the result of evaluating the expression is a
4401 * result tree fragment, the complete fragment is copied into the
4402 * result tree. When the result is a node-set, all the nodes in the
4403 * set are copied in document order into the result tree; copying
4404 * an element node copies the attribute nodes, namespace nodes and
4405 * children of the element node as well as the element node itself;
4406 * a root node is copied by copying its children. When the result
4407 * is neither a node-set nor a result tree fragment, the result is
4408 * converted to a string and then inserted into the result tree,
4409 * as with xsl:value-of.
4410 */
4411
4412#ifdef WITH_XSLT_DEBUG_PROCESS
4414 "xsltCopyOf: select %s\n", comp->select));
4415#endif
4416
4417 /*
4418 * Evaluate the "select" expression.
4419 */
4420 res = xsltPreCompEval(ctxt, node, comp);
4421
4422 if (res != NULL) {
4423 if (res->type == XPATH_NODESET) {
4424 /*
4425 * Node-set
4426 * --------
4427 */
4428#ifdef WITH_XSLT_DEBUG_PROCESS
4430 "xsltCopyOf: result is a node set\n"));
4431#endif
4432 list = res->nodesetval;
4433 if (list != NULL) {
4434 xmlNodePtr cur;
4435 /*
4436 * The list is already sorted in document order by XPath.
4437 * Append everything in this order under ctxt->insert.
4438 */
4439 for (i = 0;i < list->nodeNr;i++) {
4440 cur = list->nodeTab[i];
4441 if (cur == NULL)
4442 continue;
4443 if ((cur->type == XML_DOCUMENT_NODE) ||
4444 (cur->type == XML_HTML_DOCUMENT_NODE))
4445 {
4446 xsltCopyTreeList(ctxt, inst,
4447 cur->children, ctxt->insert, 0, 0);
4448 } else if (cur->type == XML_ATTRIBUTE_NODE) {
4449 xsltShallowCopyAttr(ctxt, inst,
4450 ctxt->insert, (xmlAttrPtr) cur);
4451 } else {
4452 xsltCopyTree(ctxt, inst, cur, ctxt->insert, 0, 0);
4453 }
4454 }
4455 }
4456 } else if (res->type == XPATH_XSLT_TREE) {
4457 /*
4458 * Result tree fragment
4459 * --------------------
4460 * E.g. via <xsl:variable ...><foo/></xsl:variable>
4461 * Note that the root node of such trees is an xmlDocPtr in Libxslt.
4462 */
4463#ifdef WITH_XSLT_DEBUG_PROCESS
4465 "xsltCopyOf: result is a result tree fragment\n"));
4466#endif
4467 list = res->nodesetval;
4468 if ((list != NULL) && (list->nodeTab != NULL) &&
4469 (list->nodeTab[0] != NULL) &&
4470 (IS_XSLT_REAL_NODE(list->nodeTab[0])))
4471 {
4472 xsltCopyTreeList(ctxt, inst,
4473 list->nodeTab[0]->children, ctxt->insert, 0, 0);
4474 }
4475 } else {
4476 xmlChar *value = NULL;
4477 /*
4478 * Convert to a string.
4479 */
4480 value = xmlXPathCastToString(res);
4481 if (value == NULL) {
4482 xsltTransformError(ctxt, NULL, inst,
4483 "Internal error in xsltCopyOf(): "
4484 "failed to cast an XPath object to string.\n");
4485 ctxt->state = XSLT_STATE_STOPPED;
4486 } else {
4487 if (value[0] != 0) {
4488 /*
4489 * Append content as text node.
4490 */
4491 xsltCopyTextString(ctxt, ctxt->insert, value, 0);
4492 }
4493 xmlFree(value);
4494
4495#ifdef WITH_XSLT_DEBUG_PROCESS
4497 "xsltCopyOf: result %s\n", res->stringval));
4498#endif
4499 }
4500 }
4501 } else {
4502 ctxt->state = XSLT_STATE_STOPPED;
4503 }
4504
4505 if (res != NULL)
4506 xmlXPathFreeObject(res);
4507}
4508
4518void
4520 xmlNodePtr inst, xsltElemPreCompPtr castedComp)
4521{
4522#ifdef XSLT_REFACTORED
4523 xsltStyleItemValueOfPtr comp = (xsltStyleItemValueOfPtr) castedComp;
4524#else
4525 xsltStylePreCompPtr comp = (xsltStylePreCompPtr) castedComp;
4526#endif
4527 xmlXPathObjectPtr res = NULL;
4528 xmlChar *value = NULL;
4529
4530 if ((ctxt == NULL) || (node == NULL) || (inst == NULL))
4531 return;
4532
4533 if ((comp == NULL) || (comp->select == NULL) || (comp->comp == NULL)) {
4534 xsltTransformError(ctxt, NULL, inst,
4535 "Internal error in xsltValueOf(): "
4536 "The XSLT 'value-of' instruction was not compiled.\n");
4537 return;
4538 }
4539
4540#ifdef WITH_XSLT_DEBUG_PROCESS
4542 "xsltValueOf: select %s\n", comp->select));
4543#endif
4544
4545 res = xsltPreCompEval(ctxt, node, comp);
4546
4547 /*
4548 * Cast the XPath object to string.
4549 */
4550 if (res != NULL) {
4551 value = xmlXPathCastToString(res);
4552 if (value == NULL) {
4553 xsltTransformError(ctxt, NULL, inst,
4554 "Internal error in xsltValueOf(): "
4555 "failed to cast an XPath object to string.\n");
4556 ctxt->state = XSLT_STATE_STOPPED;
4557 goto error;
4558 }
4559 if (value[0] != 0) {
4560 xsltCopyTextString(ctxt, ctxt->insert, value, comp->noescape);
4561 }
4562 } else {
4563 xsltTransformError(ctxt, NULL, inst,
4564 "XPath evaluation returned no result.\n");
4565 ctxt->state = XSLT_STATE_STOPPED;
4566 goto error;
4567 }
4568
4569#ifdef WITH_XSLT_DEBUG_PROCESS
4570 if (value) {
4572 "xsltValueOf: result '%s'\n", value));
4573 }
4574#endif
4575
4576error:
4577 if (value != NULL)
4578 xmlFree(value);
4579 if (res != NULL)
4580 xmlXPathFreeObject(res);
4581}
4582
4592void
4594 xmlNodePtr inst, xsltElemPreCompPtr castedComp)
4595{
4596#ifdef XSLT_REFACTORED
4597 xsltStyleItemNumberPtr comp = (xsltStyleItemNumberPtr) castedComp;
4598#else
4599 xsltStylePreCompPtr comp = (xsltStylePreCompPtr) castedComp;
4600#endif
4601 xmlXPathContextPtr xpctxt;
4602 xmlNsPtr *oldXPNamespaces;
4603 int oldXPNsNr;
4604
4605 if (comp == NULL) {
4606 xsltTransformError(ctxt, NULL, inst,
4607 "xsl:number : compilation failed\n");
4608 return;
4609 }
4610
4611 if ((ctxt == NULL) || (node == NULL) || (inst == NULL) || (comp == NULL))
4612 return;
4613
4614 comp->numdata.doc = inst->doc;
4615 comp->numdata.node = inst;
4616
4617 xpctxt = ctxt->xpathCtxt;
4618 oldXPNsNr = xpctxt->nsNr;
4619 oldXPNamespaces = xpctxt->namespaces;
4620
4621#ifdef XSLT_REFACTORED
4622 if (comp->inScopeNs != NULL) {
4623 xpctxt->namespaces = comp->inScopeNs->list;
4624 xpctxt->nsNr = comp->inScopeNs->xpathNumber;
4625 } else {
4626 xpctxt->namespaces = NULL;
4627 xpctxt->nsNr = 0;
4628 }
4629#else
4630 xpctxt->namespaces = comp->nsList;
4631 xpctxt->nsNr = comp->nsNr;
4632#endif
4633
4634 xsltNumberFormat(ctxt, &comp->numdata, node);
4635
4636 xpctxt->nsNr = oldXPNsNr;
4637 xpctxt->namespaces = oldXPNamespaces;
4638}
4639
4649void
4650xsltApplyImports(xsltTransformContextPtr ctxt, xmlNodePtr contextNode,
4651 xmlNodePtr inst,
4653{
4654 xsltTemplatePtr templ;
4655
4656 if ((ctxt == NULL) || (inst == NULL))
4657 return;
4658
4659 if (comp == NULL) {
4660 xsltTransformError(ctxt, NULL, inst,
4661 "Internal error in xsltApplyImports(): "
4662 "The XSLT 'apply-imports' instruction was not compiled.\n");
4663 return;
4664 }
4665 /*
4666 * NOTE that ctxt->currentTemplateRule and ctxt->templ is not the
4667 * same; the former is the "Current Template Rule" as defined by the
4668 * XSLT spec, the latter is simply the template struct being
4669 * currently processed.
4670 */
4671 if (ctxt->currentTemplateRule == NULL) {
4672 /*
4673 * SPEC XSLT 2.0:
4674 * "[ERR XTDE0560] It is a non-recoverable dynamic error if
4675 * xsl:apply-imports or xsl:next-match is evaluated when the
4676 * current template rule is null."
4677 */
4678 xsltTransformError(ctxt, NULL, inst,
4679 "It is an error to call 'apply-imports' "
4680 "when there's no current template rule.\n");
4681 return;
4682 }
4683 /*
4684 * TODO: Check if this is correct.
4685 */
4686 templ = xsltGetTemplate(ctxt, contextNode,
4687 ctxt->currentTemplateRule->style);
4688
4689 if (templ != NULL) {
4690 xsltTemplatePtr oldCurTemplRule = ctxt->currentTemplateRule;
4691 /*
4692 * Set the current template rule.
4693 */
4694 ctxt->currentTemplateRule = templ;
4695 /*
4696 * URGENT TODO: Need xsl:with-param be handled somehow here?
4697 */
4698 xsltApplyXSLTTemplate(ctxt, contextNode, templ->content,
4699 templ, NULL);
4700
4701 ctxt->currentTemplateRule = oldCurTemplRule;
4702 }
4703 else {
4704 /* Use built-in templates. */
4705 xsltDefaultProcessOneNode(ctxt, contextNode, NULL);
4706 }
4707}
4708
4718void
4720 xmlNodePtr inst, xsltElemPreCompPtr castedComp)
4721{
4722#ifdef XSLT_REFACTORED
4723 xsltStyleItemCallTemplatePtr comp =
4724 (xsltStyleItemCallTemplatePtr) castedComp;
4725#else
4726 xsltStylePreCompPtr comp = (xsltStylePreCompPtr) castedComp;
4727#endif
4728 xsltStackElemPtr withParams = NULL;
4729
4730 if (ctxt->insert == NULL)
4731 return;
4732 if (comp == NULL) {
4733 xsltTransformError(ctxt, NULL, inst,
4734 "The XSLT 'call-template' instruction was not compiled.\n");
4735 return;
4736 }
4737
4738 /*
4739 * The template must have been precomputed
4740 */
4741 if (comp->templ == NULL) {
4742 comp->templ = xsltFindTemplate(ctxt, comp->name, comp->ns);
4743 if (comp->templ == NULL) {
4744 if (comp->ns != NULL) {
4745 xsltTransformError(ctxt, NULL, inst,
4746 "The called template '{%s}%s' was not found.\n",
4747 comp->ns, comp->name);
4748 } else {
4749 xsltTransformError(ctxt, NULL, inst,
4750 "The called template '%s' was not found.\n",
4751 comp->name);
4752 }
4753 return;
4754 }
4755 }
4756
4757#ifdef WITH_XSLT_DEBUG_PROCESS
4758 if ((comp != NULL) && (comp->name != NULL))
4760 "call-template: name %s\n", comp->name));
4761#endif
4762
4763 if (inst->children) {
4764 xmlNodePtr cur;
4766
4767 cur = inst->children;
4768 while (cur != NULL) {
4769#ifdef WITH_DEBUGGER
4770 if (ctxt->debugStatus != XSLT_DEBUG_NONE)
4771 xslHandleDebugger(cur, node, comp->templ, ctxt);
4772#endif
4773 if (ctxt->state == XSLT_STATE_STOPPED) break;
4774 /*
4775 * TODO: The "with-param"s could be part of the "call-template"
4776 * structure. Avoid to "search" for params dynamically
4777 * in the XML tree every time.
4778 */
4779 if (IS_XSLT_ELEM(cur)) {
4780 if (IS_XSLT_NAME(cur, "with-param")) {
4782 if (param != NULL) {
4783 param->next = withParams;
4784 withParams = param;
4785 }
4786 } else {
4788 "xsl:call-template: misplaced xsl:%s\n", cur->name);
4789 }
4790 } else {
4792 "xsl:call-template: misplaced %s element\n", cur->name);
4793 }
4794 cur = cur->next;
4795 }
4796 }
4797 /*
4798 * Create a new frame using the params first
4799 */
4800 xsltApplyXSLTTemplate(ctxt, node, comp->templ->content, comp->templ,
4801 withParams);
4802 if (withParams != NULL)
4803 xsltFreeStackElemList(withParams);
4804
4805#ifdef WITH_XSLT_DEBUG_PROCESS
4806 if ((comp != NULL) && (comp->name != NULL))
4808 "call-template returned: name %s\n", comp->name));
4809#endif
4810}
4811
4821void
4823 xmlNodePtr inst, xsltElemPreCompPtr castedComp)
4824{
4825#ifdef XSLT_REFACTORED
4826 xsltStyleItemApplyTemplatesPtr comp =
4827 (xsltStyleItemApplyTemplatesPtr) castedComp;
4828#else
4829 xsltStylePreCompPtr comp = (xsltStylePreCompPtr) castedComp;
4830#endif
4831 int i;
4832 xmlNodePtr cur, oldContextNode;
4833 xmlNodeSetPtr list = NULL, oldList;
4834 xsltStackElemPtr withParams = NULL;
4835 int oldXPProximityPosition, oldXPContextSize;
4836 const xmlChar *oldMode, *oldModeURI;
4837 xmlDocPtr oldXPDoc;
4838 xsltDocumentPtr oldDocInfo;
4839 xmlXPathContextPtr xpctxt;
4840
4841 if (comp == NULL) {
4842 xsltTransformError(ctxt, NULL, inst,
4843 "xsl:apply-templates : compilation failed\n");
4844 return;
4845 }
4846 if ((ctxt == NULL) || (node == NULL) || (inst == NULL) || (comp == NULL))
4847 return;
4848
4849#ifdef WITH_XSLT_DEBUG_PROCESS
4850 if ((node != NULL) && (node->name != NULL))
4852 "xsltApplyTemplates: node: '%s'\n", node->name));
4853#endif
4854
4855 xpctxt = ctxt->xpathCtxt;
4856 /*
4857 * Save context states.
4858 */
4859 oldContextNode = ctxt->node;
4860 oldMode = ctxt->mode;
4861 oldModeURI = ctxt->modeURI;
4862 oldDocInfo = ctxt->document;
4863 oldList = ctxt->nodeList;
4864
4865 /*
4866 * The xpath context size and proximity position, as
4867 * well as the xpath and context documents, may be changed
4868 * so we save their initial state and will restore on exit
4869 */
4870 oldXPContextSize = xpctxt->contextSize;
4871 oldXPProximityPosition = xpctxt->proximityPosition;
4872 oldXPDoc = xpctxt->doc;
4873
4874 /*
4875 * Set up contexts.
4876 */
4877 ctxt->mode = comp->mode;
4878 ctxt->modeURI = comp->modeURI;
4879
4880 if (comp->select != NULL) {
4881 xmlXPathObjectPtr res = NULL;
4882
4883 if (comp->comp == NULL) {
4884 xsltTransformError(ctxt, NULL, inst,
4885 "xsl:apply-templates : compilation failed\n");
4886 goto error;
4887 }
4888#ifdef WITH_XSLT_DEBUG_PROCESS
4890 "xsltApplyTemplates: select %s\n", comp->select));
4891#endif
4892
4893 res = xsltPreCompEval(ctxt, node, comp);
4894
4895 if (res != NULL) {
4896 if (res->type == XPATH_NODESET) {
4897 list = res->nodesetval; /* consume the node set */
4898 res->nodesetval = NULL;
4899 } else {
4900 xsltTransformError(ctxt, NULL, inst,
4901 "The 'select' expression did not evaluate to a "
4902 "node set.\n");
4903 ctxt->state = XSLT_STATE_STOPPED;
4904 xmlXPathFreeObject(res);
4905 goto error;
4906 }
4907 xmlXPathFreeObject(res);
4908 /*
4909 * Note: An xsl:apply-templates with a 'select' attribute,
4910 * can change the current source doc.
4911 */
4912 } else {
4913 xsltTransformError(ctxt, NULL, inst,
4914 "Failed to evaluate the 'select' expression.\n");
4915 ctxt->state = XSLT_STATE_STOPPED;
4916 goto error;
4917 }
4918 if (list == NULL) {
4919#ifdef WITH_XSLT_DEBUG_PROCESS
4921 "xsltApplyTemplates: select didn't evaluate to a node list\n"));
4922#endif
4923 goto exit;
4924 }
4925 /*
4926 *
4927 * NOTE: Previously a document info (xsltDocument) was
4928 * created and attached to the Result Tree Fragment.
4929 * But such a document info is created on demand in
4930 * xsltKeyFunction() (functions.c), so we need to create
4931 * it here beforehand.
4932 * In order to take care of potential keys we need to
4933 * do some extra work for the case when a Result Tree Fragment
4934 * is converted into a nodeset (e.g. exslt:node-set()) :
4935 * We attach a "pseudo-doc" (xsltDocument) to _private.
4936 * This xsltDocument, together with the keyset, will be freed
4937 * when the Result Tree Fragment is freed.
4938 *
4939 */
4940#if 0
4941 if ((ctxt->nbKeys > 0) &&
4942 (list->nodeNr != 0) &&
4943 (list->nodeTab[0]->doc != NULL) &&
4944 XSLT_IS_RES_TREE_FRAG(list->nodeTab[0]->doc))
4945 {
4946 /*
4947 * NOTE that it's also OK if @effectiveDocInfo will be
4948 * set to NULL.
4949 */
4950 isRTF = 1;
4951 effectiveDocInfo = list->nodeTab[0]->doc->_private;
4952 }
4953#endif
4954 } else {
4955 /*
4956 * Build an XPath node set with the children
4957 */
4958 list = xmlXPathNodeSetCreate(NULL);
4959 if (list == NULL)
4960 goto error;
4961 if (node->type != XML_NAMESPACE_DECL)
4962 cur = node->children;
4963 else
4964 cur = NULL;
4965 while (cur != NULL) {
4967 xmlXPathNodeSetAddUnique(list, cur);
4968 cur = cur->next;
4969 }
4970 }
4971
4972#ifdef WITH_XSLT_DEBUG_PROCESS
4973 if (list != NULL)
4975 "xsltApplyTemplates: list of %d nodes\n", list->nodeNr));
4976#endif
4977
4978 if ((list == NULL) || (list->nodeNr == 0))
4979 goto exit;
4980
4981 /*
4982 * Set the context's node set and size; this is also needed for
4983 * for xsltDoSortFunction().
4984 */
4985 ctxt->nodeList = list;
4986 /*
4987 * Process xsl:with-param and xsl:sort instructions.
4988 * (The code became so verbose just to avoid the
4989 * xmlNodePtr sorts[XSLT_MAX_SORT] if there's no xsl:sort)
4990 * BUG TODO: We are not using namespaced potentially defined on the
4991 * xsl:sort or xsl:with-param elements; XPath expression might fail.
4992 */
4993 if (inst->children) {
4995
4996 cur = inst->children;
4997 while (cur) {
4998
4999#ifdef WITH_DEBUGGER
5000 if (ctxt->debugStatus != XSLT_DEBUG_NONE)
5001 xslHandleDebugger(cur, node, NULL, ctxt);
5002#endif
5003 if (ctxt->state == XSLT_STATE_STOPPED)
5004 break;
5005 if (cur->type == XML_TEXT_NODE) {
5006 cur = cur->next;
5007 continue;
5008 }
5009 if (! IS_XSLT_ELEM(cur))
5010 break;
5011 if (IS_XSLT_NAME(cur, "with-param")) {
5013 if (param != NULL) {
5014 param->next = withParams;
5015 withParams = param;
5016 }
5017 }
5018 if (IS_XSLT_NAME(cur, "sort")) {
5019 xsltTemplatePtr oldCurTempRule =
5020 ctxt->currentTemplateRule;
5021 int nbsorts = 0;
5022 xmlNodePtr sorts[XSLT_MAX_SORT];
5023
5024 sorts[nbsorts++] = cur;
5025 cur = cur->next;
5026
5027 while (cur) {
5028
5029#ifdef WITH_DEBUGGER
5030 if (ctxt->debugStatus != XSLT_DEBUG_NONE)
5031 xslHandleDebugger(cur, node, NULL, ctxt);
5032#endif
5033 if (ctxt->state == XSLT_STATE_STOPPED)
5034 break;
5035
5036 if (cur->type == XML_TEXT_NODE) {
5037 cur = cur->next;
5038 continue;
5039 }
5040
5041 if (! IS_XSLT_ELEM(cur))
5042 break;
5043 if (IS_XSLT_NAME(cur, "with-param")) {
5045 if (param != NULL) {
5046 param->next = withParams;
5047 withParams = param;
5048 }
5049 }
5050 if (IS_XSLT_NAME(cur, "sort")) {
5051 if (nbsorts >= XSLT_MAX_SORT) {
5053 "The number (%d) of xsl:sort instructions exceeds the "
5054 "maximum allowed by this processor's settings.\n",
5055 nbsorts);
5056 ctxt->state = XSLT_STATE_STOPPED;
5057 break;
5058 } else {
5059 sorts[nbsorts++] = cur;
5060 }
5061 }
5062 cur = cur->next;
5063 }
5064 /*
5065 * The "current template rule" is cleared for xsl:sort.
5066 */
5067 ctxt->currentTemplateRule = NULL;
5068 /*
5069 * Sort.
5070 */
5071 xsltDoSortFunction(ctxt, sorts, nbsorts);
5072 ctxt->currentTemplateRule = oldCurTempRule;
5073 break;
5074 }
5075 cur = cur->next;
5076 }
5077 }
5078 xpctxt->contextSize = list->nodeNr;
5079 /*
5080 * Apply templates for all selected source nodes.
5081 */
5082 for (i = 0; i < list->nodeNr; i++) {
5083 cur = list->nodeTab[i];
5084 /*
5085 * The node becomes the "current node".
5086 */
5087 ctxt->node = cur;
5088 /*
5089 * An xsl:apply-templates can change the current context doc.
5090 * OPTIMIZE TODO: Get rid of the need to set the context doc.
5091 */
5092 if ((cur->type != XML_NAMESPACE_DECL) && (cur->doc != NULL))
5093 xpctxt->doc = cur->doc;
5094
5095 xpctxt->proximityPosition = i + 1;
5096 /*
5097 * Find and apply a template for this node.
5098 */
5099 xsltProcessOneNode(ctxt, cur, withParams);
5100 }
5101
5102exit:
5103error:
5104 /*
5105 * Free the parameter list.
5106 */
5107 if (withParams != NULL)
5108 xsltFreeStackElemList(withParams);
5109 if (list != NULL)
5110 xmlXPathFreeNodeSet(list);
5111 /*
5112 * Restore context states.
5113 */
5114 xpctxt->doc = oldXPDoc;
5115 xpctxt->contextSize = oldXPContextSize;
5116 xpctxt->proximityPosition = oldXPProximityPosition;
5117
5118 ctxt->document = oldDocInfo;
5119 ctxt->nodeList = oldList;
5120 ctxt->node = oldContextNode;
5121 ctxt->mode = oldMode;
5122 ctxt->modeURI = oldModeURI;
5123}
5124
5125
5135void
5136xsltChoose(xsltTransformContextPtr ctxt, xmlNodePtr contextNode,
5137 xmlNodePtr inst, xsltElemPreCompPtr comp ATTRIBUTE_UNUSED)
5138{
5139 xmlNodePtr cur;
5140
5141 if ((ctxt == NULL) || (contextNode == NULL) || (inst == NULL))
5142 return;
5143
5144 /*
5145 * TODO: Content model checks should be done only at compilation
5146 * time.
5147 */
5148 cur = inst->children;
5149 if (cur == NULL) {
5150 xsltTransformError(ctxt, NULL, inst,
5151 "xsl:choose: The instruction has no content.\n");
5152 return;
5153 }
5154
5155#ifdef XSLT_REFACTORED
5156 /*
5157 * We don't check the content model during transformation.
5158 */
5159#else
5160 if ((! IS_XSLT_ELEM(cur)) || (! IS_XSLT_NAME(cur, "when"))) {
5161 xsltTransformError(ctxt, NULL, inst,
5162 "xsl:choose: xsl:when expected first\n");
5163 return;
5164 }
5165#endif
5166
5167 {
5168 int testRes = 0, res = 0;
5169
5170#ifdef XSLT_REFACTORED
5171 xsltStyleItemWhenPtr wcomp = NULL;
5172#else
5173 xsltStylePreCompPtr wcomp = NULL;
5174#endif
5175
5176 /*
5177 * Process xsl:when ---------------------------------------------------
5178 */
5179 while (IS_XSLT_ELEM(cur) && IS_XSLT_NAME(cur, "when")) {
5180 wcomp = cur->psvi;
5181
5182 if ((wcomp == NULL) || (wcomp->test == NULL) ||
5183 (wcomp->comp == NULL))
5184 {
5186 "Internal error in xsltChoose(): "
5187 "The XSLT 'when' instruction was not compiled.\n");
5188 goto error;
5189 }
5190
5191
5192#ifdef WITH_DEBUGGER
5194 /*
5195 * TODO: Isn't comp->templ always NULL for xsl:choose?
5196 */
5197 xslHandleDebugger(cur, contextNode, NULL, ctxt);
5198 }
5199#endif
5200#ifdef WITH_XSLT_DEBUG_PROCESS
5202 "xsltChoose: test %s\n", wcomp->test));
5203#endif
5204
5205#ifdef XSLT_FAST_IF
5206 res = xsltPreCompEvalToBoolean(ctxt, contextNode, wcomp);
5207
5208 if (res == -1) {
5209 ctxt->state = XSLT_STATE_STOPPED;
5210 goto error;
5211 }
5212 testRes = (res == 1) ? 1 : 0;
5213
5214#else /* XSLT_FAST_IF */
5215
5216 res = xsltPreCompEval(ctxt, cotextNode, wcomp);
5217
5218 if (res != NULL) {
5219 if (res->type != XPATH_BOOLEAN)
5220 res = xmlXPathConvertBoolean(res);
5221 if (res->type == XPATH_BOOLEAN)
5222 testRes = res->boolval;
5223 else {
5224#ifdef WITH_XSLT_DEBUG_PROCESS
5226 "xsltChoose: test didn't evaluate to a boolean\n"));
5227#endif
5228 goto error;
5229 }
5230 xmlXPathFreeObject(res);
5231 res = NULL;
5232 } else {
5233 ctxt->state = XSLT_STATE_STOPPED;
5234 goto error;
5235 }
5236
5237#endif /* else of XSLT_FAST_IF */
5238
5239#ifdef WITH_XSLT_DEBUG_PROCESS
5241 "xsltChoose: test evaluate to %d\n", testRes));
5242#endif
5243 if (testRes)
5244 goto test_is_true;
5245
5246 cur = cur->next;
5247 }
5248
5249 /*
5250 * Process xsl:otherwise ----------------------------------------------
5251 */
5252 if (IS_XSLT_ELEM(cur) && IS_XSLT_NAME(cur, "otherwise")) {
5253
5254#ifdef WITH_DEBUGGER
5256 xslHandleDebugger(cur, contextNode, NULL, ctxt);
5257#endif
5258
5259#ifdef WITH_XSLT_DEBUG_PROCESS
5261 "evaluating xsl:otherwise\n"));
5262#endif
5263 goto test_is_true;
5264 }
5265 goto exit;
5266
5267test_is_true:
5268
5269 goto process_sequence;
5270 }
5271
5272process_sequence:
5273
5274 /*
5275 * Instantiate the sequence constructor.
5276 */
5277 xsltApplySequenceConstructor(ctxt, ctxt->node, cur->children,
5278 NULL);
5279
5280exit:
5281error:
5282 return;
5283}
5284
5294void
5295xsltIf(xsltTransformContextPtr ctxt, xmlNodePtr contextNode,
5296 xmlNodePtr inst, xsltElemPreCompPtr castedComp)
5297{
5298 int res = 0;
5299
5300#ifdef XSLT_REFACTORED
5301 xsltStyleItemIfPtr comp = (xsltStyleItemIfPtr) castedComp;
5302#else
5303 xsltStylePreCompPtr comp = (xsltStylePreCompPtr) castedComp;
5304#endif
5305
5306 if ((ctxt == NULL) || (contextNode == NULL) || (inst == NULL))
5307 return;
5308 if ((comp == NULL) || (comp->test == NULL) || (comp->comp == NULL)) {
5309 xsltTransformError(ctxt, NULL, inst,
5310 "Internal error in xsltIf(): "
5311 "The XSLT 'if' instruction was not compiled.\n");
5312 return;
5313 }
5314
5315#ifdef WITH_XSLT_DEBUG_PROCESS
5317 "xsltIf: test %s\n", comp->test));
5318#endif
5319
5320#ifdef XSLT_FAST_IF
5321 {
5322 xmlDocPtr oldLocalFragmentTop = ctxt->localRVT;
5323
5324 res = xsltPreCompEvalToBoolean(ctxt, contextNode, comp);
5325
5326 /*
5327 * Cleanup fragments created during evaluation of the
5328 * "select" expression.
5329 */
5330 if (oldLocalFragmentTop != ctxt->localRVT)
5331 xsltReleaseLocalRVTs(ctxt, oldLocalFragmentTop);
5332 }
5333
5334#ifdef WITH_XSLT_DEBUG_PROCESS
5336 "xsltIf: test evaluate to %d\n", res));
5337#endif
5338
5339 if (res == -1) {
5340 ctxt->state = XSLT_STATE_STOPPED;
5341 goto error;
5342 }
5343 if (res == 1) {
5344 /*
5345 * Instantiate the sequence constructor of xsl:if.
5346 */
5348 contextNode, inst->children, NULL);
5349 }
5350
5351#else /* XSLT_FAST_IF */
5352 {
5353 /*
5354 * OLD CODE:
5355 */
5356 xmlXPathObjectPtr xpobj = xsltPreCompEval(ctxt, contextNode, comp);
5357 if (xpobj != NULL) {
5358 if (xpobj->type != XPATH_BOOLEAN)
5359 xpobj = xmlXPathConvertBoolean(xpobj);
5360 if (xpobj->type == XPATH_BOOLEAN) {
5361 res = xpobj->boolval;
5362
5363#ifdef WITH_XSLT_DEBUG_PROCESS
5365 "xsltIf: test evaluate to %d\n", res));
5366#endif
5367 if (res) {
5369 contextNode, inst->children, NULL);
5370 }
5371 } else {
5372
5373#ifdef WITH_XSLT_DEBUG_PROCESS
5376 "xsltIf: test didn't evaluate to a boolean\n"));
5377#endif
5378 ctxt->state = XSLT_STATE_STOPPED;
5379 }
5380 xmlXPathFreeObject(xpobj);
5381 } else {
5382 ctxt->state = XSLT_STATE_STOPPED;
5383 }
5384 }
5385#endif /* else of XSLT_FAST_IF */
5386
5387error:
5388 return;
5389}
5390
5400void
5401xsltForEach(xsltTransformContextPtr ctxt, xmlNodePtr contextNode,
5402 xmlNodePtr inst, xsltElemPreCompPtr castedComp)
5403{
5404#ifdef XSLT_REFACTORED
5405 xsltStyleItemForEachPtr comp = (xsltStyleItemForEachPtr) castedComp;
5406#else
5407 xsltStylePreCompPtr comp = (xsltStylePreCompPtr) castedComp;
5408#endif
5409 int i;
5410 xmlXPathObjectPtr res = NULL;
5411 xmlNodePtr cur, curInst;
5412 xmlNodeSetPtr list = NULL;
5413 xmlNodeSetPtr oldList;
5414 int oldXPProximityPosition, oldXPContextSize;
5415 xmlNodePtr oldContextNode;
5416 xsltTemplatePtr oldCurTemplRule;
5417 xmlDocPtr oldXPDoc;
5418 xsltDocumentPtr oldDocInfo;
5419 xmlXPathContextPtr xpctxt;
5420
5421 if ((ctxt == NULL) || (contextNode == NULL) || (inst == NULL)) {
5423 "xsltForEach(): Bad arguments.\n");
5424 return;
5425 }
5426
5427 if (comp == NULL) {
5428 xsltTransformError(ctxt, NULL, inst,
5429 "Internal error in xsltForEach(): "
5430 "The XSLT 'for-each' instruction was not compiled.\n");
5431 return;
5432 }
5433 if ((comp->select == NULL) || (comp->comp == NULL)) {
5434 xsltTransformError(ctxt, NULL, inst,
5435 "Internal error in xsltForEach(): "
5436 "The selecting expression of the XSLT 'for-each' "
5437 "instruction was not compiled correctly.\n");
5438 return;
5439 }
5440 xpctxt = ctxt->xpathCtxt;
5441
5442#ifdef WITH_XSLT_DEBUG_PROCESS
5444 "xsltForEach: select %s\n", comp->select));
5445#endif
5446
5447 /*
5448 * Save context states.
5449 */
5450 oldDocInfo = ctxt->document;
5451 oldList = ctxt->nodeList;
5452 oldContextNode = ctxt->node;
5453 /*
5454 * The "current template rule" is cleared for the instantiation of
5455 * xsl:for-each.
5456 */
5457 oldCurTemplRule = ctxt->currentTemplateRule;
5458 ctxt->currentTemplateRule = NULL;
5459
5460 oldXPDoc = xpctxt->doc;
5461 oldXPProximityPosition = xpctxt->proximityPosition;
5462 oldXPContextSize = xpctxt->contextSize;
5463
5464 /*
5465 * Evaluate the 'select' expression.
5466 */
5467 res = xsltPreCompEval(ctxt, contextNode, comp);
5468
5469 if (res != NULL) {
5470 if (res->type == XPATH_NODESET)
5471 list = res->nodesetval;
5472 else {
5473 xsltTransformError(ctxt, NULL, inst,
5474 "The 'select' expression does not evaluate to a node set.\n");
5475
5476#ifdef WITH_XSLT_DEBUG_PROCESS
5478 "xsltForEach: select didn't evaluate to a node list\n"));
5479#endif
5480 goto error;
5481 }
5482 } else {
5483 xsltTransformError(ctxt, NULL, inst,
5484 "Failed to evaluate the 'select' expression.\n");
5485 ctxt->state = XSLT_STATE_STOPPED;
5486 goto error;
5487 }
5488
5489 if ((list == NULL) || (list->nodeNr <= 0))
5490 goto exit;
5491
5492#ifdef WITH_XSLT_DEBUG_PROCESS
5494 "xsltForEach: select evaluates to %d nodes\n", list->nodeNr));
5495#endif
5496
5497 /*
5498 * Set the list; this has to be done already here for xsltDoSortFunction().
5499 */
5500 ctxt->nodeList = list;
5501 /*
5502 * Handle xsl:sort instructions and skip them for further processing.
5503 * BUG TODO: We are not using namespaced potentially defined on the
5504 * xsl:sort element; XPath expression might fail.
5505 */
5506 curInst = inst->children;
5507 if (IS_XSLT_ELEM(curInst) && IS_XSLT_NAME(curInst, "sort")) {
5508 int nbsorts = 0;
5509 xmlNodePtr sorts[XSLT_MAX_SORT];
5510
5511 sorts[nbsorts++] = curInst;
5512
5513#ifdef WITH_DEBUGGER
5515 xslHandleDebugger(curInst, contextNode, NULL, ctxt);
5516#endif
5517
5518 curInst = curInst->next;
5519 while (IS_XSLT_ELEM(curInst) && IS_XSLT_NAME(curInst, "sort")) {
5520 if (nbsorts >= XSLT_MAX_SORT) {
5521 xsltTransformError(ctxt, NULL, curInst,
5522 "The number of xsl:sort instructions exceeds the "
5523 "maximum (%d) allowed by this processor.\n",
5525 goto error;
5526 } else {
5527 sorts[nbsorts++] = curInst;
5528 }
5529
5530#ifdef WITH_DEBUGGER
5532 xslHandleDebugger(curInst, contextNode, NULL, ctxt);
5533#endif
5534 curInst = curInst->next;
5535 }
5536 xsltDoSortFunction(ctxt, sorts, nbsorts);
5537 }
5538 xpctxt->contextSize = list->nodeNr;
5539 /*
5540 * Instantiate the sequence constructor for each selected node.
5541 */
5542 for (i = 0; i < list->nodeNr; i++) {
5543 cur = list->nodeTab[i];
5544 /*
5545 * The selected node becomes the "current node".
5546 */
5547 ctxt->node = cur;
5548 /*
5549 * An xsl:for-each can change the current context doc.
5550 * OPTIMIZE TODO: Get rid of the need to set the context doc.
5551 */
5552 if ((cur->type != XML_NAMESPACE_DECL) && (cur->doc != NULL))
5553 xpctxt->doc = cur->doc;
5554
5555 xpctxt->proximityPosition = i + 1;
5556
5557 xsltApplySequenceConstructor(ctxt, cur, curInst, NULL);
5558 }
5559
5560exit:
5561error:
5562 if (res != NULL)
5563 xmlXPathFreeObject(res);
5564 /*
5565 * Restore old states.
5566 */
5567 ctxt->document = oldDocInfo;
5568 ctxt->nodeList = oldList;
5569 ctxt->node = oldContextNode;
5570 ctxt->currentTemplateRule = oldCurTemplRule;
5571
5572 xpctxt->doc = oldXPDoc;
5573 xpctxt->contextSize = oldXPContextSize;
5574 xpctxt->proximityPosition = oldXPProximityPosition;
5575}
5576
5577/************************************************************************
5578 * *
5579 * Generic interface *
5580 * *
5581 ************************************************************************/
5582
5583#ifdef XSLT_GENERATE_HTML_DOCTYPE
5584typedef struct xsltHTMLVersion {
5585 const char *version;
5586 const char *public;
5587 const char *system;
5589
5591 { "5", NULL, "about:legacy-compat" },
5592 { "4.01frame", "-//W3C//DTD HTML 4.01 Frameset//EN",
5593 "http://www.w3.org/TR/1999/REC-html401-19991224/frameset.dtd"},
5594 { "4.01strict", "-//W3C//DTD HTML 4.01//EN",
5595 "http://www.w3.org/TR/1999/REC-html401-19991224/strict.dtd"},
5596 { "4.01trans", "-//W3C//DTD HTML 4.01 Transitional//EN",
5597 "http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd"},
5598 { "4.01", "-//W3C//DTD HTML 4.01 Transitional//EN",
5599 "http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd"},
5600 { "4.0strict", "-//W3C//DTD HTML 4.01//EN",
5601 "http://www.w3.org/TR/html4/strict.dtd"},
5602 { "4.0trans", "-//W3C//DTD HTML 4.01 Transitional//EN",
5603 "http://www.w3.org/TR/html4/loose.dtd"},
5604 { "4.0frame", "-//W3C//DTD HTML 4.01 Frameset//EN",
5605 "http://www.w3.org/TR/html4/frameset.dtd"},
5606 { "4.0", "-//W3C//DTD HTML 4.01 Transitional//EN",
5607 "http://www.w3.org/TR/html4/loose.dtd"},
5608 { "3.2", "-//W3C//DTD HTML 3.2//EN", NULL }
5609};
5610
5620static int
5621xsltGetHTMLIDs(const xmlChar *version, const xmlChar **publicID,
5622 const xmlChar **systemID) {
5623 unsigned int i;
5624 if (version == NULL)
5625 return(-1);
5626 for (i = 0;i < (sizeof(xsltHTMLVersions)/sizeof(xsltHTMLVersions[1]));
5627 i++) {
5629 (const xmlChar *) xsltHTMLVersions[i].version)) {
5630 if (publicID != NULL)
5631 *publicID = (const xmlChar *) xsltHTMLVersions[i].public;
5632 if (systemID != NULL)
5633 *systemID = (const xmlChar *) xsltHTMLVersions[i].system;
5634 return(0);
5635 }
5636 }
5637 return(-1);
5638}
5639#endif
5640
5648void
5650 xmlNodePtr current;
5651#ifdef WITH_XSLT_DEBUG_PROCESS
5652 int nb = 0;
5653#endif
5654
5655
5656 current = node;
5657 while (current != NULL) {
5658 /*
5659 * Cleanup children empty nodes if asked for
5660 */
5661 if ((IS_XSLT_REAL_NODE(current)) &&
5662 (current->children != NULL) &&
5664 xmlNodePtr delete = NULL, cur = current->children;
5665
5666 while (cur != NULL) {
5667 if (IS_BLANK_NODE(cur))
5668 delete = cur;
5669
5670 cur = cur->next;
5671 if (delete != NULL) {
5672 xmlUnlinkNode(delete);
5673 xmlFreeNode(delete);
5674 delete = NULL;
5675#ifdef WITH_XSLT_DEBUG_PROCESS
5676 nb++;
5677#endif
5678 }
5679 }
5680 }
5681
5682 /*
5683 * Skip to next node in document order.
5684 */
5685 if (node->type == XML_ENTITY_REF_NODE) {
5686 /* process deep in entities */
5687 xsltApplyStripSpaces(ctxt, node->children);
5688 }
5689 if ((current->children != NULL) &&
5690 (current->type != XML_ENTITY_REF_NODE)) {
5691 current = current->children;
5692 } else if (current->next != NULL) {
5693 current = current->next;
5694 } else {
5695 do {
5696 current = current->parent;
5697 if (current == NULL)
5698 break;
5699 if (current == node)
5700 goto done;
5701 if (current->next != NULL) {
5702 current = current->next;
5703 break;
5704 }
5705 } while (current != NULL);
5706 }
5707 }
5708
5709done:
5710#ifdef WITH_XSLT_DEBUG_PROCESS
5712 "xsltApplyStripSpaces: removed %d ignorable blank node\n", nb));
5713#endif
5714 return;
5715}
5716
5717static int
5719{
5721 xsltKeyDefPtr keyd;
5722
5723 if (ctxt == NULL)
5724 return(-1);
5725
5726 /*
5727 * Do we have those nastly templates with a key() in the match pattern?
5728 */
5729 ctxt->hasTemplKeyPatterns = 0;
5730 style = ctxt->style;
5731 while (style != NULL) {
5732 if (style->keyMatch != NULL) {
5733 ctxt->hasTemplKeyPatterns = 1;
5734 break;
5735 }
5737 }
5738 /*
5739 * Count number of key declarations.
5740 */
5741 ctxt->nbKeys = 0;
5742 style = ctxt->style;
5743 while (style != NULL) {
5744 keyd = style->keys;
5745 while (keyd) {
5746 ctxt->nbKeys++;
5747 keyd = keyd->next;
5748 }
5750 }
5751 return(ctxt->nbKeys);
5752}
5753
5760static void
5761xsltCleanupSourceDoc(xmlDocPtr doc) {
5762 xmlNodePtr cur = (xmlNodePtr) doc;
5763 void **psviPtr;
5764
5765 while (1) {
5766 xsltClearSourceNodeFlags(cur, XSLT_SOURCE_NODE_MASK);
5767 psviPtr = xsltGetPSVIPtr(cur);
5768 if (psviPtr)
5769 *psviPtr = NULL;
5770
5771 if (cur->type == XML_ELEMENT_NODE) {
5772 xmlAttrPtr prop = cur->properties;
5773
5774 while (prop) {
5775 prop->atype &= ~(XSLT_SOURCE_NODE_MASK << 27);
5776 prop->psvi = NULL;
5777 prop = prop->next;
5778 }
5779 }
5780
5781 if (cur->children != NULL && cur->type != XML_ENTITY_REF_NODE) {
5782 cur = cur->children;
5783 } else {
5784 if (cur == (xmlNodePtr) doc)
5785 return;
5786 while (cur->next == NULL) {
5787 cur = cur->parent;
5788 if (cur == (xmlNodePtr) doc)
5789 return;
5790 }
5791
5792 cur = cur->next;
5793 }
5794 }
5795}
5796
5811static xmlDocPtr
5813 const char **params, const char *output,
5815{
5816 xmlDocPtr res = NULL;
5818 xmlNodePtr root, node;
5819 const xmlChar *method;
5820 const xmlChar *doctypePublic;
5821 const xmlChar *doctypeSystem;
5822 const xmlChar *version;
5823 const xmlChar *encoding;
5824 xsltStackElemPtr variables;
5825 xsltStackElemPtr vptr;
5826
5828
5829 if ((style == NULL) || (doc == NULL))
5830 return (NULL);
5831
5832 if (style->internalized == 0) {
5833#ifdef WITH_XSLT_DEBUG
5835 "Stylesheet was not fully internalized !\n");
5836#endif
5837 }
5838 if (doc->intSubset != NULL) {
5839 /*
5840 * Avoid hitting the DTD when scanning nodes
5841 * but keep it linked as doc->intSubset
5842 */
5843 xmlNodePtr cur = (xmlNodePtr) doc->intSubset;
5844 if (cur->next != NULL)
5845 cur->next->prev = cur->prev;
5846 if (cur->prev != NULL)
5847 cur->prev->next = cur->next;
5848 if (doc->children == cur)
5849 doc->children = cur->next;
5850 if (doc->last == cur)
5851 doc->last = cur->prev;
5852 cur->prev = cur->next = NULL;
5853 }
5854
5855 /*
5856 * Check for XPath document order availability
5857 */
5858 root = xmlDocGetRootElement(doc);
5859 if (root != NULL) {
5860 if (((ptrdiff_t) root->content >= 0) &&
5862 xmlXPathOrderDocElems(doc);
5863 }
5864
5865 if (userCtxt != NULL)
5866 ctxt = userCtxt;
5867 else
5868 ctxt = xsltNewTransformContext(style, doc);
5869
5870 if (ctxt == NULL)
5871 return (NULL);
5872
5873 ctxt->initialContextDoc = doc;
5874 ctxt->initialContextNode = (xmlNodePtr) doc;
5875
5876 if (profile != NULL) {
5877#ifdef WITH_PROFILER
5878 ctxt->profile = 1;
5879#else
5880 xsltTransformError(ctxt, NULL, (xmlNodePtr) doc,
5881 "xsltApplyStylesheetInternal: "
5882 "libxslt compiled without profiler\n");
5883 goto error;
5884#endif
5885 }
5886
5887 if (output != NULL)
5888 ctxt->outputFile = output;
5889 else
5890 ctxt->outputFile = NULL;
5891
5892 /*
5893 * internalize the modes if needed
5894 */
5895 if (ctxt->dict != NULL) {
5896 if (ctxt->mode != NULL)
5897 ctxt->mode = xmlDictLookup(ctxt->dict, ctxt->mode, -1);
5898 if (ctxt->modeURI != NULL)
5899 ctxt->modeURI = xmlDictLookup(ctxt->dict, ctxt->modeURI, -1);
5900 }
5901
5903 XSLT_GET_IMPORT_PTR(doctypePublic, style, doctypePublic)
5904 XSLT_GET_IMPORT_PTR(doctypeSystem, style, doctypeSystem)
5906 XSLT_GET_IMPORT_PTR(encoding, style, encoding)
5907
5908 if ((method != NULL) &&
5909 (!xmlStrEqual(method, (const xmlChar *) "xml")))
5910 {
5911 if (xmlStrEqual(method, (const xmlChar *) "html")) {
5912 ctxt->type = XSLT_OUTPUT_HTML;
5913 if (((doctypePublic != NULL) || (doctypeSystem != NULL))) {
5914 res = htmlNewDoc(doctypeSystem, doctypePublic);
5915 } else {
5916 if (version == NULL) {
5917 xmlDtdPtr dtd;
5918
5919 res = htmlNewDoc(NULL, NULL);
5920 /*
5921 * Make sure no DTD node is generated in this case
5922 */
5923 if (res != NULL) {
5924 dtd = xmlGetIntSubset(res);
5925 if (dtd != NULL) {
5926 xmlUnlinkNode((xmlNodePtr) dtd);
5927 xmlFreeDtd(dtd);
5928 }
5929 res->intSubset = NULL;
5930 res->extSubset = NULL;
5931 }
5932 } else {
5933
5934#ifdef XSLT_GENERATE_HTML_DOCTYPE
5935 xsltGetHTMLIDs(version, &doctypePublic, &doctypeSystem);
5936#endif
5937 res = htmlNewDoc(doctypeSystem, doctypePublic);
5938 }
5939 }
5940 if (res == NULL)
5941 goto error;
5942 res->dict = ctxt->dict;
5943 xmlDictReference(res->dict);
5944
5945#ifdef WITH_XSLT_DEBUG
5947 "reusing transformation dict for output\n");
5948#endif
5949 } else if (xmlStrEqual(method, (const xmlChar *) "xhtml")) {
5950 xsltTransformError(ctxt, NULL, (xmlNodePtr) doc,
5951 "xsltApplyStylesheetInternal: unsupported method xhtml, using html\n");
5952 ctxt->type = XSLT_OUTPUT_HTML;
5953 res = htmlNewDoc(doctypeSystem, doctypePublic);
5954 if (res == NULL)
5955 goto error;
5956 res->dict = ctxt->dict;
5957 xmlDictReference(res->dict);
5958
5959#ifdef WITH_XSLT_DEBUG
5961 "reusing transformation dict for output\n");
5962#endif
5963 } else if (xmlStrEqual(method, (const xmlChar *) "text")) {
5964 ctxt->type = XSLT_OUTPUT_TEXT;
5965 res = xmlNewDoc(style->version);
5966 if (res == NULL)
5967 goto error;
5968 res->dict = ctxt->dict;
5969 xmlDictReference(res->dict);
5970
5971#ifdef WITH_XSLT_DEBUG
5973 "reusing transformation dict for output\n");
5974#endif
5975 } else {
5976 xsltTransformError(ctxt, NULL, (xmlNodePtr) doc,
5977 "xsltApplyStylesheetInternal: unsupported method (%s)\n",
5978 method);
5979 goto error;
5980 }
5981 } else {
5982 ctxt->type = XSLT_OUTPUT_XML;
5983 res = xmlNewDoc(style->version);
5984 if (res == NULL)
5985 goto error;
5986 res->dict = ctxt->dict;
5987 xmlDictReference(ctxt->dict);
5988#ifdef WITH_XSLT_DEBUG
5990 "reusing transformation dict for output\n");
5991#endif
5992 }
5993 res->charset = XML_CHAR_ENCODING_UTF8;
5994 if (encoding != NULL)
5995 res->encoding = xmlStrdup(encoding);
5996 variables = style->variables;
5997
5998 ctxt->node = (xmlNodePtr) doc;
5999 ctxt->output = res;
6000
6001 ctxt->xpathCtxt->contextSize = 1;
6002 ctxt->xpathCtxt->proximityPosition = 1;
6003 ctxt->xpathCtxt->node = NULL; /* TODO: Set the context node here? */
6004
6005 /*
6006 * Start the evaluation, evaluate the params, the stylesheets globals
6007 * and start by processing the top node.
6008 */
6009 if (xsltNeedElemSpaceHandling(ctxt))
6010 xsltApplyStripSpaces(ctxt, xmlDocGetRootElement(doc));
6011 /*
6012 * Evaluate global params and user-provided params.
6013 */
6014 if (ctxt->globalVars == NULL)
6015 ctxt->globalVars = xmlHashCreate(20);
6016 if (params != NULL) {
6018 }
6019
6020 /* need to be called before evaluating global variables */
6021 xsltCountKeys(ctxt);
6022
6024
6025 /* Clean up any unused RVTs. */
6027
6028 ctxt->insert = (xmlNodePtr) res;
6029 ctxt->varsBase = ctxt->varsNr - 1;
6030
6031 /*
6032 * Start processing the source tree -----------------------------------
6033 */
6034 xsltProcessOneNode(ctxt, ctxt->node, NULL);
6035 /*
6036 * Remove all remaining vars from the stack.
6037 */
6038 xsltLocalVariablePop(ctxt, 0, -2);
6040
6041 xsltCleanupTemplates(style); /* TODO: <- style should be read only */
6042
6043 /*
6044 * Now cleanup our variables so stylesheet can be re-used
6045 *
6046 * TODO: this is not needed anymore global variables are copied
6047 * and not evaluated directly anymore, keep this as a check
6048 */
6049 if (style->variables != variables) {
6050 vptr = style->variables;
6051 while (vptr->next != variables)
6052 vptr = vptr->next;
6053 vptr->next = NULL;
6054 xsltFreeStackElemList(style->variables);
6055 style->variables = variables;
6056 }
6057 vptr = style->variables;
6058 while (vptr != NULL) {
6059 if (vptr->computed) {
6060 if (vptr->value != NULL) {
6061 xmlXPathFreeObject(vptr->value);
6062 vptr->value = NULL;
6063 vptr->computed = 0;
6064 }
6065 }
6066 vptr = vptr->next;
6067 }
6068#if 0
6069 /*
6070 * code disabled by wmb; awaiting kb's review
6071 * problem is that global variable(s) may contain xpath objects
6072 * from doc associated with RVT, so can't be freed at this point.
6073 * xsltFreeTransformContext includes a call to xsltFreeRVTs, so
6074 * I assume this shouldn't be required at this point.
6075 */
6076 /*
6077 * Free all remaining tree fragments.
6078 */
6079 xsltFreeRVTs(ctxt);
6080#endif
6081 /*
6082 * Do some post processing work depending on the generated output
6083 */
6084 root = xmlDocGetRootElement(res);
6085 if (root != NULL) {
6086 const xmlChar *doctype = NULL;
6087
6088 if ((root->ns != NULL) && (root->ns->prefix != NULL))
6089 doctype = xmlDictQLookup(ctxt->dict, root->ns->prefix, root->name);
6090 if (doctype == NULL)
6091 doctype = root->name;
6092
6093 /*
6094 * Apply the default selection of the method
6095 */
6096 if ((method == NULL) &&
6097 (root->ns == NULL) &&
6098 (!xmlStrcasecmp(root->name, (const xmlChar *) "html"))) {
6099 xmlNodePtr tmp;
6100
6101 tmp = res->children;
6102 while ((tmp != NULL) && (tmp != root)) {
6103 if (tmp->type == XML_ELEMENT_NODE)
6104 break;
6105 if ((tmp->type == XML_TEXT_NODE) && (!xmlIsBlankNode(tmp)))
6106 break;
6107 tmp = tmp->next;
6108 }
6109 if (tmp == root) {
6110 ctxt->type = XSLT_OUTPUT_HTML;
6111 /*
6112 * REVISIT TODO: XML_HTML_DOCUMENT_NODE is set after the
6113 * transformation on the doc, but functions like
6114 */
6115 res->type = XML_HTML_DOCUMENT_NODE;
6116 if (((doctypePublic != NULL) || (doctypeSystem != NULL))) {
6117 res->intSubset = xmlCreateIntSubset(res, doctype,
6118 doctypePublic,
6119 doctypeSystem);
6120#ifdef XSLT_GENERATE_HTML_DOCTYPE
6121 } else if (version != NULL) {
6122 xsltGetHTMLIDs(version, &doctypePublic,
6123 &doctypeSystem);
6124 if (((doctypePublic != NULL) || (doctypeSystem != NULL)))
6125 res->intSubset =
6126 xmlCreateIntSubset(res, doctype,
6127 doctypePublic,
6128 doctypeSystem);
6129#endif
6130 }
6131 }
6132
6133 }
6134 if (ctxt->type == XSLT_OUTPUT_XML) {
6135 XSLT_GET_IMPORT_PTR(doctypePublic, style, doctypePublic)
6136 XSLT_GET_IMPORT_PTR(doctypeSystem, style, doctypeSystem)
6137 if (((doctypePublic != NULL) || (doctypeSystem != NULL))) {
6138 xmlNodePtr last;
6139 /* Need a small "hack" here to assure DTD comes before
6140 possible comment nodes */
6141 node = res->children;
6142 last = res->last;
6143 res->children = NULL;
6144 res->last = NULL;
6145 res->intSubset = xmlCreateIntSubset(res, doctype,
6146 doctypePublic,
6147 doctypeSystem);
6148 if (res->children != NULL) {
6149 res->children->next = node;
6150 node->prev = res->children;
6151 res->last = last;
6152 } else {
6153 res->children = node;
6154 res->last = last;
6155 }
6156 }
6157 }
6158 }
6159 xmlXPathFreeNodeSet(ctxt->nodeList);
6160
6161#ifdef WITH_PROFILER
6162 if (profile != NULL) {
6163 xsltSaveProfiling(ctxt, profile);
6164 }
6165#endif
6166
6167 /*
6168 * Be pedantic.
6169 */
6170 if ((ctxt != NULL) && (ctxt->state != XSLT_STATE_OK)) {
6171 xmlFreeDoc(res);
6172 res = NULL;
6173 }
6174 if ((res != NULL) && (ctxt != NULL) && (output != NULL)) {
6175 int ret;
6176
6177 ret = xsltCheckWrite(ctxt->sec, ctxt, (const xmlChar *) output);
6178 if (ret == 0) {
6180 "xsltApplyStylesheet: forbidden to save to %s\n",
6181 output);
6182 } else if (ret < 0) {
6184 "xsltApplyStylesheet: saving to %s may not be possible\n",
6185 output);
6186 }
6187 }
6188
6189#ifdef XSLT_DEBUG_PROFILE_CACHE
6190 printf("# Cache:\n");
6191 printf("# Reused tree fragments: %d\n", ctxt->cache->dbgReusedRVTs);
6192 printf("# Reused variables : %d\n", ctxt->cache->dbgReusedVars);
6193#endif
6194
6195 if (ctxt->sourceDocDirty)
6197
6198 if ((ctxt != NULL) && (userCtxt == NULL))
6200
6201 return (res);
6202
6203error:
6204 if (res != NULL)
6205 xmlFreeDoc(res);
6206
6207#ifdef XSLT_DEBUG_PROFILE_CACHE
6208 printf("# Cache:\n");
6209 printf("# Reused tree fragments: %d\n", ctxt->cache->dbgReusedRVTs);
6210 printf("# Reused variables : %d\n", ctxt->cache->dbgReusedVars);
6211#endif
6212
6213 if ((ctxt != NULL) && (userCtxt == NULL))
6215 return (NULL);
6216}
6217
6229xmlDocPtr
6231 const char **params)
6232{
6234}
6235
6248xmlDocPtr
6250 const char **params, FILE * output)
6251{
6252 xmlDocPtr res;
6253
6255 return (res);
6256}
6257
6272xmlDocPtr
6274 const char **params, const char *output,
6276{
6277 xmlDocPtr res;
6278
6280 profile, userCtxt);
6281 return (res);
6282}
6283
6310int
6312 const char **params, const char *output,
6313 xmlSAXHandlerPtr SAX, xmlOutputBufferPtr IObuf,
6315{
6316 xmlDocPtr tmp;
6317 int ret;
6318
6319 if ((output == NULL) && (SAX == NULL) && (IObuf == NULL))
6320 return (-1);
6321 if ((SAX != NULL) && (IObuf != NULL))
6322 return (-1);
6323
6324 /* unsupported yet */
6325 if (SAX != NULL) {
6326 XSLT_TODO /* xsltRunStylesheet xmlSAXHandlerPtr SAX */
6327 return (-1);
6328 }
6329
6330 tmp = xsltApplyStylesheetInternal(style, doc, params, output, profile,
6331 userCtxt);
6332 if (tmp == NULL) {
6333 xsltTransformError(NULL, NULL, (xmlNodePtr) doc,
6334 "xsltRunStylesheet : run failed\n");
6335 return (-1);
6336 }
6337 if (IObuf != NULL) {
6338 /* TODO: incomplete, IObuf output not progressive */
6339 ret = xsltSaveResultTo(IObuf, tmp, style);
6340 } else {
6341 ret = xsltSaveResultToFilename(output, tmp, style, 0);
6342 }
6343 xmlFreeDoc(tmp);
6344 return (ret);
6345}
6346
6371int
6373 const char **params, const char *output,
6374 xmlSAXHandlerPtr SAX, xmlOutputBufferPtr IObuf)
6375{
6376 return(xsltRunStylesheetUser(style, doc, params, output, SAX, IObuf,
6377 NULL, NULL));
6378}
6379
6380static void
6382 xmlNodePtr inst, xsltElemPreCompPtr comp ATTRIBUTE_UNUSED) {
6383 xsltMessage(ctxt, node, inst);
6384}
6385
6392void
6394{
6395 xsltRegisterExtElement(ctxt, (const xmlChar *) "apply-templates",
6398 xsltRegisterExtElement(ctxt, (const xmlChar *) "apply-imports",
6401 xsltRegisterExtElement(ctxt, (const xmlChar *) "call-template",
6404 xsltRegisterExtElement(ctxt, (const xmlChar *) "element",
6406 xsltElement);
6407 xsltRegisterExtElement(ctxt, (const xmlChar *) "attribute",
6410 xsltRegisterExtElement(ctxt, (const xmlChar *) "text",
6412 xsltText);
6413 xsltRegisterExtElement(ctxt, (const xmlChar *) "processing-instruction",
6416 xsltRegisterExtElement(ctxt, (const xmlChar *) "comment",
6418 xsltComment);
6419 xsltRegisterExtElement(ctxt, (const xmlChar *) "copy",
6421 xsltCopy);
6422 xsltRegisterExtElement(ctxt, (const xmlChar *) "value-of",
6424 xsltValueOf);
6425 xsltRegisterExtElement(ctxt, (const xmlChar *) "number",
6427 xsltNumber);
6428 xsltRegisterExtElement(ctxt, (const xmlChar *) "for-each",
6430 xsltForEach);
6431 xsltRegisterExtElement(ctxt, (const xmlChar *) "if",
6433 xsltIf);
6434 xsltRegisterExtElement(ctxt, (const xmlChar *) "choose",
6436 xsltChoose);
6437 xsltRegisterExtElement(ctxt, (const xmlChar *) "sort",
6439 xsltSort);
6440 xsltRegisterExtElement(ctxt, (const xmlChar *) "copy-of",
6442 xsltCopyOf);
6443 xsltRegisterExtElement(ctxt, (const xmlChar *) "message",
6446
6447 /*
6448 * Those don't have callable entry points but are registered anyway
6449 */
6450 xsltRegisterExtElement(ctxt, (const xmlChar *) "variable",
6452 xsltDebug);
6453 xsltRegisterExtElement(ctxt, (const xmlChar *) "param",
6455 xsltDebug);
6456 xsltRegisterExtElement(ctxt, (const xmlChar *) "with-param",
6458 xsltDebug);
6459 xsltRegisterExtElement(ctxt, (const xmlChar *) "decimal-format",
6461 xsltDebug);
6462 xsltRegisterExtElement(ctxt, (const xmlChar *) "when",
6464 xsltDebug);
6465 xsltRegisterExtElement(ctxt, (const xmlChar *) "otherwise",
6467 xsltDebug);
6468 xsltRegisterExtElement(ctxt, (const xmlChar *) "fallback",
6470 xsltDebug);
6471
6472}
int xsltInitCtxtExts(xsltTransformContextPtr ctxt)
Definition: extensions.c:1041
int xsltRegisterExtElement(xsltTransformContextPtr ctxt, const xmlChar *name, const xmlChar *URI, xsltTransformFunction function)
Definition: extensions.c:643
void xsltFreeCtxtExts(xsltTransformContextPtr ctxt)
Definition: extensions.c:664
xsltTransformFunction xsltExtElementLookup(xsltTransformContextPtr ctxt, const xmlChar *name, const xmlChar *URI)
Definition: extensions.c:1693
void xsltInitGlobals(void)
Definition: extensions.c:2282
void xsltShutdownCtxtExts(xsltTransformContextPtr ctxt)
Definition: extensions.c:1106
void xsltDebug(xsltTransformContextPtr ctxt, xmlNodePtr node ATTRIBUTE_UNUSED, xmlNodePtr inst ATTRIBUTE_UNUSED, xsltElemPreCompPtr comp ATTRIBUTE_UNUSED)
Definition: extra.c:53
void xsltNumberFormat(xsltTransformContextPtr ctxt, xsltNumberDataPtr data, xmlNodePtr node)
Definition: numbers.c:744
const xmlChar * xsltExtMarker
Definition: preproc.c:48
Arabic default style
Definition: afstyles.h:94
INT copy(TCHAR source[MAX_PATH], TCHAR dest[MAX_PATH], INT append, DWORD lpdwFlags, BOOL bTouch)
Definition: copy.c:51
struct _root root
#define xmlIsBlank_ch(c)
Definition: chvalid.h:88
Definition: list.h:37
struct list * next
Definition: list.h:38
#define NULL
Definition: types.h:112
void xsltApplyAttributeSet(xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr inst, const xmlChar *attrSets)
Definition: attributes.c:1118
void xsltAttribute(xsltTransformContextPtr ctxt, xmlNodePtr contextNode, xmlNodePtr inst, xsltElemPreCompPtr castedComp)
Definition: attributes.c:748
xsltTemplatePtr xsltGetTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node, xsltStylesheetPtr style)
Definition: pattern.c:2277
void xsltCleanupTemplates(xsltStylesheetPtr style ATTRIBUTE_UNUSED)
Definition: pattern.c:2502
int xsltCheckWrite(xsltSecurityPrefsPtr sec, xsltTransformContextPtr ctxt, const xmlChar *URL)
Definition: security.c:352
xsltSecurityPrefsPtr xsltGetDefaultSecurityPrefs(void)
Definition: security.c:180
void xsltDebugSetDefaultTrace(xsltDebugTraceCodes val)
Definition: transform.c:477
static xsltTemplatePtr templPop(xsltTransformContextPtr ctxt)
Definition: transform.c:149
static xmlDocPtr xsltApplyStylesheetInternal(xsltStylesheetPtr style, xmlDocPtr doc, const char **params, const char *output, FILE *profile, xsltTransformContextPtr userCtxt)
Definition: transform.c:5812
static xmlAttrPtr xsltShallowCopyAttr(xsltTransformContextPtr ctxt, xmlNodePtr invocNode, xmlNodePtr target, xmlAttrPtr attr)
Definition: transform.c:1155
int xsltRunStylesheet(xsltStylesheetPtr style, xmlDocPtr doc, const char **params, const char *output, xmlSAXHandlerPtr SAX, xmlOutputBufferPtr IObuf)
Definition: transform.c:6372
xmlNodePtr xsltCopyTextString(xsltTransformContextPtr ctxt, xmlNodePtr target, const xmlChar *string, int noescape)
Definition: transform.c:881
void xsltForEach(xsltTransformContextPtr ctxt, xmlNodePtr contextNode, xmlNodePtr inst, xsltElemPreCompPtr castedComp)
Definition: transform.c:5401
static xmlNsPtr xsltShallowCopyNsNode(xsltTransformContextPtr ctxt, xmlNodePtr invocNode, xmlNodePtr insert, xmlNsPtr ns)
Definition: transform.c:1515
void xsltCallTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr inst, xsltElemPreCompPtr castedComp)
Definition: transform.c:4719
xsltTransformContextPtr xsltNewTransformContext(xsltStylesheetPtr style, xmlDocPtr doc)
Definition: transform.c:564
void xsltValueOf(xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr inst, xsltElemPreCompPtr castedComp)
Definition: transform.c:4519
static xmlNodePtr xsltCopyText(xsltTransformContextPtr ctxt, xmlNodePtr target, xmlNodePtr cur, int interned)
Definition: transform.c:977
static xmlNodePtr xsltAddChild(xmlNodePtr parent, xmlNodePtr cur)
Definition: transform.c:783
static int xsltPreCompEvalToBoolean(xsltTransformContextPtr ctxt, xmlNodePtr node, xsltStylePreCompPtr comp)
Definition: transform.c:398
xmlDocPtr xsltProfileStylesheet(xsltStylesheetPtr style, xmlDocPtr doc, const char **params, FILE *output)
Definition: transform.c:6249
static xsltHTMLVersion xsltHTMLVersions[]
Definition: transform.c:5590
void xsltSort(xsltTransformContextPtr ctxt, xmlNodePtr node ATTRIBUTE_UNUSED, xmlNodePtr inst, xsltElemPreCompPtr comp)
Definition: transform.c:3879
static xmlNodePtr xsltAddTextString(xsltTransformContextPtr ctxt, xmlNodePtr target, const xmlChar *string, int len)
Definition: transform.c:809
int xsltRunStylesheetUser(xsltStylesheetPtr style, xmlDocPtr doc, const char **params, const char *output, xmlSAXHandlerPtr SAX, xmlOutputBufferPtr IObuf, FILE *profile, xsltTransformContextPtr userCtxt)
Definition: transform.c:6311
void xsltApplyImports(xsltTransformContextPtr ctxt, xmlNodePtr contextNode, xmlNodePtr inst, xsltElemPreCompPtr comp ATTRIBUTE_UNUSED)
Definition: transform.c:4650
static xmlXPathObjectPtr xsltPreCompEval(xsltTransformContextPtr ctxt, xmlNodePtr node, xsltStylePreCompPtr comp)
Definition: transform.c:349
static void xsltTransformCacheFree(xsltTransformCachePtr cache)
Definition: transform.c:514
void xsltLocalVariablePop(xsltTransformContextPtr ctxt, int limitNr, int level)
Definition: transform.c:178
void xsltProcessOneNode(xsltTransformContextPtr ctxt, xmlNodePtr contextNode, xsltStackElemPtr withParams)
Definition: transform.c:2112
static xmlNodePtr xsltCopyTreeList(xsltTransformContextPtr ctxt, xmlNodePtr invocNode, xmlNodePtr list, xmlNodePtr insert, int isLRE, int topElemVisited)
Definition: transform.c:1422
void xsltProcessingInstruction(xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr inst, xsltElemPreCompPtr castedComp)
Definition: transform.c:4309
static void xsltMessageWrapper(xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr inst, xsltElemPreCompPtr comp ATTRIBUTE_UNUSED)
Definition: transform.c:6381
static unsigned long xsltDefaultTrace
Definition: transform.c:469
void xsltCopyOf(xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr inst, xsltElemPreCompPtr castedComp)
Definition: transform.c:4375
void xsltElement(xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr inst, xsltElemPreCompPtr castedComp)
Definition: transform.c:4057
static xmlNodePtr xsltShallowCopyElem(xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr insert, int isLRE)
Definition: transform.c:1330
static void xsltTemplateParamsCleanup(xsltTransformContextPtr ctxt)
Definition: transform.c:208
static int templPush(xsltTransformContextPtr ctxt, xsltTemplatePtr value)
Definition: transform.c:121
xmlDocPtr xsltApplyStylesheetUser(xsltStylesheetPtr style, xmlDocPtr doc, const char **params, const char *output, FILE *profile, xsltTransformContextPtr userCtxt)
Definition: transform.c:6273
static xmlNsPtr xsltCopyNamespaceListInternal(xmlNodePtr node, xmlNsPtr cur)
Definition: transform.c:1458
xmlDocPtr xsltApplyStylesheet(xsltStylesheetPtr style, xmlDocPtr doc, const char **params)
Definition: transform.c:6230
void xsltIf(xsltTransformContextPtr ctxt, xmlNodePtr contextNode, xmlNodePtr inst, xsltElemPreCompPtr castedComp)
Definition: transform.c:5295
static void xsltReleaseLocalRVTs(xsltTransformContextPtr ctxt, xmlDocPtr base)
Definition: transform.c:2266
int xsltLocalVariablePush(xsltTransformContextPtr ctxt, xsltStackElemPtr variable, int level)
Definition: transform.c:2236
static void xsltApplySequenceConstructor(xsltTransformContextPtr ctxt, xmlNodePtr contextNode, xmlNodePtr list, xsltTemplatePtr templ)
Definition: transform.c:2318
static int xsltApplyFallbacks(xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr inst)
Definition: transform.c:1837
void xsltDocumentElem(xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr inst, xsltElemPreCompPtr castedComp)
Definition: transform.c:3363
static void xsltApplyXSLTTemplate(xsltTransformContextPtr ctxt, xmlNodePtr contextNode, xmlNodePtr list, xsltTemplatePtr templ, xsltStackElemPtr withParams)
Definition: transform.c:3066
void xsltFreeTransformContext(xsltTransformContextPtr ctxt)
Definition: transform.c:721
void xsltComment(xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr inst, xsltElemPreCompPtr comp ATTRIBUTE_UNUSED)
Definition: transform.c:4265
static void xsltCleanupSourceDoc(xmlDocPtr doc)
Definition: transform.c:5761
void xsltChoose(xsltTransformContextPtr ctxt, xmlNodePtr contextNode, xmlNodePtr inst, xsltElemPreCompPtr comp ATTRIBUTE_UNUSED)
Definition: transform.c:5136
#define IS_BLANK_NODE(n)
Definition: transform.c:83
int xsltMaxDepth
Definition: transform.c:71
void xsltText(xsltTransformContextPtr ctxt, xmlNodePtr node ATTRIBUTE_UNUSED, xmlNodePtr inst, xsltElemPreCompPtr comp ATTRIBUTE_UNUSED)
Definition: transform.c:4020
static int xsltCountKeys(xsltTransformContextPtr ctxt)
Definition: transform.c:5718
void xsltSetXIncludeDefault(int xinclude)
Definition: transform.c:453
void xsltCopy(xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr inst, xsltElemPreCompPtr castedComp)
Definition: transform.c:3901
xsltDebugTraceCodes xsltDebugGetDefaultTrace(void)
Definition: transform.c:488
void xsltApplyOneTemplate(xsltTransformContextPtr ctxt, xmlNodePtr contextNode, xmlNodePtr list, xsltTemplatePtr templ ATTRIBUTE_UNUSED, xsltStackElemPtr params)
Definition: transform.c:3313
static xsltTransformCachePtr xsltTransformCacheCreate(void)
Definition: transform.c:499
static int xsltDoXIncludeDefault
Definition: transform.c:444
void xsltNumber(xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr inst, xsltElemPreCompPtr castedComp)
Definition: transform.c:4593
static xmlNodePtr xsltCopyTree(xsltTransformContextPtr ctxt, xmlNodePtr invocNode, xmlNodePtr node, xmlNodePtr insert, int isLRE, int topElemVisited)
Definition: transform.c:1626
int xsltGetXIncludeDefault(void)
Definition: transform.c:465
int xsltMaxVars
Definition: transform.c:72
void xsltApplyStripSpaces(xsltTransformContextPtr ctxt, xmlNodePtr node)
Definition: transform.c:5649
static int xsltCopyAttrListNoOverwrite(xsltTransformContextPtr ctxt, xmlNodePtr invocNode, xmlNodePtr target, xmlAttrPtr attr)
Definition: transform.c:1254
void xsltRegisterAllElement(xsltTransformContextPtr ctxt)
Definition: transform.c:6393
static int xsltGetHTMLIDs(const xmlChar *version, const xmlChar **publicID, const xmlChar **systemID)
Definition: transform.c:5621
static void xsltDefaultProcessOneNode(xsltTransformContextPtr ctxt, xmlNodePtr node, xsltStackElemPtr params)
Definition: transform.c:1893
void xsltApplyTemplates(xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr inst, xsltElemPreCompPtr castedComp)
Definition: transform.c:4822
static const WCHAR version[]
Definition: asmname.c:66
const UINT template
Definition: action.c:7511
const WCHAR * text
Definition: package.c:1794
int CDECL fclose(FILE *file)
Definition: file.c:3757
FILE *CDECL fopen(const char *path, const char *mode)
Definition: file.c:4310
int ptrdiff_t
Definition: corecrt.h:194
#define INT_MAX
Definition: limits.h:26
_ACRTIMP int __cdecl system(const char *)
Definition: process.c:1297
xsltDocumentPtr xsltNewDocument(xsltTransformContextPtr ctxt, xmlDocPtr doc)
Definition: documents.c:142
void xsltFreeDocuments(xsltTransformContextPtr ctxt)
Definition: documents.c:249
method
Definition: dragdrop.c:54
return ret
Definition: mutex.c:146
r parent
Definition: btrfs.c:3010
@ XML_CHAR_ENCODING_UTF8
Definition: encoding.h:68
#define XSLT_XALAN_NAMESPACE
Definition: extra.h:48
#define XSLT_SAXON_NAMESPACE
Definition: extra.h:34
#define printf
Definition: freeldr.h:104
#define XSLT_REGISTER_FUNCTION_LOOKUP(ctxt)
Definition: functions.h:27
FxCollectionEntry * cur
size_t total
GLuint start
Definition: gl.h:1545
GLint level
Definition: gl.h:1546
GLuint GLuint end
Definition: gl.h:1545
GLdouble GLdouble GLdouble GLdouble q
Definition: gl.h:2063
GLenum func
Definition: glext.h:6028
GLuint res
Definition: glext.h:9613
GLsizeiptr size
Definition: glext.h:5919
GLfloat f
Definition: glext.h:7540
GLenum const GLfloat * params
Definition: glext.h:5645
GLuint GLfloat * val
Definition: glext.h:7180
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLenum variable
Definition: glext.h:9031
GLfloat param
Definition: glext.h:5796
GLenum GLsizei len
Definition: glext.h:6722
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
#define ATTRIBUTE_UNUSED
Definition: i386-dis.c:36
@ extra
Definition: id3.c:95
int xsltFindElemSpaceHandling(xsltTransformContextPtr ctxt, xmlNodePtr node)
Definition: imports.c:349
xsltTemplatePtr xsltFindTemplate(xsltTransformContextPtr ctxt, const xmlChar *name, const xmlChar *nameURI)
Definition: imports.c:403
xsltStylesheetPtr xsltNextImport(xsltStylesheetPtr cur)
Definition: imports.c:297
int xsltNeedElemSpaceHandling(xsltTransformContextPtr ctxt)
Definition: imports.c:322
const char * filename
Definition: ioapi.h:137
#define f
Definition: ke_i.h:83
#define profile
Definition: kernel32.h:12
void xsltFreeDocumentKeys(xsltDocumentPtr idoc)
Definition: keys.c:931
if(dx< 0)
Definition: linetemp.h:194
#define error(str)
Definition: mkdosfs.c:1605
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
struct task_struct * current
Definition: linux.c:32
static UINT UINT last
Definition: font.c:45
static PROCESS_INFORMATION pi
Definition: debugger.c:2303
static size_t elem
Definition: string.c:71
#define cmp(status, error)
Definition: error.c:114
static HWND child
Definition: cursoricon.c:298
xmlNsPtr xsltGetSpecialNamespace(xsltTransformContextPtr ctxt, xmlNodePtr invocNode, const xmlChar *nsName, const xmlChar *nsPrefix, xmlNodePtr target)
Definition: namespaces.c:319
xmlNsPtr xsltCopyNamespaceList(xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNsPtr cur)
Definition: namespaces.c:717
xmlNsPtr xsltGetNamespace(xsltTransformContextPtr ctxt, xmlNodePtr cur, xmlNsPtr ns, xmlNodePtr out)
Definition: namespaces.c:616
#define UNDEFINED_DEFAULT_NS
Definition: namespaces.h:30
#define XSLT_GET_IMPORT_PTR(res, style, name)
Definition: node.c:1070
XMLPUBVAR const xmlChar xmlStringTextNoenc[]
XMLPUBVAR const xmlChar xmlStringText[]
#define long
Definition: qsort.c:33
#define list
Definition: rosglue.h:35
#define exit(n)
Definition: config.h:202
void xmlDictFree(xmlDictPtr dict)
Definition: dict.c:333
xmlDictPtr xmlDictCreateSub(xmlDictPtr sub)
Definition: dict.c:297
int xmlDictOwns(xmlDictPtr dict, const xmlChar *str)
Definition: dict.c:376
int xmlDictReference(xmlDictPtr dict)
Definition: dict.c:317
const xmlChar * xmlDictQLookup(xmlDictPtr dict, const xmlChar *prefix, const xmlChar *name)
Definition: dict.c:894
const xmlChar * xmlDictLookup(xmlDictPtr dict, const xmlChar *name, int len)
Definition: dict.c:824
void * xmlGenericErrorContext
Definition: globals.c:410
xmlReallocFunc xmlRealloc
Definition: globals.c:214
xmlFreeFunc xmlFree
Definition: globals.c:184
xmlGenericErrorFunc xmlGenericError
Definition: globals.c:396
xmlMallocFunc xmlMalloc
Definition: globals.c:193
void * xmlHashLookup(xmlHashTablePtr hash, const xmlChar *key)
Definition: hash.c:739
void * xmlHashLookup2(xmlHashTablePtr hash, const xmlChar *key, const xmlChar *key2)
Definition: hash.c:754
xmlHashTablePtr xmlHashCreate(int size)
Definition: hash.c:160
int xmlHashAddEntry2(xmlHashTablePtr hash, const xmlChar *key, const xmlChar *key2, void *payload)
Definition: hash.c:639
#define memset(x, y, z)
Definition: compat.h:39
struct _xsltKeyDef * next
xmlFreeFunc deallocate
struct _xsltStackElem * next
xmlXPathObjectPtr value
const xmlChar * nameURI
const xmlChar * name
xmlXPathCompExprPtr comp
xmlHashTablePtr cdataSection
xmlNodePtr elem
xmlNodePtr content
const xmlChar * name
xmlNsPtr * inheritedNs
unsigned long time
struct _xsltStylesheet * style
xsltTemplatePtr * templCalledTab
xmlChar * match
xsltTemplatePtr * templTab
xsltTransformState state
const xmlChar * modeURI
xsltStackElemPtr vars
xsltDocumentPtr document
xsltTemplatePtr templ
xmlHashTablePtr globalVars
xmlNodeSetPtr nodeList
xsltTransformCachePtr cache
xmlNodePtr initialContextNode
xsltRuntimeExtraPtr extras
xsltTemplatePtr currentTemplateRule
xsltStylesheetPtr style
xsltStackElemPtr * varsTab
xmlXPathContextPtr xpathCtxt
const xmlChar * lasttext
const xmlChar * mode
Definition: cookie.c:202
WCHAR * name
Definition: cookie.c:203
Definition: cache.c:49
char * name
Definition: compiler.c:66
struct define * next
Definition: compiler.c:65
Definition: name.c:39
WCHAR * name
Definition: name.c:42
Definition: mxnamespace.c:38
BSTR prefix
Definition: mxnamespace.c:39
Definition: tools.h:99
const char * system
Definition: transform.c:5587
const char * version
Definition: transform.c:5585
xmlChar * xsltEvalXPathString(xsltTransformContextPtr ctxt, xmlXPathCompExprPtr comp)
Definition: templates.c:189
xmlChar * xsltEvalAttrValueTemplate(xsltTransformContextPtr ctxt, xmlNodePtr inst, const xmlChar *name, const xmlChar *ns)
Definition: templates.c:410
xmlAttrPtr xsltAttrListTemplateProcess(xsltTransformContextPtr ctxt, xmlNodePtr target, xmlAttrPtr attrs)
Definition: templates.c:653
xmlChar * xsltEvalTemplateString(xsltTransformContextPtr ctxt, xmlNodePtr contextNode, xmlNodePtr inst)
Definition: templates.c:207
Character const *const prefix
Definition: tempnam.cpp:195
XSLTPUBFUN void XSLTCALL xslHandleDebugger(xmlNodePtr cur, xmlNodePtr node, xsltTemplatePtr templ, xsltTransformContextPtr ctxt)
Definition: dlist.c:348
Definition: pdh_main.c:96
XMLPUBFUN xmlChar * xmlBuildURI(const xmlChar *URI, const xmlChar *base)
Definition: uri.c:1902
XMLPUBFUN xmlChar * xmlURIEscapeStr(const xmlChar *str, const xmlChar *list)
Definition: uri.c:1689
void xsltFreeRVTs(xsltTransformContextPtr ctxt)
Definition: variables.c:439
int xsltEvalGlobalVariables(xsltTransformContextPtr ctxt)
Definition: variables.c:1279
int xsltRegisterLocalRVT(xsltTransformContextPtr ctxt, xmlDocPtr RVT)
Definition: variables.c:159
int xsltRegisterPersistRVT(xsltTransformContextPtr ctxt, xmlDocPtr RVT)
Definition: variables.c:417
void xsltParseStylesheetParam(xsltTransformContextPtr ctxt, xmlNodePtr cur)
Definition: variables.c:2218
void xsltReleaseRVT(xsltTransformContextPtr ctxt, xmlDocPtr RVT)
Definition: variables.c:351
void xsltParseStylesheetVariable(xsltTransformContextPtr ctxt, xmlNodePtr inst)
Definition: variables.c:2176
void xsltFreeGlobalVariables(xsltTransformContextPtr ctxt)
Definition: variables.c:2254
xsltStackElemPtr xsltParseStylesheetCallerParam(xsltTransformContextPtr ctxt, xmlNodePtr inst)
Definition: variables.c:1989
void xsltFreeStackElemList(xsltStackElemPtr elem)
Definition: variables.c:626
int xsltEvalUserParams(xsltTransformContextPtr ctxt, const char **params)
Definition: variables.c:1686
#define XSLT_REGISTER_VARIABLE_LOOKUP(ctxt)
Definition: variables.h:30
#define XSLT_RVT_GLOBAL
Definition: variables.h:62
#define XSLT_RVT_FUNC_RESULT
Definition: variables.h:55
#define XSLT_RVT_LOCAL
Definition: variables.h:46
XMLPUBFUN xmlChar * xmlStrndup(const xmlChar *cur, int len)
Definition: xmlstring.c:45
XMLPUBFUN int xmlStrlen(const xmlChar *str)
Definition: xmlstring.c:428
XMLPUBFUN int xmlStrcasecmp(const xmlChar *str1, const xmlChar *str2)
Definition: xmlstring.c:277
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
xsltTransformContext * xsltTransformContextPtr
@ XSLT_FUNC_VARIABLE
xsltTransformCache * xsltTransformCachePtr
xsltElemPreComp * xsltElemPreCompPtr
xsltOutputType
@ XSLT_OUTPUT_XML
@ XSLT_OUTPUT_HTML
@ XSLT_OUTPUT_TEXT
xsltRuntimeExtra * xsltRuntimeExtraPtr
xsltTemplate * xsltTemplatePtr
@ XSLT_STATE_STOPPED
@ XSLT_STATE_OK
#define XSLT_IS_TEXT_NODE(n)
Definition: xsltInternals.h:37
#define CHECK_STOPPED
#define XSLT_MAX_SORT
#define XSLT_IS_RES_TREE_FRAG(n)
Definition: xsltInternals.h:55
xsltStylePreComp * xsltStylePreCompPtr
void(* xsltTransformFunction)(xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr inst, xsltElemPreCompPtr comp)
xsltStylesheetPtr xsltNewStylesheet(void)
Definition: xslt.c:810
void xsltFreeStylesheet(xsltStylesheetPtr style)
Definition: xslt.c:965
#define XSLT_PARSE_OPTIONS
Definition: xslt.h:54
#define XSLT_NAMESPACE
Definition: xslt.h:46
xmlChar * xsltStrxfrm(void *vlocale, const xmlChar *string)
Definition: xsltlocale.c:392
void * xsltNewLocale(const xmlChar *languageTag, int lowerFirst ATTRIBUTE_UNUSED)
Definition: xsltlocale.c:112
void xsltFreeLocale(void *locale)
Definition: xsltlocale.c:372
void xsltDoSortFunction(xsltTransformContextPtr ctxt, xmlNodePtr *sorts, int nbsorts)
Definition: xsltutils.c:1447
const xmlChar * xsltGetQNameURI(xmlNodePtr node, xmlChar **name)
Definition: xsltutils.c:837
void xsltTransformError(xsltTransformContextPtr ctxt, xsltStylesheetPtr style, xmlNodePtr node, const char *msg,...)
Definition: xsltutils.c:762
xmlGenericErrorFunc xsltGenericError
Definition: xsltutils.c:586
int xsltClearSourceNodeFlags(xmlNodePtr node, int flags)
Definition: xsltutils.c:1999
xmlGenericErrorFunc xsltGenericDebug
Definition: xsltutils.c:632
void ** xsltGetPSVIPtr(xmlNodePtr cur)
Definition: xsltutils.c:2030
int xsltSaveResultTo(xmlOutputBufferPtr buf, xmlDocPtr result, xsltStylesheetPtr style)
Definition: xsltutils.c:1564
int xsltSaveResultToFilename(const char *URL, xmlDocPtr result, xsltStylesheetPtr style, int compression)
Definition: xsltutils.c:1740
int xslDebugStatus
Definition: xsltutils.c:2603
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
int xsltSaveResultToFile(FILE *file, xmlDocPtr result, xsltStylesheetPtr style)
Definition: xsltutils.c:1783
void xsltMessage(xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr inst)
Definition: xsltutils.c:492
@ XSLT_DEBUG_QUIT
Definition: xsltutils.h:313
@ XSLT_DEBUG_NONE
Definition: xsltutils.h:304
@ XSLT_DEBUG_RUN_RESTART
Definition: xsltutils.h:312
#define IS_XSLT_NAME(n, val)
Definition: xsltutils.h:60
xsltDebugTraceCodes
Definition: xsltutils.h:105
@ XSLT_TRACE_VALUE_OF
Definition: xsltutils.h:115
@ XSLT_TRACE_FOR_EACH
Definition: xsltutils.h:120
@ XSLT_TRACE_COPY_OF
Definition: xsltutils.h:114
@ XSLT_TRACE_ALL
Definition: xsltutils.h:106
@ XSLT_TRACE_APPLY_TEMPLATE
Definition: xsltutils.h:110
@ XSLT_TRACE_COPY_TEXT
Definition: xsltutils.h:108
@ XSLT_TRACE_COPY
Definition: xsltutils.h:111
@ XSLT_TRACE_PROCESS_NODE
Definition: xsltutils.h:109
@ XSLT_TRACE_CHOOSE
Definition: xsltutils.h:118
@ XSLT_TRACE_COMMENT
Definition: xsltutils.h:112
@ XSLT_TRACE_PI
Definition: xsltutils.h:113
@ XSLT_TRACE_CALL_TEMPLATE
Definition: xsltutils.h:116
@ XSLT_TRACE_STRIP_SPACES
Definition: xsltutils.h:121
@ XSLT_TRACE_APPLY_TEMPLATES
Definition: xsltutils.h:117
@ XSLT_TRACE_IF
Definition: xsltutils.h:119
#define IS_XSLT_REAL_NODE(n)
Definition: xsltutils.h:68
#define XSLT_TRACE(ctxt, code, call)
Definition: xsltutils.h:132
#define XSLT_TODO
Definition: xsltutils.h:31
#define IS_XSLT_ELEM(n)
Definition: xsltutils.h:51