ReactOS 0.4.16-dev-2206-gc56950d
xslt.c
Go to the documentation of this file.
1/*
2 * xslt.c: Implemetation of an XSL Transformation 1.0 engine
3 *
4 * Reference:
5 * XSLT specification
6 * http://www.w3.org/TR/1999/REC-xslt-19991116
7 *
8 * Associating Style Sheets with XML documents
9 * http://www.w3.org/1999/06/REC-xml-stylesheet-19990629
10 *
11 * See Copyright for the status of this software.
12 *
13 * daniel@veillard.com
14 */
15
16#define IN_LIBXSLT
17#include "libxslt.h"
18
19#include <string.h>
20
21#include <libxml/xmlmemory.h>
22#include <libxml/parser.h>
23#include <libxml/tree.h>
24#include <libxml/valid.h>
25#include <libxml/hash.h>
26#include <libxml/uri.h>
27#include <libxml/xmlerror.h>
30#include <libxml/xpath.h>
31#include "xslt.h"
32#include "xsltInternals.h"
33#include "pattern.h"
34#include "variables.h"
35#include "namespaces.h"
36#include "attributes.h"
37#include "xsltutils.h"
38#include "imports.h"
39#include "keys.h"
40#include "documents.h"
41#include "extensions.h"
42#include "preproc.h"
43#include "extra.h"
44#include "security.h"
45#include "xsltlocale.h"
46
47#ifdef WITH_XSLT_DEBUG
48#define WITH_XSLT_DEBUG_PARSING
49/* #define WITH_XSLT_DEBUG_BLANKS */
50#endif
51
55
56#ifdef XSLT_REFACTORED
57
58const xmlChar *xsltConstNamespaceNameXSLT = (const xmlChar *) XSLT_NAMESPACE;
59
60#define XSLT_ELEMENT_CATEGORY_XSLT 0
61#define XSLT_ELEMENT_CATEGORY_EXTENSION 1
62#define XSLT_ELEMENT_CATEGORY_LRE 2
63
64/*
65* xsltLiteralResultMarker:
66* Marker for Literal result elements, in order to avoid multiple attempts
67* to recognize such elements in the stylesheet's tree.
68* This marker is set on node->psvi during the initial traversal
69* of a stylesheet's node tree.
70*
71const xmlChar *xsltLiteralResultMarker =
72 (const xmlChar *) "Literal Result Element";
73*/
74
75/*
76* xsltXSLTTextMarker:
77* Marker for xsl:text elements. Used to recognize xsl:text elements
78* for post-processing of the stylesheet's tree, where those
79* elements are removed from the tree.
80*/
81const xmlChar *xsltXSLTTextMarker = (const xmlChar *) "XSLT Text Element";
82
83/*
84* xsltXSLTAttrMarker:
85* Marker for XSLT attribute on Literal Result Elements.
86*/
87const xmlChar *xsltXSLTAttrMarker = (const xmlChar *) "LRE XSLT Attr";
88
89#endif
90
91#ifdef XSLT_LOCALE_WINAPI
92extern xmlRMutexPtr xsltLocaleMutex;
93#endif
94
95/*
96 * Useful macros
97 */
98
99#ifdef IS_BLANK
100#undef IS_BLANK
101#endif
102#define IS_BLANK(c) (((c) == 0x20) || ((c) == 0x09) || ((c) == 0xA) || \
103 ((c) == 0x0D))
104
105#ifdef IS_BLANK_NODE
106#undef IS_BLANK_NODE
107#endif
108#define IS_BLANK_NODE(n) \
109 (((n)->type == XML_TEXT_NODE) && (xsltIsBlank((n)->content)))
110
119static void
121 xmlNodePtr node)
122{
123 if ((style == NULL) || (node == NULL))
124 return;
125
126 if (IS_XSLT_ELEM(node))
128 "The XSLT-element '%s' is not allowed at this position.\n",
129 node->name);
130 else
132 "The element '%s' is not allowed at this position.\n",
133 node->name);
134 style->errors++;
135}
136
137#ifdef XSLT_REFACTORED
138#else
149static int
151{
152 int i;
153
154 /* do not push duplicates */
155 for (i = 0;i < style->exclPrefixNr;i++) {
156 if (xmlStrEqual(style->exclPrefixTab[i], value))
157 return(-1);
158 }
159 if (style->exclPrefixNr >= style->exclPrefixMax) {
160 xmlChar **tmp;
161 size_t max = style->exclPrefixMax ? style->exclPrefixMax * 2 : 4;
162
163 tmp = xmlRealloc(style->exclPrefixTab,
164 max * sizeof(style->exclPrefixTab[0]));
165 if (tmp == NULL) {
166 xmlGenericError(xmlGenericErrorContext, "realloc failed !\n");
167 return (-1);
168 }
169 style->exclPrefixTab = tmp;
170 style->exclPrefixMax = max;
171 }
172 style->exclPrefixTab[style->exclPrefixNr] = value;
173 style->exclPrefix = value;
174 return (style->exclPrefixNr++);
175}
184static xmlChar *
186{
187 xmlChar *ret;
188
189 if (style->exclPrefixNr <= 0)
190 return (0);
191 style->exclPrefixNr--;
192 if (style->exclPrefixNr > 0)
193 style->exclPrefix = style->exclPrefixTab[style->exclPrefixNr - 1];
194 else
195 style->exclPrefix = NULL;
196 ret = style->exclPrefixTab[style->exclPrefixNr];
197 style->exclPrefixTab[style->exclPrefixNr] = 0;
198 return (ret);
199}
200#endif
201
202/************************************************************************
203 * *
204 * Helper functions *
205 * *
206 ************************************************************************/
207
208static int initialized = 0;
215void
216xsltInit (void) {
217 if (initialized == 0) {
218 initialized = 1;
219#ifdef XSLT_LOCALE_WINAPI
220 xsltLocaleMutex = xmlNewRMutex();
221#endif
223 }
224}
225
231void
233#ifdef XSLT_LOCALE_WINAPI
234 xmlFreeRMutex(xsltLocaleMutex);
235 xsltLocaleMutex = NULL;
236#endif
237 initialized = 0;
238}
239
248int
250 if (str == NULL)
251 return(1);
252 while (*str != 0) {
253 if (!(IS_BLANK(*str))) return(0);
254 str++;
255 }
256 return(1);
257}
258
259/************************************************************************
260 * *
261 * Routines to handle XSLT data structures *
262 * *
263 ************************************************************************/
266{
268 /* UTF-8 for 0x2030 */
269 static const xmlChar permille[4] = {0xe2, 0x80, 0xb0, 0};
270
271 self = xmlMalloc(sizeof(xsltDecimalFormat));
272 if (self != NULL) {
273 self->next = NULL;
274 self->nsUri = nsUri;
275 self->name = name;
276
277 /* Default values */
278 self->digit = xmlStrdup(BAD_CAST("#"));
279 self->patternSeparator = xmlStrdup(BAD_CAST(";"));
280 self->decimalPoint = xmlStrdup(BAD_CAST("."));
281 self->grouping = xmlStrdup(BAD_CAST(","));
282 self->percent = xmlStrdup(BAD_CAST("%"));
283 self->permille = xmlStrdup(BAD_CAST(permille));
284 self->zeroDigit = xmlStrdup(BAD_CAST("0"));
285 self->minusSign = xmlStrdup(BAD_CAST("-"));
286 self->infinity = xmlStrdup(BAD_CAST("Infinity"));
287 self->noNumber = xmlStrdup(BAD_CAST("NaN"));
288 }
289 return self;
290}
291
292static void
294{
295 if (self != NULL) {
296 if (self->digit)
297 xmlFree(self->digit);
298 if (self->patternSeparator)
300 if (self->decimalPoint)
301 xmlFree(self->decimalPoint);
302 if (self->grouping)
303 xmlFree(self->grouping);
304 if (self->percent)
305 xmlFree(self->percent);
306 if (self->permille)
307 xmlFree(self->permille);
308 if (self->zeroDigit)
309 xmlFree(self->zeroDigit);
310 if (self->minusSign)
311 xmlFree(self->minusSign);
312 if (self->infinity)
313 xmlFree(self->infinity);
314 if (self->noNumber)
315 xmlFree(self->noNumber);
316 if (self->name)
317 xmlFree(self->name);
318 xmlFree(self);
319 }
320}
321
322static void
324{
327
328 if (self == NULL)
329 return;
330
331 iter = self->decimalFormat;
332 while (iter != NULL) {
333 tmp = iter->next;
335 iter = tmp;
336 }
337}
338
350{
352
353 if (name == NULL)
354 return style->decimalFormat;
355
356 while (style != NULL) {
357 for (result = style->decimalFormat->next;
358 result != NULL;
359 result = result->next) {
360 if ((result->nsUri == NULL) && xmlStrEqual(name, result->name))
361 return result;
362 }
364 }
365 return result;
366}
367
380 const xmlChar *name)
381{
383
384 if (name == NULL)
385 return style->decimalFormat;
386
387 while (style != NULL) {
388 for (result = style->decimalFormat->next;
389 result != NULL;
390 result = result->next) {
391 if (xmlStrEqual(nsUri, result->nsUri) &&
393 return result;
394 }
396 }
397 return result;
398}
399
400
408static xsltTemplatePtr
411
413 if (cur == NULL) {
415 "xsltNewTemplate : malloc failed\n");
416 return(NULL);
417 }
418 memset(cur, 0, sizeof(xsltTemplate));
419 cur->priority = XSLT_PAT_NO_PRIORITY;
420 return(cur);
421}
422
429static void
431 if (template == NULL)
432 return;
433 if (template->match) xmlFree(template->match);
434/*
435* NOTE: @name and @nameURI are put into the string dict now.
436* if (template->name) xmlFree(template->name);
437* if (template->nameURI) xmlFree(template->nameURI);
438*/
439/*
440 if (template->mode) xmlFree(template->mode);
441 if (template->modeURI) xmlFree(template->modeURI);
442 */
443 if (template->inheritedNs) xmlFree(template->inheritedNs);
444
445 /* free profiling data */
446 if (template->templCalledTab) xmlFree(template->templCalledTab);
447 if (template->templCountTab) xmlFree(template->templCountTab);
448
449 memset(template, -1, sizeof(xsltTemplate));
450 xmlFree(template);
451}
452
459static void
462
463 while (template != NULL) {
464 cur = template;
465 template = template->next;
467 }
468}
469
470#ifdef XSLT_REFACTORED
471
472static void
473xsltFreeNsAliasList(xsltNsAliasPtr item)
474{
475 xsltNsAliasPtr tmp;
476
477 while (item) {
478 tmp = item;
479 item = item->next;
480 xmlFree(tmp);
481 }
482 return;
483}
484
485#ifdef XSLT_REFACTORED_XSLT_NSCOMP
486static void
487xsltFreeNamespaceMap(xsltNsMapPtr item)
488{
489 xsltNsMapPtr tmp;
490
491 while (item) {
492 tmp = item;
493 item = item->next;
494 xmlFree(tmp);
495 }
496 return;
497}
498
499static xsltNsMapPtr
500xsltNewNamespaceMapItem(xsltCompilerCtxtPtr cctxt,
501 xmlDocPtr doc,
502 xmlNsPtr ns,
503 xmlNodePtr elem)
504{
505 xsltNsMapPtr ret;
506
507 if ((cctxt == NULL) || (doc == NULL) || (ns == NULL))
508 return(NULL);
509
510 ret = (xsltNsMapPtr) xmlMalloc(sizeof(xsltNsMap));
511 if (ret == NULL) {
512 xsltTransformError(NULL, cctxt->style, elem,
513 "Internal error: (xsltNewNamespaceMapItem) "
514 "memory allocation failed.\n");
515 return(NULL);
516 }
517 memset(ret, 0, sizeof(xsltNsMap));
518 ret->doc = doc;
519 ret->ns = ns;
520 ret->origNsName = ns->href;
521 /*
522 * Store the item at current stylesheet-level.
523 */
524 if (cctxt->psData->nsMap != NULL)
525 ret->next = cctxt->psData->nsMap;
526 cctxt->psData->nsMap = ret;
527
528 return(ret);
529}
530#endif /* XSLT_REFACTORED_XSLT_NSCOMP */
531
538static void
539xsltCompilerVarInfoFree(xsltCompilerCtxtPtr cctxt)
540{
541 xsltVarInfoPtr ivar = cctxt->ivars, ivartmp;
542
543 while (ivar) {
544 ivartmp = ivar;
545 ivar = ivar->next;
546 xmlFree(ivartmp);
547 }
548}
549
555static void
556xsltCompilationCtxtFree(xsltCompilerCtxtPtr cctxt)
557{
558 if (cctxt == NULL)
559 return;
560#ifdef WITH_XSLT_DEBUG_PARSING
562 "Freeing compilation context\n");
564 "### Max inodes: %d\n", cctxt->maxNodeInfos);
566 "### Max LREs : %d\n", cctxt->maxLREs);
567#endif
568 /*
569 * Free node-infos.
570 */
571 if (cctxt->inodeList != NULL) {
572 xsltCompilerNodeInfoPtr tmp, cur = cctxt->inodeList;
573 while (cur != NULL) {
574 tmp = cur;
575 cur = cur->next;
576 xmlFree(tmp);
577 }
578 }
579 if (cctxt->tmpList != NULL)
580 xsltPointerListFree(cctxt->tmpList);
581 if (cctxt->nsAliases != NULL)
582 xsltFreeNsAliasList(cctxt->nsAliases);
583
584 if (cctxt->ivars)
585 xsltCompilerVarInfoFree(cctxt);
586
587 xmlFree(cctxt);
588}
589
598static xsltCompilerCtxtPtr
599xsltCompilationCtxtCreate(xsltStylesheetPtr style) {
600 xsltCompilerCtxtPtr ret;
601
602 ret = (xsltCompilerCtxtPtr) xmlMalloc(sizeof(xsltCompilerCtxt));
603 if (ret == NULL) {
605 "xsltCompilerCreate: allocation of compiler "
606 "context failed.\n");
607 return(NULL);
608 }
609 memset(ret, 0, sizeof(xsltCompilerCtxt));
610
611 ret->errSeverity = XSLT_ERROR_SEVERITY_ERROR;
612 ret->tmpList = xsltPointerListCreate(20);
613 if (ret->tmpList == NULL) {
614 goto internal_err;
615 }
616
617 return(ret);
618
619internal_err:
620 xsltCompilationCtxtFree(ret);
621 return(NULL);
622}
623
624static void
625xsltLREEffectiveNsNodesFree(xsltEffectiveNsPtr first)
626{
627 xsltEffectiveNsPtr tmp;
628
629 while (first != NULL) {
630 tmp = first;
631 first = first->nextInStore;
632 xmlFree(tmp);
633 }
634}
635
636static void
637xsltFreePrincipalStylesheetData(xsltPrincipalStylesheetDataPtr data)
638{
639 if (data == NULL)
640 return;
641
642 if (data->inScopeNamespaces != NULL) {
643 int i;
644 xsltNsListContainerPtr nsi;
645 xsltPointerListPtr list =
646 (xsltPointerListPtr) data->inScopeNamespaces;
647
648 for (i = 0; i < list->number; i++) {
649 /*
650 * REVISIT TODO: Free info of in-scope namespaces.
651 */
652 nsi = (xsltNsListContainerPtr) list->items[i];
653 if (nsi->list != NULL)
654 xmlFree(nsi->list);
655 xmlFree(nsi);
656 }
657 xsltPointerListFree(list);
658 data->inScopeNamespaces = NULL;
659 }
660
661 if (data->exclResultNamespaces != NULL) {
662 int i;
663 xsltPointerListPtr list = (xsltPointerListPtr)
664 data->exclResultNamespaces;
665
666 for (i = 0; i < list->number; i++)
667 xsltPointerListFree((xsltPointerListPtr) list->items[i]);
668
669 xsltPointerListFree(list);
670 data->exclResultNamespaces = NULL;
671 }
672
673 if (data->extElemNamespaces != NULL) {
674 xsltPointerListPtr list = (xsltPointerListPtr)
675 data->extElemNamespaces;
676 int i;
677
678 for (i = 0; i < list->number; i++)
679 xsltPointerListFree((xsltPointerListPtr) list->items[i]);
680
681 xsltPointerListFree(list);
682 data->extElemNamespaces = NULL;
683 }
684 if (data->effectiveNs) {
685 xsltLREEffectiveNsNodesFree(data->effectiveNs);
686 data->effectiveNs = NULL;
687 }
688#ifdef XSLT_REFACTORED_XSLT_NSCOMP
689 xsltFreeNamespaceMap(data->nsMap);
690#endif
691 xmlFree(data);
692}
693
694static xsltPrincipalStylesheetDataPtr
695xsltNewPrincipalStylesheetData(void)
696{
697 xsltPrincipalStylesheetDataPtr ret;
698
699 ret = (xsltPrincipalStylesheetDataPtr)
700 xmlMalloc(sizeof(xsltPrincipalStylesheetData));
701 if (ret == NULL) {
703 "xsltNewPrincipalStylesheetData: memory allocation failed.\n");
704 return(NULL);
705 }
706 memset(ret, 0, sizeof(xsltPrincipalStylesheetData));
707
708 /*
709 * Global list of in-scope namespaces.
710 */
711 ret->inScopeNamespaces = xsltPointerListCreate(-1);
712 if (ret->inScopeNamespaces == NULL)
713 goto internal_err;
714 /*
715 * Global list of excluded result ns-decls.
716 */
717 ret->exclResultNamespaces = xsltPointerListCreate(-1);
718 if (ret->exclResultNamespaces == NULL)
719 goto internal_err;
720 /*
721 * Global list of extension instruction namespace names.
722 */
723 ret->extElemNamespaces = xsltPointerListCreate(-1);
724 if (ret->extElemNamespaces == NULL)
725 goto internal_err;
726
727 return(ret);
728
729internal_err:
730
731 return(NULL);
732}
733
734#endif
735
747
749 if (ret == NULL) {
751 "xsltNewStylesheet : malloc failed\n");
752 goto internal_err;
753 }
754 memset(ret, 0, sizeof(xsltStylesheet));
755
756 ret->parent = parent;
757 ret->omitXmlDeclaration = -1;
758 ret->standalone = -1;
759 ret->decimalFormat = xsltNewDecimalFormat(NULL, NULL);
760 ret->indent = -1;
761 ret->errors = 0;
762 ret->warnings = 0;
763 ret->exclPrefixNr = 0;
764 ret->exclPrefixMax = 0;
765 ret->exclPrefixTab = NULL;
766 ret->extInfos = NULL;
767 ret->extrasNr = 0;
768 ret->internalized = 1;
769 ret->literal_result = 0;
770 ret->forwards_compatible = 0;
771 ret->dict = xmlDictCreate();
772#ifdef WITH_XSLT_DEBUG
774 "creating dictionary for stylesheet\n");
775#endif
776
777 if (parent == NULL) {
778 ret->principal = ret;
779
780 ret->xpathCtxt = xmlXPathNewContext(NULL);
781 if (ret->xpathCtxt == NULL) {
783 "xsltNewStylesheet: xmlXPathNewContext failed\n");
784 goto internal_err;
785 }
786 if (xmlXPathContextSetCache(ret->xpathCtxt, 1, -1, 0) == -1)
787 goto internal_err;
788 } else {
789 ret->principal = parent->principal;
790 }
791
792 xsltInit();
793
794 return(ret);
795
796internal_err:
797 if (ret != NULL)
799 return(NULL);
800}
801
812}
813
823int
825{
826 return(style->extrasNr++);
827}
828
839int
841{
842 if (ctxt->extrasNr >= ctxt->extrasMax) {
843 int i;
844 if (ctxt->extrasNr == 0) {
845 ctxt->extrasMax = 20;
847 xmlMalloc(ctxt->extrasMax * sizeof(xsltRuntimeExtra));
848 if (ctxt->extras == NULL) {
850 "xsltAllocateExtraCtxt: out of memory\n");
851 return(0);
852 }
853 for (i = 0;i < ctxt->extrasMax;i++) {
854 ctxt->extras[i].info = NULL;
855 ctxt->extras[i].deallocate = NULL;
856 ctxt->extras[i].val.ptr = NULL;
857 }
858
859 } else {
861
862 ctxt->extrasMax += 100;
864 ctxt->extrasMax * sizeof(xsltRuntimeExtra));
865 if (tmp == NULL) {
867 "xsltAllocateExtraCtxt: out of memory\n");
868 return(0);
869 }
870 ctxt->extras = tmp;
871 for (i = ctxt->extrasNr;i < ctxt->extrasMax;i++) {
872 ctxt->extras[i].info = NULL;
873 ctxt->extras[i].deallocate = NULL;
874 ctxt->extras[i].val.ptr = NULL;
875 }
876 }
877 }
878 return(ctxt->extrasNr++);
879}
880
887static void
890
891 while (style != NULL) {
892 next = style->next;
894 style = next;
895 }
896}
897
909static int
911 xmlNodePtr rootElem ATTRIBUTE_UNUSED)
912{
913#if 0 /* TODO: Currently disabled, since probably not needed. */
914 xmlNodePtr cur;
915
916 if ((doc == NULL) || (rootElem == NULL) ||
917 (rootElem->type != XML_ELEMENT_NODE) ||
918 (doc != rootElem->doc))
919 return(-1);
920
921 /*
922 * Cleanup was suggested by Aleksey Sanin:
923 * Clear the PSVI field to avoid problems if the
924 * node-tree of the stylesheet is intended to be used for
925 * further processing by the user (e.g. for compiling it
926 * once again - although not recommended).
927 */
928
929 cur = rootElem;
930 while (cur != NULL) {
931 if (cur->type == XML_ELEMENT_NODE) {
932 /*
933 * Clear the PSVI field.
934 */
935 cur->psvi = NULL;
936 if (cur->children) {
937 cur = cur->children;
938 continue;
939 }
940 }
941
942leave_node:
943 if (cur == rootElem)
944 break;
945 if (cur->next != NULL)
946 cur = cur->next;
947 else {
948 cur = cur->parent;
949 if (cur == NULL)
950 break;
951 goto leave_node;
952 }
953 }
954#endif /* #if 0 */
955 return(0);
956}
957
964void
966{
967 if (style == NULL)
968 return;
969
970#ifdef XSLT_REFACTORED
971 /*
972 * Start with a cleanup of the main stylesheet's doc.
973 */
974 if ((style->principal == style) && (style->doc))
976 xmlDocGetRootElement(style->doc));
977#ifdef XSLT_REFACTORED_XSLT_NSCOMP
978 /*
979 * Restore changed ns-decls before freeing the document.
980 */
981 if ((style->doc != NULL) &&
982 XSLT_HAS_INTERNAL_NSMAP(style))
983 {
984 xsltRestoreDocumentNamespaces(XSLT_GET_INTERNAL_NSMAP(style),
985 style->doc);
986 }
987#endif /* XSLT_REFACTORED_XSLT_NSCOMP */
988#else
989 /*
990 * Start with a cleanup of the main stylesheet's doc.
991 */
992 if ((style->parent == NULL) && (style->doc))
994 xmlDocGetRootElement(style->doc));
995#endif /* XSLT_REFACTORED */
996
1001 xsltFreeTemplateList(style->templates);
1005 /*
1006 * Free documents of all included stylsheet modules of this
1007 * stylesheet level.
1008 */
1010 /*
1011 * TODO: Best time to shutdown extension stuff?
1012 */
1014
1015 if (style->variables != NULL)
1016 xsltFreeStackElemList(style->variables);
1017 if (style->cdataSection != NULL)
1018 xmlHashFree(style->cdataSection, NULL);
1019 if (style->stripSpaces != NULL)
1020 xmlHashFree(style->stripSpaces, NULL);
1021 if (style->nsHash != NULL)
1022 xmlHashFree(style->nsHash, NULL);
1023 if (style->exclPrefixTab != NULL)
1024 xmlFree(style->exclPrefixTab);
1025 if (style->method != NULL)
1026 xmlFree(style->method);
1027 if (style->methodURI != NULL)
1028 xmlFree(style->methodURI);
1029 if (style->version != NULL)
1030 xmlFree(style->version);
1031 if (style->encoding != NULL)
1032 xmlFree(style->encoding);
1033 if (style->doctypePublic != NULL)
1034 xmlFree(style->doctypePublic);
1035 if (style->doctypeSystem != NULL)
1036 xmlFree(style->doctypeSystem);
1037 if (style->mediaType != NULL)
1038 xmlFree(style->mediaType);
1039 if (style->attVTs)
1040 xsltFreeAVTList(style->attVTs);
1041 if (style->imports != NULL)
1042 xsltFreeStylesheetList(style->imports);
1043
1044#ifdef XSLT_REFACTORED
1045 /*
1046 * If this is the principal stylesheet, then
1047 * free its internal data.
1048 */
1049 if (style->principal == style) {
1050 if (style->principalData) {
1051 xsltFreePrincipalStylesheetData(style->principalData);
1052 style->principalData = NULL;
1053 }
1054 }
1055#endif
1056 /*
1057 * Better to free the main document of this stylesheet level
1058 * at the end - so here.
1059 */
1060 if (style->doc != NULL) {
1061 xmlFreeDoc(style->doc);
1062 }
1063
1064#ifdef WITH_XSLT_DEBUG
1066 "freeing dictionary from stylesheet\n");
1067#endif
1068 xmlDictFree(style->dict);
1069
1070 if (style->xpathCtxt != NULL)
1071 xmlXPathFreeContext(style->xpathCtxt);
1072
1073 memset(style, -1, sizeof(xsltStylesheet));
1074 xmlFree(style);
1075}
1076
1077/************************************************************************
1078 * *
1079 * Parsing of an XSLT Stylesheet *
1080 * *
1081 ************************************************************************/
1082
1083#ifdef XSLT_REFACTORED
1084 /*
1085 * This is now performed in an optimized way in xsltParseXSLTTemplate.
1086 */
1087#else
1100static int
1102 xsltTemplatePtr template,
1103 xmlNodePtr node)
1104{
1105 xmlNsPtr cur;
1106 xmlNsPtr *ret = NULL, *tmp;
1107 int nbns = 0;
1108 int maxns = 0;
1109 int i;
1110
1111 if ((style == NULL) || (template == NULL) || (node == NULL) ||
1112 (template->inheritedNsNr != 0) || (template->inheritedNs != NULL))
1113 return(0);
1114 while (node != NULL) {
1115 if (node->type == XML_ELEMENT_NODE) {
1116 cur = node->nsDef;
1117 while (cur != NULL) {
1118 if (xmlStrEqual(cur->href, XSLT_NAMESPACE))
1119 goto skip_ns;
1120
1121 if ((cur->prefix != NULL) &&
1122 (xsltCheckExtPrefix(style, cur->prefix)))
1123 goto skip_ns;
1124 /*
1125 * Check if this namespace was excluded.
1126 * Note that at this point only the exclusions defined
1127 * on the topmost stylesheet element are in the exclusion-list.
1128 */
1129 for (i = 0;i < style->exclPrefixNr;i++) {
1130 if (xmlStrEqual(cur->href, style->exclPrefixTab[i]))
1131 goto skip_ns;
1132 }
1133 /*
1134 * Skip shadowed namespace bindings.
1135 */
1136 for (i = 0; i < nbns; i++) {
1137 if ((cur->prefix == ret[i]->prefix) ||
1138 (xmlStrEqual(cur->prefix, ret[i]->prefix)))
1139 break;
1140 }
1141 if (i >= nbns) {
1142 if (nbns >= maxns) {
1143 maxns = (maxns == 0) ? 10 : 2 * maxns;
1144 tmp = (xmlNsPtr *) xmlRealloc(ret,
1145 (maxns + 1) * sizeof(xmlNsPtr));
1146 if (tmp == NULL) {
1148 "xsltGetInheritedNsList : realloc failed!\n");
1149 xmlFree(ret);
1150 return(0);
1151 }
1152 ret = tmp;
1153 }
1154 ret[nbns++] = cur;
1155 ret[nbns] = NULL;
1156 }
1157skip_ns:
1158 cur = cur->next;
1159 }
1160 }
1161 node = node->parent;
1162 }
1163 if (nbns != 0) {
1164#ifdef WITH_XSLT_DEBUG_PARSING
1166 "template has %d inherited namespaces\n", nbns);
1167#endif
1168 template->inheritedNsNr = nbns;
1169 template->inheritedNs = ret;
1170 }
1171 return (nbns);
1172}
1173#endif /* else of XSLT_REFACTORED */
1174
1184void
1186{
1187 xmlChar *elements,
1188 *prop;
1190 *end;
1191
1192 if ((cur == NULL) || (style == NULL) || (cur->type != XML_ELEMENT_NODE))
1193 return;
1194
1195 prop = xmlGetNsProp(cur, (const xmlChar *) "version", NULL);
1196 if (prop != NULL) {
1197 if (style->version != NULL)
1198 xmlFree(style->version);
1199 style->version = prop;
1200 }
1201
1202 prop = xmlGetNsProp(cur, (const xmlChar *) "encoding", NULL);
1203 if (prop != NULL) {
1204 if (style->encoding != NULL)
1205 xmlFree(style->encoding);
1206 style->encoding = prop;
1207 }
1208
1209 /* relaxed to support xt:document
1210 * TODO KB: What does "relaxed to support xt:document" mean?
1211 */
1212 prop = xmlGetNsProp(cur, (const xmlChar *) "method", NULL);
1213 if (prop != NULL) {
1214 const xmlChar *URI;
1215
1216 if (style->method != NULL)
1217 xmlFree(style->method);
1218 style->method = NULL;
1219 if (style->methodURI != NULL)
1220 xmlFree(style->methodURI);
1221 style->methodURI = NULL;
1222
1223 /*
1224 * TODO: Don't use xsltGetQNameURI().
1225 */
1226 URI = xsltGetQNameURI(cur, &prop);
1227 if (prop == NULL) {
1228 if (style != NULL) style->errors++;
1229 } else if (URI == NULL) {
1230 if ((xmlStrEqual(prop, (const xmlChar *) "xml")) ||
1231 (xmlStrEqual(prop, (const xmlChar *) "html")) ||
1232 (xmlStrEqual(prop, (const xmlChar *) "text"))) {
1233 style->method = prop;
1234 } else {
1236 "invalid value for method: %s\n", prop);
1237 if (style != NULL) style->warnings++;
1238 xmlFree(prop);
1239 }
1240 } else {
1241 style->method = prop;
1242 style->methodURI = xmlStrdup(URI);
1243 }
1244 }
1245
1246 prop = xmlGetNsProp(cur, (const xmlChar *) "doctype-system", NULL);
1247 if (prop != NULL) {
1248 if (style->doctypeSystem != NULL)
1249 xmlFree(style->doctypeSystem);
1250 style->doctypeSystem = prop;
1251 }
1252
1253 prop = xmlGetNsProp(cur, (const xmlChar *) "doctype-public", NULL);
1254 if (prop != NULL) {
1255 if (style->doctypePublic != NULL)
1256 xmlFree(style->doctypePublic);
1257 style->doctypePublic = prop;
1258 }
1259
1260 prop = xmlGetNsProp(cur, (const xmlChar *) "standalone", NULL);
1261 if (prop != NULL) {
1262 if (xmlStrEqual(prop, (const xmlChar *) "yes")) {
1263 style->standalone = 1;
1264 } else if (xmlStrEqual(prop, (const xmlChar *) "no")) {
1265 style->standalone = 0;
1266 } else {
1268 "invalid value for standalone: %s\n", prop);
1269 style->errors++;
1270 }
1271 xmlFree(prop);
1272 }
1273
1274 prop = xmlGetNsProp(cur, (const xmlChar *) "indent", NULL);
1275 if (prop != NULL) {
1276 if (xmlStrEqual(prop, (const xmlChar *) "yes")) {
1277 style->indent = 1;
1278 } else if (xmlStrEqual(prop, (const xmlChar *) "no")) {
1279 style->indent = 0;
1280 } else {
1282 "invalid value for indent: %s\n", prop);
1283 style->errors++;
1284 }
1285 xmlFree(prop);
1286 }
1287
1288 prop = xmlGetNsProp(cur, (const xmlChar *) "omit-xml-declaration", NULL);
1289 if (prop != NULL) {
1290 if (xmlStrEqual(prop, (const xmlChar *) "yes")) {
1291 style->omitXmlDeclaration = 1;
1292 } else if (xmlStrEqual(prop, (const xmlChar *) "no")) {
1293 style->omitXmlDeclaration = 0;
1294 } else {
1296 "invalid value for omit-xml-declaration: %s\n",
1297 prop);
1298 style->errors++;
1299 }
1300 xmlFree(prop);
1301 }
1302
1303 elements = xmlGetNsProp(cur, (const xmlChar *) "cdata-section-elements",
1304 NULL);
1305 if (elements != NULL) {
1306 if (style->cdataSection == NULL)
1307 style->cdataSection = xmlHashCreate(10);
1308 if (style->cdataSection == NULL) {
1309 xmlFree(elements);
1310 return;
1311 }
1312
1313 element = elements;
1314 while (*element != 0) {
1315 while (IS_BLANK(*element))
1316 element++;
1317 if (*element == 0)
1318 break;
1319 end = element;
1320 while ((*end != 0) && (!IS_BLANK(*end)))
1321 end++;
1323 if (element) {
1324#ifdef WITH_XSLT_DEBUG_PARSING
1326 "add cdata section output element %s\n",
1327 element);
1328#endif
1329 if (xmlValidateQName(BAD_CAST element, 0) != 0) {
1331 "Attribute 'cdata-section-elements': The value "
1332 "'%s' is not a valid QName.\n", element);
1334 style->errors++;
1335 } else {
1336 const xmlChar *URI;
1337
1338 /*
1339 * TODO: Don't use xsltGetQNameURI().
1340 */
1341 URI = xsltGetQNameURI(cur, &element);
1342 if (element == NULL) {
1343 /*
1344 * TODO: We'll report additionally an error
1345 * via the stylesheet's error handling.
1346 */
1348 "Attribute 'cdata-section-elements': "
1349 "Not a valid QName.\n");
1350 style->errors++;
1351 } else {
1352 xmlNsPtr ns;
1353
1354 /*
1355 * XSLT-1.0 "Each QName is expanded into an
1356 * expanded-name using the namespace declarations in
1357 * effect on the xsl:output element in which the QName
1358 * occurs; if there is a default namespace, it is used
1359 * for QNames that do not have a prefix"
1360 * NOTE: Fix of bug #339570.
1361 */
1362 if (URI == NULL) {
1363 ns = xmlSearchNs(style->doc, cur, NULL);
1364 if (ns != NULL)
1365 URI = ns->href;
1366 }
1367 xmlHashAddEntry2(style->cdataSection, element, URI,
1368 (void *) "cdata");
1370 }
1371 }
1372 }
1373 element = end;
1374 }
1375 xmlFree(elements);
1376 }
1377
1378 prop = xmlGetNsProp(cur, (const xmlChar *) "media-type", NULL);
1379 if (prop != NULL) {
1380 if (style->mediaType)
1381 xmlFree(style->mediaType);
1382 style->mediaType = prop;
1383 }
1384 if (cur->children != NULL) {
1385 xsltParseContentError(style, cur->children);
1386 }
1387}
1388
1404static void
1406{
1407 xmlChar *prop;
1410
1411 if ((cur == NULL) || (style == NULL) || (cur->type != XML_ELEMENT_NODE))
1412 return;
1413
1414 format = style->decimalFormat;
1415
1416 prop = xmlGetNsProp(cur, BAD_CAST("name"), NULL);
1417 if (prop != NULL) {
1418 const xmlChar *nsUri;
1419
1420 if (xmlValidateQName(prop, 0) != 0) {
1422 "xsl:decimal-format: Invalid QName '%s'.\n", prop);
1423 style->warnings++;
1424 xmlFree(prop);
1425 return;
1426 }
1427 /*
1428 * TODO: Don't use xsltGetQNameURI().
1429 */
1430 nsUri = xsltGetQNameURI(cur, &prop);
1431 if (prop == NULL) {
1432 style->warnings++;
1433 return;
1434 }
1436 if (format != NULL) {
1438 "xsltParseStylestyleDecimalFormat: %s already exists\n", prop);
1439 style->warnings++;
1440 xmlFree(prop);
1441 return;
1442 }
1443 format = xsltNewDecimalFormat(nsUri, prop);
1444 if (format == NULL) {
1446 "xsltParseStylestyleDecimalFormat: failed creating new decimal-format\n");
1447 style->errors++;
1448 xmlFree(prop);
1449 return;
1450 }
1451 /* Append new decimal-format structure */
1452 for (iter = style->decimalFormat; iter->next; iter = iter->next)
1453 ;
1454 if (iter)
1455 iter->next = format;
1456 }
1457
1458 prop = xmlGetNsProp(cur, (const xmlChar *)"decimal-separator", NULL);
1459 if (prop != NULL) {
1460 if (format->decimalPoint != NULL) xmlFree(format->decimalPoint);
1461 format->decimalPoint = prop;
1462 }
1463
1464 prop = xmlGetNsProp(cur, (const xmlChar *)"grouping-separator", NULL);
1465 if (prop != NULL) {
1466 if (format->grouping != NULL) xmlFree(format->grouping);
1467 format->grouping = prop;
1468 }
1469
1470 prop = xmlGetNsProp(cur, (const xmlChar *)"infinity", NULL);
1471 if (prop != NULL) {
1472 if (format->infinity != NULL) xmlFree(format->infinity);
1473 format->infinity = prop;
1474 }
1475
1476 prop = xmlGetNsProp(cur, (const xmlChar *)"minus-sign", NULL);
1477 if (prop != NULL) {
1478 if (format->minusSign != NULL) xmlFree(format->minusSign);
1479 format->minusSign = prop;
1480 }
1481
1482 prop = xmlGetNsProp(cur, (const xmlChar *)"NaN", NULL);
1483 if (prop != NULL) {
1484 if (format->noNumber != NULL) xmlFree(format->noNumber);
1485 format->noNumber = prop;
1486 }
1487
1488 prop = xmlGetNsProp(cur, (const xmlChar *)"percent", NULL);
1489 if (prop != NULL) {
1490 if (format->percent != NULL) xmlFree(format->percent);
1491 format->percent = prop;
1492 }
1493
1494 prop = xmlGetNsProp(cur, (const xmlChar *)"per-mille", NULL);
1495 if (prop != NULL) {
1496 if (format->permille != NULL) xmlFree(format->permille);
1497 format->permille = prop;
1498 }
1499
1500 prop = xmlGetNsProp(cur, (const xmlChar *)"zero-digit", NULL);
1501 if (prop != NULL) {
1502 if (format->zeroDigit != NULL) xmlFree(format->zeroDigit);
1503 format->zeroDigit = prop;
1504 }
1505
1506 prop = xmlGetNsProp(cur, (const xmlChar *)"digit", NULL);
1507 if (prop != NULL) {
1508 if (format->digit != NULL) xmlFree(format->digit);
1509 format->digit = prop;
1510 }
1511
1512 prop = xmlGetNsProp(cur, (const xmlChar *)"pattern-separator", NULL);
1513 if (prop != NULL) {
1514 if (format->patternSeparator != NULL) xmlFree(format->patternSeparator);
1515 format->patternSeparator = prop;
1516 }
1517 if (cur->children != NULL) {
1518 xsltParseContentError(style, cur->children);
1519 }
1520}
1521
1531static void
1533 xmlChar *elements;
1534 xmlChar *element, *end;
1535
1536 if ((cur == NULL) || (style == NULL) || (cur->type != XML_ELEMENT_NODE))
1537 return;
1538
1539 elements = xmlGetNsProp(cur, (const xmlChar *)"elements", NULL);
1540 if (elements == NULL) {
1542 "xsltParseStylesheetPreserveSpace: missing elements attribute\n");
1543 if (style != NULL) style->warnings++;
1544 return;
1545 }
1546
1547 if (style->stripSpaces == NULL)
1548 style->stripSpaces = xmlHashCreate(10);
1549 if (style->stripSpaces == NULL) {
1550 xmlFree(elements);
1551 return;
1552 }
1553
1554 element = elements;
1555 while (*element != 0) {
1556 while (IS_BLANK(*element)) element++;
1557 if (*element == 0)
1558 break;
1559 end = element;
1560 while ((*end != 0) && (!IS_BLANK(*end))) end++;
1562 if (element) {
1563#ifdef WITH_XSLT_DEBUG_PARSING
1565 "add preserved space element %s\n", element);
1566#endif
1567 if (xmlStrEqual(element, (const xmlChar *)"*")) {
1568 style->stripAll = -1;
1569 } else {
1570 const xmlChar *URI;
1571
1572 /*
1573 * TODO: Don't use xsltGetQNameURI().
1574 */
1575 URI = xsltGetQNameURI(cur, &element);
1576
1577 xmlHashAddEntry2(style->stripSpaces, element, URI,
1578 (xmlChar *) "preserve");
1579 }
1581 }
1582 element = end;
1583 }
1584 xmlFree(elements);
1585 if (cur->children != NULL) {
1586 xsltParseContentError(style, cur->children);
1587 }
1588}
1589
1590#ifdef XSLT_REFACTORED
1591#else
1606static void
1608 int isXsltElem) {
1610 xmlChar *prefix, *end;
1611
1612 if ((cur == NULL) || (style == NULL) || (cur->type != XML_ELEMENT_NODE))
1613 return;
1614
1615 if (isXsltElem) {
1616 /* For xsl:stylesheet/xsl:transform. */
1617 prefixes = xmlGetNsProp(cur,
1618 (const xmlChar *)"extension-element-prefixes", NULL);
1619 } else {
1620 /* For literal result elements and extension instructions. */
1621 prefixes = xmlGetNsProp(cur,
1622 (const xmlChar *)"extension-element-prefixes", XSLT_NAMESPACE);
1623 }
1624 if (prefixes == NULL) {
1625 return;
1626 }
1627
1628 prefix = prefixes;
1629 while (*prefix != 0) {
1630 while (IS_BLANK(*prefix)) prefix++;
1631 if (*prefix == 0)
1632 break;
1633 end = prefix;
1634 while ((*end != 0) && (!IS_BLANK(*end))) end++;
1636 if (prefix) {
1637 xmlNsPtr ns;
1638
1639 if (xmlStrEqual(prefix, (const xmlChar *)"#default"))
1640 ns = xmlSearchNs(style->doc, cur, NULL);
1641 else
1642 ns = xmlSearchNs(style->doc, cur, prefix);
1643 if (ns == NULL) {
1645 "xsl:extension-element-prefix : undefined namespace %s\n",
1646 prefix);
1647 if (style != NULL) style->warnings++;
1648 } else {
1649#ifdef WITH_XSLT_DEBUG_PARSING
1651 "add extension prefix %s\n", prefix);
1652#endif
1654 }
1655 xmlFree(prefix);
1656 }
1657 prefix = end;
1658 }
1660}
1661#endif /* else of XSLT_REFACTORED */
1662
1672static void
1674 xmlChar *elements;
1675 xmlChar *element, *end;
1676
1677 if ((cur == NULL) || (style == NULL) || (cur->type != XML_ELEMENT_NODE))
1678 return;
1679
1680 if (style->stripSpaces == NULL)
1681 style->stripSpaces = xmlHashCreate(10);
1682 if (style->stripSpaces == NULL)
1683 return;
1684
1685 elements = xmlGetNsProp(cur, (const xmlChar *)"elements", NULL);
1686 if (elements == NULL) {
1688 "xsltParseStylesheetStripSpace: missing elements attribute\n");
1689 if (style != NULL) style->warnings++;
1690 return;
1691 }
1692
1693 element = elements;
1694 while (*element != 0) {
1695 while (IS_BLANK(*element)) element++;
1696 if (*element == 0)
1697 break;
1698 end = element;
1699 while ((*end != 0) && (!IS_BLANK(*end))) end++;
1701 if (element) {
1702#ifdef WITH_XSLT_DEBUG_PARSING
1704 "add stripped space element %s\n", element);
1705#endif
1706 if (xmlStrEqual(element, (const xmlChar *)"*")) {
1707 style->stripAll = 1;
1708 } else {
1709 const xmlChar *URI;
1710
1711 /*
1712 * TODO: Don't use xsltGetQNameURI().
1713 */
1714 URI = xsltGetQNameURI(cur, &element);
1715
1716 xmlHashAddEntry2(style->stripSpaces, element, URI,
1717 (xmlChar *) "strip");
1718 }
1720 }
1721 element = end;
1722 }
1723 xmlFree(elements);
1724 if (cur->children != NULL) {
1725 xsltParseContentError(style, cur->children);
1726 }
1727}
1728
1729#ifdef XSLT_REFACTORED
1730#else
1742static int
1744 int isXsltElem)
1745{
1746 int nb = 0;
1748 xmlChar *prefix, *end;
1749
1750 if ((cur == NULL) || (style == NULL) || (cur->type != XML_ELEMENT_NODE))
1751 return(0);
1752
1753 if (isXsltElem)
1754 prefixes = xmlGetNsProp(cur,
1755 (const xmlChar *)"exclude-result-prefixes", NULL);
1756 else
1757 prefixes = xmlGetNsProp(cur,
1758 (const xmlChar *)"exclude-result-prefixes", XSLT_NAMESPACE);
1759
1760 if (prefixes == NULL) {
1761 return(0);
1762 }
1763
1764 prefix = prefixes;
1765 while (*prefix != 0) {
1766 while (IS_BLANK(*prefix)) prefix++;
1767 if (*prefix == 0)
1768 break;
1769 end = prefix;
1770 while ((*end != 0) && (!IS_BLANK(*end))) end++;
1772 if (prefix) {
1773 xmlNsPtr ns;
1774
1775 if (xmlStrEqual(prefix, (const xmlChar *)"#default"))
1776 ns = xmlSearchNs(style->doc, cur, NULL);
1777 else
1778 ns = xmlSearchNs(style->doc, cur, prefix);
1779 if (ns == NULL) {
1781 "xsl:exclude-result-prefixes : undefined namespace %s\n",
1782 prefix);
1783 if (style != NULL) style->warnings++;
1784 } else {
1785 if (exclPrefixPush(style, (xmlChar *) ns->href) >= 0) {
1786#ifdef WITH_XSLT_DEBUG_PARSING
1788 "exclude result prefix %s\n", prefix);
1789#endif
1790 nb++;
1791 }
1792 }
1793 xmlFree(prefix);
1794 }
1795 prefix = end;
1796 }
1798 return(nb);
1799}
1800#endif /* else of XSLT_REFACTORED */
1801
1802#ifdef XSLT_REFACTORED
1803
1804/*
1805* xsltTreeEnsureXMLDecl:
1806* @doc: the doc
1807*
1808* BIG NOTE:
1809* This was copy&pasted from Libxml2's xmlTreeEnsureXMLDecl() in "tree.c".
1810* Ensures that there is an XML namespace declaration on the doc.
1811*
1812* Returns the XML ns-struct or NULL on API and internal errors.
1813*/
1814static xmlNsPtr
1815xsltTreeEnsureXMLDecl(xmlDocPtr doc)
1816{
1817 if (doc == NULL)
1818 return (NULL);
1819 if (doc->oldNs != NULL)
1820 return (doc->oldNs);
1821 {
1822 xmlNsPtr ns;
1823 ns = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
1824 if (ns == NULL) {
1826 "xsltTreeEnsureXMLDecl: Failed to allocate "
1827 "the XML namespace.\n");
1828 return (NULL);
1829 }
1830 memset(ns, 0, sizeof(xmlNs));
1831 ns->type = XML_LOCAL_NAMESPACE;
1832 /*
1833 * URGENT TODO: revisit this.
1834 */
1835#ifdef LIBXML_NAMESPACE_DICT
1836 if (doc->dict)
1837 ns->href = xmlDictLookup(doc->dict, XML_XML_NAMESPACE, -1);
1838 else
1839 ns->href = xmlStrdup(XML_XML_NAMESPACE);
1840#else
1841 ns->href = xmlStrdup(XML_XML_NAMESPACE);
1842#endif
1843 ns->prefix = xmlStrdup((const xmlChar *)"xml");
1844 doc->oldNs = ns;
1845 return (ns);
1846 }
1847}
1848
1849/*
1850* xsltTreeAcquireStoredNs:
1851* @doc: the doc
1852* @nsName: the namespace name
1853* @prefix: the prefix
1854*
1855* BIG NOTE:
1856* This was copy&pasted from Libxml2's xmlDOMWrapStoreNs() in "tree.c".
1857* Creates or reuses an xmlNs struct on doc->oldNs with
1858* the given prefix and namespace name.
1859*
1860* Returns the aquired ns struct or NULL in case of an API
1861* or internal error.
1862*/
1863static xmlNsPtr
1864xsltTreeAcquireStoredNs(xmlDocPtr doc,
1865 const xmlChar *nsName,
1866 const xmlChar *prefix)
1867{
1868 xmlNsPtr ns;
1869
1870 if (doc == NULL)
1871 return (NULL);
1872 if (doc->oldNs != NULL)
1873 ns = doc->oldNs;
1874 else
1875 ns = xsltTreeEnsureXMLDecl(doc);
1876 if (ns == NULL)
1877 return (NULL);
1878 if (ns->next != NULL) {
1879 /* Reuse. */
1880 ns = ns->next;
1881 while (ns != NULL) {
1882 if ((ns->prefix == NULL) != (prefix == NULL)) {
1883 /* NOP */
1884 } else if (prefix == NULL) {
1885 if (xmlStrEqual(ns->href, nsName))
1886 return (ns);
1887 } else {
1888 if ((ns->prefix[0] == prefix[0]) &&
1890 xmlStrEqual(ns->href, nsName))
1891 return (ns);
1892
1893 }
1894 if (ns->next == NULL)
1895 break;
1896 ns = ns->next;
1897 }
1898 }
1899 /* Create. */
1900 ns->next = xmlNewNs(NULL, nsName, prefix);
1901 return (ns->next);
1902}
1903
1910static int
1911xsltLREBuildEffectiveNs(xsltCompilerCtxtPtr cctxt,
1912 xmlNodePtr elem)
1913{
1914 xmlNsPtr ns;
1915 xsltNsAliasPtr alias;
1916
1917 if ((cctxt == NULL) || (elem == NULL))
1918 return(-1);
1919 if ((cctxt->nsAliases == NULL) || (! cctxt->hasNsAliases))
1920 return(0);
1921
1922 alias = cctxt->nsAliases;
1923 while (alias != NULL) {
1924 if ( /* If both namespaces are NULL... */
1925 ( (elem->ns == NULL) &&
1926 ((alias->literalNs == NULL) ||
1927 (alias->literalNs->href == NULL)) ) ||
1928 /* ... or both namespace are equal */
1929 ( (elem->ns != NULL) &&
1930 (alias->literalNs != NULL) &&
1931 xmlStrEqual(elem->ns->href, alias->literalNs->href) ) )
1932 {
1933 if ((alias->targetNs != NULL) &&
1934 (alias->targetNs->href != NULL))
1935 {
1936 /*
1937 * Convert namespace.
1938 */
1939 if (elem->doc == alias->docOfTargetNs) {
1940 /*
1941 * This is the nice case: same docs.
1942 * This will eventually assign a ns-decl which
1943 * is shadowed, but this has no negative effect on
1944 * the generation of the result tree.
1945 */
1946 elem->ns = alias->targetNs;
1947 } else {
1948 /*
1949 * This target xmlNs originates from a different
1950 * stylesheet tree. Try to locate it in the
1951 * in-scope namespaces.
1952 * OPTIMIZE TODO: Use the compiler-node-info inScopeNs.
1953 */
1954 ns = xmlSearchNs(elem->doc, elem,
1955 alias->targetNs->prefix);
1956 /*
1957 * If no matching ns-decl found, then assign a
1958 * ns-decl stored in xmlDoc.
1959 */
1960 if ((ns == NULL) ||
1961 (! xmlStrEqual(ns->href, alias->targetNs->href)))
1962 {
1963 /*
1964 * BIG NOTE: The use of xsltTreeAcquireStoredNs()
1965 * is not very efficient, but currently I don't
1966 * see an other way of *safely* changing a node's
1967 * namespace, since the xmlNs struct in
1968 * alias->targetNs might come from an other
1969 * stylesheet tree. So we need to anchor it in the
1970 * current document, without adding it to the tree,
1971 * which would otherwise change the in-scope-ns
1972 * semantic of the tree.
1973 */
1974 ns = xsltTreeAcquireStoredNs(elem->doc,
1975 alias->targetNs->href,
1976 alias->targetNs->prefix);
1977
1978 if (ns == NULL) {
1979 xsltTransformError(NULL, cctxt->style, elem,
1980 "Internal error in "
1981 "xsltLREBuildEffectiveNs(): "
1982 "failed to acquire a stored "
1983 "ns-declaration.\n");
1984 cctxt->style->errors++;
1985 return(-1);
1986
1987 }
1988 }
1989 elem->ns = ns;
1990 }
1991 } else {
1992 /*
1993 * Move into or leave in the NULL namespace.
1994 */
1995 elem->ns = NULL;
1996 }
1997 break;
1998 }
1999 alias = alias->next;
2000 }
2001 /*
2002 * Same with attributes of literal result elements.
2003 */
2004 if (elem->properties != NULL) {
2005 xmlAttrPtr attr = elem->properties;
2006
2007 while (attr != NULL) {
2008 if (attr->ns == NULL) {
2009 attr = attr->next;
2010 continue;
2011 }
2012 alias = cctxt->nsAliases;
2013 while (alias != NULL) {
2014 if ( /* If both namespaces are NULL... */
2015 ( (elem->ns == NULL) &&
2016 ((alias->literalNs == NULL) ||
2017 (alias->literalNs->href == NULL)) ) ||
2018 /* ... or both namespace are equal */
2019 ( (elem->ns != NULL) &&
2020 (alias->literalNs != NULL) &&
2021 xmlStrEqual(elem->ns->href, alias->literalNs->href) ) )
2022 {
2023 if ((alias->targetNs != NULL) &&
2024 (alias->targetNs->href != NULL))
2025 {
2026 if (elem->doc == alias->docOfTargetNs) {
2027 elem->ns = alias->targetNs;
2028 } else {
2029 ns = xmlSearchNs(elem->doc, elem,
2030 alias->targetNs->prefix);
2031 if ((ns == NULL) ||
2032 (! xmlStrEqual(ns->href, alias->targetNs->href)))
2033 {
2034 ns = xsltTreeAcquireStoredNs(elem->doc,
2035 alias->targetNs->href,
2036 alias->targetNs->prefix);
2037
2038 if (ns == NULL) {
2039 xsltTransformError(NULL, cctxt->style, elem,
2040 "Internal error in "
2041 "xsltLREBuildEffectiveNs(): "
2042 "failed to acquire a stored "
2043 "ns-declaration.\n");
2044 cctxt->style->errors++;
2045 return(-1);
2046
2047 }
2048 }
2049 elem->ns = ns;
2050 }
2051 } else {
2052 /*
2053 * Move into or leave in the NULL namespace.
2054 */
2055 elem->ns = NULL;
2056 }
2057 break;
2058 }
2059 alias = alias->next;
2060 }
2061
2062 attr = attr->next;
2063 }
2064 }
2065 return(0);
2066}
2067
2081static int
2082xsltLREBuildEffectiveNsNodes(xsltCompilerCtxtPtr cctxt,
2083 xsltStyleItemLRElementInfoPtr item,
2084 xmlNodePtr elem,
2085 int isLRE)
2086{
2087 xmlNsPtr ns, tmpns;
2088 xsltEffectiveNsPtr effNs, lastEffNs = NULL;
2089 int i, j, holdByElem;
2090 xsltPointerListPtr extElemNs = cctxt->inode->extElemNs;
2091 xsltPointerListPtr exclResultNs = cctxt->inode->exclResultNs;
2092
2093 if ((cctxt == NULL) || (cctxt->inode == NULL) || (elem == NULL) ||
2094 (item == NULL) || (item->effectiveNs != NULL))
2095 return(-1);
2096
2097 if (item->inScopeNs == NULL)
2098 return(0);
2099
2100 extElemNs = cctxt->inode->extElemNs;
2101 exclResultNs = cctxt->inode->exclResultNs;
2102
2103 for (i = 0; i < item->inScopeNs->totalNumber; i++) {
2104 ns = item->inScopeNs->list[i];
2105 /*
2106 * Skip namespaces designated as excluded namespaces
2107 * -------------------------------------------------
2108 *
2109 * XSLT-20 TODO: In XSLT 2.0 we need to keep namespaces
2110 * which are target namespaces of namespace-aliases
2111 * regardless if designated as excluded.
2112 *
2113 * Exclude the XSLT namespace.
2114 */
2115 if (xmlStrEqual(ns->href, XSLT_NAMESPACE))
2116 goto skip_ns;
2117
2118 /*
2119 * Apply namespace aliasing
2120 * ------------------------
2121 *
2122 * SPEC XSLT 2.0
2123 * "- A namespace node whose string value is a literal namespace
2124 * URI is not copied to the result tree.
2125 * - A namespace node whose string value is a target namespace URI
2126 * is copied to the result tree, whether or not the URI
2127 * identifies an excluded namespace."
2128 *
2129 * NOTE: The ns-aliasing machanism is non-cascading.
2130 * (checked with Saxon, Xalan and MSXML .NET).
2131 * URGENT TODO: is style->nsAliases the effective list of
2132 * ns-aliases, or do we need to lookup the whole
2133 * import-tree?
2134 * TODO: Get rid of import-tree lookup.
2135 */
2136 if (cctxt->hasNsAliases) {
2137 xsltNsAliasPtr alias;
2138 /*
2139 * First check for being a target namespace.
2140 */
2141 alias = cctxt->nsAliases;
2142 do {
2143 /*
2144 * TODO: Is xmlns="" handled already?
2145 */
2146 if ((alias->targetNs != NULL) &&
2147 (xmlStrEqual(alias->targetNs->href, ns->href)))
2148 {
2149 /*
2150 * Recognized as a target namespace; use it regardless
2151 * if excluded otherwise.
2152 */
2153 goto add_effective_ns;
2154 }
2155 alias = alias->next;
2156 } while (alias != NULL);
2157
2158 alias = cctxt->nsAliases;
2159 do {
2160 /*
2161 * TODO: Is xmlns="" handled already?
2162 */
2163 if ((alias->literalNs != NULL) &&
2164 (xmlStrEqual(alias->literalNs->href, ns->href)))
2165 {
2166 /*
2167 * Recognized as an namespace alias; do not use it.
2168 */
2169 goto skip_ns;
2170 }
2171 alias = alias->next;
2172 } while (alias != NULL);
2173 }
2174
2175 /*
2176 * Exclude excluded result namespaces.
2177 */
2178 if (exclResultNs) {
2179 for (j = 0; j < exclResultNs->number; j++)
2180 if (xmlStrEqual(ns->href, BAD_CAST exclResultNs->items[j]))
2181 goto skip_ns;
2182 }
2183 /*
2184 * Exclude extension-element namespaces.
2185 */
2186 if (extElemNs) {
2187 for (j = 0; j < extElemNs->number; j++)
2188 if (xmlStrEqual(ns->href, BAD_CAST extElemNs->items[j]))
2189 goto skip_ns;
2190 }
2191
2192add_effective_ns:
2193 /*
2194 * OPTIMIZE TODO: This information may not be needed.
2195 */
2196 if (isLRE && (elem->nsDef != NULL)) {
2197 holdByElem = 0;
2198 tmpns = elem->nsDef;
2199 do {
2200 if (tmpns == ns) {
2201 holdByElem = 1;
2202 break;
2203 }
2204 tmpns = tmpns->next;
2205 } while (tmpns != NULL);
2206 } else
2207 holdByElem = 0;
2208
2209
2210 /*
2211 * Add the effective namespace declaration.
2212 */
2213 effNs = (xsltEffectiveNsPtr) xmlMalloc(sizeof(xsltEffectiveNs));
2214 if (effNs == NULL) {
2215 xsltTransformError(NULL, cctxt->style, elem,
2216 "Internal error in xsltLREBuildEffectiveNs(): "
2217 "failed to allocate memory.\n");
2218 cctxt->style->errors++;
2219 return(-1);
2220 }
2221 if (cctxt->psData->effectiveNs == NULL) {
2222 cctxt->psData->effectiveNs = effNs;
2223 effNs->nextInStore = NULL;
2224 } else {
2225 effNs->nextInStore = cctxt->psData->effectiveNs;
2226 cctxt->psData->effectiveNs = effNs;
2227 }
2228
2229 effNs->next = NULL;
2230 effNs->prefix = ns->prefix;
2231 effNs->nsName = ns->href;
2232 effNs->holdByElem = holdByElem;
2233
2234 if (lastEffNs == NULL)
2235 item->effectiveNs = effNs;
2236 else
2237 lastEffNs->next = effNs;
2238 lastEffNs = effNs;
2239
2240skip_ns:
2241 {}
2242 }
2243 return(0);
2244}
2245
2246
2254static int
2255xsltLREInfoCreate(xsltCompilerCtxtPtr cctxt,
2256 xmlNodePtr elem,
2257 int isLRE)
2258{
2259 xsltStyleItemLRElementInfoPtr item;
2260
2261 if ((cctxt == NULL) || (cctxt->inode == NULL))
2262 return(-1);
2263
2264 item = (xsltStyleItemLRElementInfoPtr)
2265 xmlMalloc(sizeof(xsltStyleItemLRElementInfo));
2266 if (item == NULL) {
2267 xsltTransformError(NULL, cctxt->style, NULL,
2268 "Internal error in xsltLREInfoCreate(): "
2269 "memory allocation failed.\n");
2270 cctxt->style->errors++;
2271 return(-1);
2272 }
2273 memset(item, 0, sizeof(xsltStyleItemLRElementInfo));
2274 item->type = XSLT_FUNC_LITERAL_RESULT_ELEMENT;
2275 /*
2276 * Store it in the stylesheet.
2277 */
2278 item->next = cctxt->style->preComps;
2279 cctxt->style->preComps = (xsltElemPreCompPtr) item;
2280 /*
2281 * @inScopeNs are used for execution of XPath expressions
2282 * in AVTs.
2283 */
2284 item->inScopeNs = cctxt->inode->inScopeNs;
2285
2286 if (elem)
2287 xsltLREBuildEffectiveNsNodes(cctxt, item, elem, isLRE);
2288
2289 cctxt->inode->litResElemInfo = item;
2290 cctxt->inode->nsChanged = 0;
2291 cctxt->maxLREs++;
2292 return(0);
2293}
2294
2303static xsltVarInfoPtr
2304xsltCompilerVarInfoPush(xsltCompilerCtxtPtr cctxt,
2305 xmlNodePtr inst,
2306 const xmlChar *name,
2307 const xmlChar *nsName)
2308{
2309 xsltVarInfoPtr ivar;
2310
2311 if ((cctxt->ivar != NULL) && (cctxt->ivar->next != NULL)) {
2312 ivar = cctxt->ivar->next;
2313 } else if ((cctxt->ivar == NULL) && (cctxt->ivars != NULL)) {
2314 ivar = cctxt->ivars;
2315 } else {
2316 ivar = (xsltVarInfoPtr) xmlMalloc(sizeof(xsltVarInfo));
2317 if (ivar == NULL) {
2318 xsltTransformError(NULL, cctxt->style, inst,
2319 "xsltParseInScopeVarPush: xmlMalloc() failed!\n");
2320 cctxt->style->errors++;
2321 return(NULL);
2322 }
2323 /* memset(retVar, 0, sizeof(xsltInScopeVar)); */
2324 if (cctxt->ivars == NULL) {
2325 cctxt->ivars = ivar;
2326 ivar->prev = NULL;
2327 } else {
2328 cctxt->ivar->next = ivar;
2329 ivar->prev = cctxt->ivar;
2330 }
2331 cctxt->ivar = ivar;
2332 ivar->next = NULL;
2333 }
2334 ivar->depth = cctxt->depth;
2335 ivar->name = name;
2336 ivar->nsName = nsName;
2337 return(ivar);
2338}
2339
2347static void
2348xsltCompilerVarInfoPop(xsltCompilerCtxtPtr cctxt)
2349{
2350
2351 while ((cctxt->ivar != NULL) &&
2352 (cctxt->ivar->depth > cctxt->depth))
2353 {
2354 cctxt->ivar = cctxt->ivar->prev;
2355 }
2356}
2357
2358/*
2359* xsltCompilerNodePush:
2360*
2361* @cctxt: the compilation context
2362* @node: the node to be pushed (this can also be the doc-node)
2363*
2364*
2365*
2366* Returns the current node info structure or
2367* NULL in case of an internal error.
2368*/
2369static xsltCompilerNodeInfoPtr
2370xsltCompilerNodePush(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)
2371{
2372 xsltCompilerNodeInfoPtr inode, iprev;
2373
2374 if ((cctxt->inode != NULL) && (cctxt->inode->next != NULL)) {
2375 inode = cctxt->inode->next;
2376 } else if ((cctxt->inode == NULL) && (cctxt->inodeList != NULL)) {
2377 inode = cctxt->inodeList;
2378 } else {
2379 /*
2380 * Create a new node-info.
2381 */
2382 inode = (xsltCompilerNodeInfoPtr)
2383 xmlMalloc(sizeof(xsltCompilerNodeInfo));
2384 if (inode == NULL) {
2385 xsltTransformError(NULL, cctxt->style, NULL,
2386 "xsltCompilerNodePush: malloc failed.\n");
2387 return(NULL);
2388 }
2389 memset(inode, 0, sizeof(xsltCompilerNodeInfo));
2390 if (cctxt->inodeList == NULL)
2391 cctxt->inodeList = inode;
2392 else {
2393 cctxt->inodeLast->next = inode;
2394 inode->prev = cctxt->inodeLast;
2395 }
2396 cctxt->inodeLast = inode;
2397 cctxt->maxNodeInfos++;
2398 if (cctxt->inode == NULL) {
2399 cctxt->inode = inode;
2400 /*
2401 * Create an initial literal result element info for
2402 * the root of the stylesheet.
2403 */
2404 xsltLREInfoCreate(cctxt, NULL, 0);
2405 }
2406 }
2407 cctxt->depth++;
2408 cctxt->inode = inode;
2409 /*
2410 * REVISIT TODO: Keep the reset always complete.
2411 * NOTE: Be carefull with the @node, since it might be
2412 * a doc-node.
2413 */
2414 inode->node = node;
2415 inode->depth = cctxt->depth;
2416 inode->templ = NULL;
2417 inode->category = XSLT_ELEMENT_CATEGORY_XSLT;
2418 inode->type = 0;
2419 inode->item = NULL;
2420 inode->curChildType = 0;
2421 inode->extContentHandled = 0;
2422 inode->isRoot = 0;
2423
2424 if (inode->prev != NULL) {
2425 iprev = inode->prev;
2426 /*
2427 * Inherit the following information:
2428 * ---------------------------------
2429 *
2430 * In-scope namespaces
2431 */
2432 inode->inScopeNs = iprev->inScopeNs;
2433 /*
2434 * Info for literal result elements
2435 */
2436 inode->litResElemInfo = iprev->litResElemInfo;
2437 inode->nsChanged = iprev->nsChanged;
2438 /*
2439 * Excluded result namespaces
2440 */
2441 inode->exclResultNs = iprev->exclResultNs;
2442 /*
2443 * Extension instruction namespaces
2444 */
2445 inode->extElemNs = iprev->extElemNs;
2446 /*
2447 * Whitespace preservation
2448 */
2449 inode->preserveWhitespace = iprev->preserveWhitespace;
2450 /*
2451 * Forwards-compatible mode
2452 */
2453 inode->forwardsCompat = iprev->forwardsCompat;
2454 } else {
2455 inode->inScopeNs = NULL;
2456 inode->exclResultNs = NULL;
2457 inode->extElemNs = NULL;
2458 inode->preserveWhitespace = 0;
2459 inode->forwardsCompat = 0;
2460 }
2461
2462 return(inode);
2463}
2464
2465/*
2466* xsltCompilerNodePop:
2467*
2468* @cctxt: the compilation context
2469* @node: the node to be pushed (this can also be the doc-node)
2470*
2471* Pops the current node info.
2472*/
2473static void
2474xsltCompilerNodePop(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)
2475{
2476 if (cctxt->inode == NULL) {
2478 "xsltCompilerNodePop: Top-node mismatch.\n");
2479 return;
2480 }
2481 /*
2482 * NOTE: Be carefull with the @node, since it might be
2483 * a doc-node.
2484 */
2485 if (cctxt->inode->node != node) {
2487 "xsltCompilerNodePop: Node mismatch.\n");
2488 goto mismatch;
2489 }
2490 if (cctxt->inode->depth != cctxt->depth) {
2492 "xsltCompilerNodePop: Depth mismatch.\n");
2493 goto mismatch;
2494 }
2495 cctxt->depth--;
2496 /*
2497 * Pop information of variables.
2498 */
2499 if ((cctxt->ivar) && (cctxt->ivar->depth > cctxt->depth))
2500 xsltCompilerVarInfoPop(cctxt);
2501
2502 cctxt->inode = cctxt->inode->prev;
2503 if (cctxt->inode != NULL)
2504 cctxt->inode->curChildType = 0;
2505 return;
2506
2507mismatch:
2508 {
2509 const xmlChar *nsName = NULL, *name = NULL;
2510 const xmlChar *infnsName = NULL, *infname = NULL;
2511
2512 if (node) {
2513 if (node->type == XML_ELEMENT_NODE) {
2514 name = node->name;
2515 if (node->ns != NULL)
2516 nsName = node->ns->href;
2517 else
2518 nsName = BAD_CAST "";
2519 } else {
2520 name = BAD_CAST "#document";
2521 nsName = BAD_CAST "";
2522 }
2523 } else
2524 name = BAD_CAST "Not given";
2525
2526 if (cctxt->inode->node) {
2527 if (node->type == XML_ELEMENT_NODE) {
2528 infname = cctxt->inode->node->name;
2529 if (cctxt->inode->node->ns != NULL)
2530 infnsName = cctxt->inode->node->ns->href;
2531 else
2532 infnsName = BAD_CAST "";
2533 } else {
2534 infname = BAD_CAST "#document";
2535 infnsName = BAD_CAST "";
2536 }
2537 } else
2538 infname = BAD_CAST "Not given";
2539
2540
2542 "xsltCompilerNodePop: Given : '%s' URI '%s'\n",
2543 name, nsName);
2545 "xsltCompilerNodePop: Expected: '%s' URI '%s'\n",
2546 infname, infnsName);
2547 }
2548}
2549
2550/*
2551* xsltCompilerBuildInScopeNsList:
2552*
2553* Create and store the list of in-scope namespaces for the given
2554* node in the stylesheet. If there are no changes in the in-scope
2555* namespaces then the last ns-info of the ancestor axis will be returned.
2556* Compilation-time only.
2557*
2558* Returns the ns-info or NULL if there are no namespaces in scope.
2559*/
2560static xsltNsListContainerPtr
2561xsltCompilerBuildInScopeNsList(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)
2562{
2563 xsltNsListContainerPtr nsi = NULL;
2564 xmlNsPtr *list = NULL, ns;
2565 int i, maxns = 5;
2566 /*
2567 * Create a new ns-list for this position in the node-tree.
2568 * xmlGetNsList() will return NULL, if there are no ns-decls in the
2569 * tree. Note that the ns-decl for the XML namespace is not added
2570 * to the resulting list; the XPath module handles the XML namespace
2571 * internally.
2572 */
2573 while (node != NULL) {
2574 if (node->type == XML_ELEMENT_NODE) {
2575 ns = node->nsDef;
2576 while (ns != NULL) {
2577 if (nsi == NULL) {
2578 nsi = (xsltNsListContainerPtr)
2579 xmlMalloc(sizeof(xsltNsListContainer));
2580 if (nsi == NULL) {
2581 xsltTransformError(NULL, cctxt->style, NULL,
2582 "xsltCompilerBuildInScopeNsList: "
2583 "malloc failed!\n");
2584 goto internal_err;
2585 }
2586 memset(nsi, 0, sizeof(xsltNsListContainer));
2587 nsi->list =
2588 (xmlNsPtr *) xmlMalloc(maxns * sizeof(xmlNsPtr));
2589 if (nsi->list == NULL) {
2590 xsltTransformError(NULL, cctxt->style, NULL,
2591 "xsltCompilerBuildInScopeNsList: "
2592 "malloc failed!\n");
2593 goto internal_err;
2594 }
2595 nsi->list[0] = NULL;
2596 }
2597 /*
2598 * Skip shadowed namespace bindings.
2599 */
2600 for (i = 0; i < nsi->totalNumber; i++) {
2601 if ((ns->prefix == nsi->list[i]->prefix) ||
2602 (xmlStrEqual(ns->prefix, nsi->list[i]->prefix)))
2603 break;
2604 }
2605 if (i >= nsi->totalNumber) {
2606 if (nsi->totalNumber +1 >= maxns) {
2607 maxns *= 2;
2608 nsi->list =
2609 (xmlNsPtr *) xmlRealloc(nsi->list,
2610 maxns * sizeof(xmlNsPtr));
2611 if (nsi->list == NULL) {
2612 xsltTransformError(NULL, cctxt->style, NULL,
2613 "xsltCompilerBuildInScopeNsList: "
2614 "realloc failed!\n");
2615 goto internal_err;
2616 }
2617 }
2618 nsi->list[nsi->totalNumber++] = ns;
2619 nsi->list[nsi->totalNumber] = NULL;
2620 }
2621
2622 ns = ns->next;
2623 }
2624 }
2625 node = node->parent;
2626 }
2627 if (nsi == NULL)
2628 return(NULL);
2629 /*
2630 * Move the default namespace to last position.
2631 */
2632 nsi->xpathNumber = nsi->totalNumber;
2633 for (i = 0; i < nsi->totalNumber; i++) {
2634 if (nsi->list[i]->prefix == NULL) {
2635 ns = nsi->list[i];
2636 nsi->list[i] = nsi->list[nsi->totalNumber-1];
2637 nsi->list[nsi->totalNumber-1] = ns;
2638 nsi->xpathNumber--;
2639 break;
2640 }
2641 }
2642 /*
2643 * Store the ns-list in the stylesheet.
2644 */
2645 if (xsltPointerListAddSize(
2646 (xsltPointerListPtr)cctxt->psData->inScopeNamespaces,
2647 (void *) nsi, 5) == -1)
2648 {
2649 xmlFree(nsi);
2650 nsi = NULL;
2651 xsltTransformError(NULL, cctxt->style, NULL,
2652 "xsltCompilerBuildInScopeNsList: failed to add ns-info.\n");
2653 goto internal_err;
2654 }
2655 /*
2656 * Notify of change in status wrt namespaces.
2657 */
2658 if (cctxt->inode != NULL)
2659 cctxt->inode->nsChanged = 1;
2660
2661 return(nsi);
2662
2663internal_err:
2664 if (list != NULL)
2665 xmlFree(list);
2666 cctxt->style->errors++;
2667 return(NULL);
2668}
2669
2670static int
2671xsltParseNsPrefixList(xsltCompilerCtxtPtr cctxt,
2672 xsltPointerListPtr list,
2673 xmlNodePtr node,
2674 const xmlChar *value)
2675{
2676 xmlChar *cur, *end;
2677 xmlNsPtr ns;
2678
2679 if ((cctxt == NULL) || (value == NULL) || (list == NULL))
2680 return(-1);
2681
2682 list->number = 0;
2683
2684 cur = (xmlChar *) value;
2685 while (*cur != 0) {
2686 while (IS_BLANK(*cur)) cur++;
2687 if (*cur == 0)
2688 break;
2689 end = cur;
2690 while ((*end != 0) && (!IS_BLANK(*end))) end++;
2691 cur = xmlStrndup(cur, end - cur);
2692 if (cur == NULL) {
2693 cur = end;
2694 continue;
2695 }
2696 /*
2697 * TODO: Export and use xmlSearchNsByPrefixStrict()
2698 * in Libxml2, tree.c, since xmlSearchNs() is in most
2699 * cases not efficient and in some cases not correct.
2700 *
2701 * XSLT-2 TODO: XSLT 2.0 allows an additional "#all" value.
2702 */
2703 if ((cur[0] == '#') &&
2704 xmlStrEqual(cur, (const xmlChar *)"#default"))
2705 ns = xmlSearchNs(cctxt->style->doc, node, NULL);
2706 else
2707 ns = xmlSearchNs(cctxt->style->doc, node, cur);
2708
2709 if (ns == NULL) {
2710 /*
2711 * TODO: Better to report the attr-node, otherwise
2712 * the user won't know which attribute was invalid.
2713 */
2714 xsltTransformError(NULL, cctxt->style, node,
2715 "No namespace binding in scope for prefix '%s'.\n", cur);
2716 /*
2717 * XSLT-1.0: "It is an error if there is no namespace
2718 * bound to the prefix on the element bearing the
2719 * exclude-result-prefixes or xsl:exclude-result-prefixes
2720 * attribute."
2721 */
2722 cctxt->style->errors++;
2723 } else {
2724#ifdef WITH_XSLT_DEBUG_PARSING
2726 "resolved prefix '%s'\n", cur);
2727#endif
2728 /*
2729 * Note that we put the namespace name into the dict.
2730 */
2731 if (xsltPointerListAddSize(list,
2732 (void *) xmlDictLookup(cctxt->style->dict,
2733 ns->href, -1), 5) == -1)
2734 {
2735 xmlFree(cur);
2736 goto internal_err;
2737 }
2738 }
2739 xmlFree(cur);
2740
2741 cur = end;
2742 }
2743 return(0);
2744
2745internal_err:
2746 cctxt->style->errors++;
2747 return(-1);
2748}
2749
2761static xsltPointerListPtr
2762xsltCompilerUtilsCreateMergedList(xsltPointerListPtr first,
2763 xsltPointerListPtr second)
2764{
2765 xsltPointerListPtr ret;
2766 size_t num;
2767
2768 if (first)
2769 num = first->number;
2770 else
2771 num = 0;
2772 if (second)
2773 num += second->number;
2774 if (num == 0)
2775 return(NULL);
2776 ret = xsltPointerListCreate(num);
2777 if (ret == NULL)
2778 return(NULL);
2779 /*
2780 * Copy contents.
2781 */
2782 if ((first != NULL) && (first->number != 0)) {
2783 memcpy(ret->items, first->items,
2784 first->number * sizeof(void *));
2785 if ((second != NULL) && (second->number != 0))
2786 memcpy(ret->items + first->number, second->items,
2787 second->number * sizeof(void *));
2788 } else if ((second != NULL) && (second->number != 0))
2789 memcpy(ret->items, (void *) second->items,
2790 second->number * sizeof(void *));
2791 ret->number = num;
2792 return(ret);
2793}
2794
2795/*
2796* xsltParseExclResultPrefixes:
2797*
2798* Create and store the list of in-scope namespaces for the given
2799* node in the stylesheet. If there are no changes in the in-scope
2800* namespaces then the last ns-info of the ancestor axis will be returned.
2801* Compilation-time only.
2802*
2803* Returns the ns-info or NULL if there are no namespaces in scope.
2804*/
2805static xsltPointerListPtr
2806xsltParseExclResultPrefixes(xsltCompilerCtxtPtr cctxt, xmlNodePtr node,
2807 xsltPointerListPtr def,
2808 int instrCategory)
2809{
2810 xsltPointerListPtr list = NULL;
2811 xmlChar *value;
2812 xmlAttrPtr attr;
2813
2814 if ((cctxt == NULL) || (node == NULL))
2815 return(NULL);
2816
2817 if (instrCategory == XSLT_ELEMENT_CATEGORY_XSLT)
2818 attr = xmlHasNsProp(node, BAD_CAST "exclude-result-prefixes", NULL);
2819 else
2820 attr = xmlHasNsProp(node, BAD_CAST "exclude-result-prefixes",
2822 if (attr == NULL)
2823 return(def);
2824
2825 if (attr && (instrCategory == XSLT_ELEMENT_CATEGORY_LRE)) {
2826 /*
2827 * Mark the XSLT attr.
2828 */
2829 attr->psvi = (void *) xsltXSLTAttrMarker;
2830 }
2831
2832 if ((attr->children != NULL) &&
2833 (attr->children->content != NULL))
2834 value = attr->children->content;
2835 else {
2836 xsltTransformError(NULL, cctxt->style, node,
2837 "Attribute 'exclude-result-prefixes': Invalid value.\n");
2838 cctxt->style->errors++;
2839 return(def);
2840 }
2841
2842 if (xsltParseNsPrefixList(cctxt, cctxt->tmpList, node,
2843 BAD_CAST value) != 0)
2844 goto exit;
2845 if (cctxt->tmpList->number == 0)
2846 goto exit;
2847 /*
2848 * Merge the list with the inherited list.
2849 */
2850 list = xsltCompilerUtilsCreateMergedList(def, cctxt->tmpList);
2851 if (list == NULL)
2852 goto exit;
2853 /*
2854 * Store the list in the stylesheet/compiler context.
2855 */
2856 if (xsltPointerListAddSize(
2857 cctxt->psData->exclResultNamespaces, list, 5) == -1)
2858 {
2859 xsltPointerListFree(list);
2860 list = NULL;
2861 goto exit;
2862 }
2863 /*
2864 * Notify of change in status wrt namespaces.
2865 */
2866 if (cctxt->inode != NULL)
2867 cctxt->inode->nsChanged = 1;
2868
2869exit:
2870 if (list != NULL)
2871 return(list);
2872 else
2873 return(def);
2874}
2875
2876/*
2877* xsltParseExtElemPrefixes:
2878*
2879* Create and store the list of in-scope namespaces for the given
2880* node in the stylesheet. If there are no changes in the in-scope
2881* namespaces then the last ns-info of the ancestor axis will be returned.
2882* Compilation-time only.
2883*
2884* Returns the ns-info or NULL if there are no namespaces in scope.
2885*/
2886static xsltPointerListPtr
2887xsltParseExtElemPrefixes(xsltCompilerCtxtPtr cctxt, xmlNodePtr node,
2888 xsltPointerListPtr def,
2889 int instrCategory)
2890{
2891 xsltPointerListPtr list = NULL;
2892 xmlAttrPtr attr;
2893 xmlChar *value;
2894 int i;
2895
2896 if ((cctxt == NULL) || (node == NULL))
2897 return(NULL);
2898
2899 if (instrCategory == XSLT_ELEMENT_CATEGORY_XSLT)
2900 attr = xmlHasNsProp(node, BAD_CAST "extension-element-prefixes", NULL);
2901 else
2902 attr = xmlHasNsProp(node, BAD_CAST "extension-element-prefixes",
2904 if (attr == NULL)
2905 return(def);
2906
2907 if (attr && (instrCategory == XSLT_ELEMENT_CATEGORY_LRE)) {
2908 /*
2909 * Mark the XSLT attr.
2910 */
2911 attr->psvi = (void *) xsltXSLTAttrMarker;
2912 }
2913
2914 if ((attr->children != NULL) &&
2915 (attr->children->content != NULL))
2916 value = attr->children->content;
2917 else {
2918 xsltTransformError(NULL, cctxt->style, node,
2919 "Attribute 'extension-element-prefixes': Invalid value.\n");
2920 cctxt->style->errors++;
2921 return(def);
2922 }
2923
2924
2925 if (xsltParseNsPrefixList(cctxt, cctxt->tmpList, node,
2926 BAD_CAST value) != 0)
2927 goto exit;
2928
2929 if (cctxt->tmpList->number == 0)
2930 goto exit;
2931 /*
2932 * REVISIT: Register the extension namespaces.
2933 */
2934 for (i = 0; i < cctxt->tmpList->number; i++)
2935 xsltRegisterExtPrefix(cctxt->style, NULL,
2936 BAD_CAST cctxt->tmpList->items[i]);
2937 /*
2938 * Merge the list with the inherited list.
2939 */
2940 list = xsltCompilerUtilsCreateMergedList(def, cctxt->tmpList);
2941 if (list == NULL)
2942 goto exit;
2943 /*
2944 * Store the list in the stylesheet.
2945 */
2946 if (xsltPointerListAddSize(
2947 cctxt->psData->extElemNamespaces, list, 5) == -1)
2948 {
2949 xsltPointerListFree(list);
2950 list = NULL;
2951 goto exit;
2952 }
2953 /*
2954 * Notify of change in status wrt namespaces.
2955 */
2956 if (cctxt->inode != NULL)
2957 cctxt->inode->nsChanged = 1;
2958
2959exit:
2960 if (list != NULL)
2961 return(list);
2962 else
2963 return(def);
2964}
2965
2966/*
2967* xsltParseAttrXSLTVersion:
2968*
2969* @cctxt: the compilation context
2970* @node: the element-node
2971* @isXsltElem: whether this is an XSLT element
2972*
2973* Parses the attribute xsl:version.
2974*
2975* Returns 1 if there was such an attribute, 0 if not and
2976* -1 if an internal or API error occured.
2977*/
2978static int
2979xsltParseAttrXSLTVersion(xsltCompilerCtxtPtr cctxt, xmlNodePtr node,
2980 int instrCategory)
2981{
2982 xmlChar *value;
2983 xmlAttrPtr attr;
2984
2985 if ((cctxt == NULL) || (node == NULL))
2986 return(-1);
2987
2988 if (instrCategory == XSLT_ELEMENT_CATEGORY_XSLT)
2989 attr = xmlHasNsProp(node, BAD_CAST "version", NULL);
2990 else
2991 attr = xmlHasNsProp(node, BAD_CAST "version", XSLT_NAMESPACE);
2992
2993 if (attr == NULL)
2994 return(0);
2995
2996 attr->psvi = (void *) xsltXSLTAttrMarker;
2997
2998 if ((attr->children != NULL) &&
2999 (attr->children->content != NULL))
3000 value = attr->children->content;
3001 else {
3002 xsltTransformError(NULL, cctxt->style, node,
3003 "Attribute 'version': Invalid value.\n");
3004 cctxt->style->errors++;
3005 return(1);
3006 }
3007
3008 if (! xmlStrEqual(value, (const xmlChar *)"1.0")) {
3009 cctxt->inode->forwardsCompat = 1;
3010 /*
3011 * TODO: To what extent do we support the
3012 * forwards-compatible mode?
3013 */
3014 /*
3015 * Report this only once per compilation episode.
3016 */
3017 if (! cctxt->hasForwardsCompat) {
3018 cctxt->hasForwardsCompat = 1;
3019 cctxt->errSeverity = XSLT_ERROR_SEVERITY_WARNING;
3020 xsltTransformError(NULL, cctxt->style, node,
3021 "Warning: the attribute xsl:version specifies a value "
3022 "different from '1.0'. Switching to forwards-compatible "
3023 "mode. Only features of XSLT 1.0 are supported by this "
3024 "processor.\n");
3025 cctxt->style->warnings++;
3026 cctxt->errSeverity = XSLT_ERROR_SEVERITY_ERROR;
3027 }
3028 } else {
3029 cctxt->inode->forwardsCompat = 0;
3030 }
3031
3032 if (attr && (instrCategory == XSLT_ELEMENT_CATEGORY_LRE)) {
3033 /*
3034 * Set a marker on XSLT attributes.
3035 */
3036 attr->psvi = (void *) xsltXSLTAttrMarker;
3037 }
3038 return(1);
3039}
3040
3041static int
3042xsltParsePreprocessStylesheetTree(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)
3043{
3044 xmlNodePtr deleteNode, cur, txt, textNode = NULL;
3045 xmlDocPtr doc;
3047 int internalize = 0, findSpaceAttr;
3048 int xsltStylesheetElemDepth;
3049 xmlAttrPtr attr;
3050 xmlChar *value;
3051 const xmlChar *name, *nsNameXSLT = NULL;
3052 int strictWhitespace, inXSLText = 0;
3053#ifdef XSLT_REFACTORED_XSLT_NSCOMP
3054 xsltNsMapPtr nsMapItem;
3055#endif
3056
3057 if ((cctxt == NULL) || (cctxt->style == NULL) ||
3058 (node == NULL) || (node->type != XML_ELEMENT_NODE))
3059 return(-1);
3060
3061 doc = node->doc;
3062 if (doc == NULL)
3063 goto internal_err;
3064
3065 style = cctxt->style;
3066 if ((style->dict != NULL) && (doc->dict == style->dict))
3067 internalize = 1;
3068 else
3069 style->internalized = 0;
3070
3071 /*
3072 * Init value of xml:space. Since this might be an embedded
3073 * stylesheet, this is needed to be performed on the element
3074 * where the stylesheet is rooted at, taking xml:space of
3075 * ancestors into account.
3076 */
3077 if (! cctxt->simplified)
3078 xsltStylesheetElemDepth = cctxt->depth +1;
3079 else
3080 xsltStylesheetElemDepth = 0;
3081
3082 if (xmlNodeGetSpacePreserve(node) != 1)
3083 cctxt->inode->preserveWhitespace = 0;
3084 else
3085 cctxt->inode->preserveWhitespace = 1;
3086
3087 /*
3088 * Eval if we should keep the old incorrect behaviour.
3089 */
3090 strictWhitespace = (cctxt->strict != 0) ? 1 : 0;
3091
3092 nsNameXSLT = xsltConstNamespaceNameXSLT;
3093
3094 deleteNode = NULL;
3095 cur = node;
3096 while (cur != NULL) {
3097 if (deleteNode != NULL) {
3098
3099#ifdef WITH_XSLT_DEBUG_BLANKS
3101 "xsltParsePreprocessStylesheetTree: removing node\n");
3102#endif
3103 xmlUnlinkNode(deleteNode);
3104 xmlFreeNode(deleteNode);
3105 deleteNode = NULL;
3106 }
3107 if (cur->type == XML_ELEMENT_NODE) {
3108
3109 /*
3110 * Clear the PSVI field.
3111 */
3112 cur->psvi = NULL;
3113
3114 xsltCompilerNodePush(cctxt, cur);
3115
3116 inXSLText = 0;
3117 textNode = NULL;
3118 findSpaceAttr = 1;
3119 cctxt->inode->stripWhitespace = 0;
3120 /*
3121 * TODO: I'd love to use a string pointer comparison here :-/
3122 */
3123 if (IS_XSLT_ELEM(cur)) {
3124#ifdef XSLT_REFACTORED_XSLT_NSCOMP
3125 if (cur->ns->href != nsNameXSLT) {
3126 nsMapItem = xsltNewNamespaceMapItem(cctxt,
3127 doc, cur->ns, cur);
3128 if (nsMapItem == NULL)
3129 goto internal_err;
3130 cur->ns->href = nsNameXSLT;
3131 }
3132#endif
3133
3134 if (cur->name == NULL)
3135 goto process_attributes;
3136 /*
3137 * Mark the XSLT element for later recognition.
3138 * TODO: Using the marker is still too dangerous, since if
3139 * the parsing mechanism leaves out an XSLT element, then
3140 * this might hit the transformation-mechanism, which
3141 * will break if it doesn't expect such a marker.
3142 */
3143 /* cur->psvi = (void *) xsltXSLTElemMarker; */
3144
3145 /*
3146 * XSLT 2.0: "Any whitespace text node whose parent is
3147 * one of the following elements is removed from the "
3148 * tree, regardless of any xml:space attributes:..."
3149 * xsl:apply-imports,
3150 * xsl:apply-templates,
3151 * xsl:attribute-set,
3152 * xsl:call-template,
3153 * xsl:choose,
3154 * xsl:stylesheet, xsl:transform.
3155 * XSLT 2.0: xsl:analyze-string,
3156 * xsl:character-map,
3157 * xsl:next-match
3158 *
3159 * TODO: I'd love to use a string pointer comparison here :-/
3160 */
3161 name = cur->name;
3162 switch (*name) {
3163 case 't':
3164 if ((name[0] == 't') && (name[1] == 'e') &&
3165 (name[2] == 'x') && (name[3] == 't') &&
3166 (name[4] == 0))
3167 {
3168 /*
3169 * Process the xsl:text element.
3170 * ----------------------------
3171 * Mark it for later recognition.
3172 */
3173 cur->psvi = (void *) xsltXSLTTextMarker;
3174 /*
3175 * For stylesheets, the set of
3176 * whitespace-preserving element names
3177 * consists of just xsl:text.
3178 */
3179 findSpaceAttr = 0;
3180 cctxt->inode->preserveWhitespace = 1;
3181 inXSLText = 1;
3182 }
3183 break;
3184 case 'c':
3185 if (xmlStrEqual(name, BAD_CAST "choose") ||
3186 xmlStrEqual(name, BAD_CAST "call-template"))
3187 cctxt->inode->stripWhitespace = 1;
3188 break;
3189 case 'a':
3190 if (xmlStrEqual(name, BAD_CAST "apply-templates") ||
3191 xmlStrEqual(name, BAD_CAST "apply-imports") ||
3192 xmlStrEqual(name, BAD_CAST "attribute-set"))
3193
3194 cctxt->inode->stripWhitespace = 1;
3195 break;
3196 default:
3197 if (xsltStylesheetElemDepth == cctxt->depth) {
3198 /*
3199 * This is a xsl:stylesheet/xsl:transform.
3200 */
3201 cctxt->inode->stripWhitespace = 1;
3202 break;
3203 }
3204
3205 if ((cur->prev != NULL) &&
3206 (cur->prev->type == XML_TEXT_NODE))
3207 {
3208 /*
3209 * XSLT 2.0 : "Any whitespace text node whose
3210 * following-sibling node is an xsl:param or
3211 * xsl:sort element is removed from the tree,
3212 * regardless of any xml:space attributes."
3213 */
3214 if (((*name == 'p') || (*name == 's')) &&
3215 (xmlStrEqual(name, BAD_CAST "param") ||
3216 xmlStrEqual(name, BAD_CAST "sort")))
3217 {
3218 do {
3219 if (IS_BLANK_NODE(cur->prev)) {
3220 txt = cur->prev;
3221 xmlUnlinkNode(txt);
3222 xmlFreeNode(txt);
3223 } else {
3224 /*
3225 * This will result in a content
3226 * error, when hitting the parsing
3227 * functions.
3228 */
3229 break;
3230 }
3231 } while (cur->prev);
3232 }
3233 }
3234 break;
3235 }
3236 }
3237
3238process_attributes:
3239 /*
3240 * Process attributes.
3241 * ------------------
3242 */
3243 if (cur->properties != NULL) {
3244 if (cur->children == NULL)
3245 findSpaceAttr = 0;
3246 attr = cur->properties;
3247 do {
3248#ifdef XSLT_REFACTORED_XSLT_NSCOMP
3249 if ((attr->ns) && (attr->ns->href != nsNameXSLT) &&
3250 xmlStrEqual(attr->ns->href, nsNameXSLT))
3251 {
3252 nsMapItem = xsltNewNamespaceMapItem(cctxt,
3253 doc, attr->ns, cur);
3254 if (nsMapItem == NULL)
3255 goto internal_err;
3256 attr->ns->href = nsNameXSLT;
3257 }
3258#endif
3259 if (internalize) {
3260 /*
3261 * Internalize the attribute's value; the goal is to
3262 * speed up operations and minimize used space by
3263 * compiled stylesheets.
3264 */
3265 txt = attr->children;
3266 /*
3267 * NOTE that this assumes only one
3268 * text-node in the attribute's content.
3269 */
3270 if ((txt != NULL) && (txt->content != NULL) &&
3271 (!xmlDictOwns(style->dict, txt->content)))
3272 {
3273 value = (xmlChar *) xmlDictLookup(style->dict,
3274 txt->content, -1);
3275 xmlNodeSetContent(txt, NULL);
3276 txt->content = value;
3277 }
3278 }
3279 /*
3280 * Process xml:space attributes.
3281 * ----------------------------
3282 */
3283 if ((findSpaceAttr != 0) &&
3284 (attr->ns != NULL) &&
3285 (attr->name != NULL) &&
3286 (attr->name[0] == 's') &&
3287 (attr->ns->prefix != NULL) &&
3288 (attr->ns->prefix[0] == 'x') &&
3289 (attr->ns->prefix[1] == 'm') &&
3290 (attr->ns->prefix[2] == 'l') &&
3291 (attr->ns->prefix[3] == 0))
3292 {
3293 value = xmlGetNsProp(cur, BAD_CAST "space",
3294 XML_XML_NAMESPACE);
3295 if (value != NULL) {
3296 if (xmlStrEqual(value, BAD_CAST "preserve")) {
3297 cctxt->inode->preserveWhitespace = 1;
3298 } else if (xmlStrEqual(value, BAD_CAST "default")) {
3299 cctxt->inode->preserveWhitespace = 0;
3300 } else {
3301 /* Invalid value for xml:space. */
3303 "Attribute xml:space: Invalid value.\n");
3304 cctxt->style->warnings++;
3305 }
3306 findSpaceAttr = 0;
3307 xmlFree(value);
3308 }
3309
3310 }
3311 attr = attr->next;
3312 } while (attr != NULL);
3313 }
3314 /*
3315 * We'll descend into the children of element nodes only.
3316 */
3317 if (cur->children != NULL) {
3318 cur = cur->children;
3319 continue;
3320 }
3321 } else if ((cur->type == XML_TEXT_NODE) ||
3322 (cur->type == XML_CDATA_SECTION_NODE))
3323 {
3324 /*
3325 * Merge adjacent text/CDATA-section-nodes
3326 * ---------------------------------------
3327 * In order to avoid breaking of existing stylesheets,
3328 * if the old behaviour is wanted (strictWhitespace == 0),
3329 * then we *won't* merge adjacent text-nodes
3330 * (except in xsl:text); this will ensure that whitespace-only
3331 * text nodes are (incorrectly) not stripped in some cases.
3332 *
3333 * Example: : <foo> <!-- bar -->zoo</foo>
3334 * Corrent (strict) result: <foo> zoo</foo>
3335 * Incorrect (old) result : <foo>zoo</foo>
3336 *
3337 * NOTE that we *will* merge adjacent text-nodes if
3338 * they are in xsl:text.
3339 * Example, the following:
3340 * <xsl:text> <!-- bar -->zoo<xsl:text>
3341 * will result in both cases in:
3342 * <xsl:text> zoo<xsl:text>
3343 */
3344 cur->type = XML_TEXT_NODE;
3345 if ((strictWhitespace != 0) || (inXSLText != 0)) {
3346 /*
3347 * New behaviour; merge nodes.
3348 */
3349 if (textNode == NULL)
3350 textNode = cur;
3351 else {
3352 if (cur->content != NULL)
3353 xmlNodeAddContent(textNode, cur->content);
3354 deleteNode = cur;
3355 }
3356 if ((cur->next == NULL) ||
3357 (cur->next->type == XML_ELEMENT_NODE))
3358 goto end_of_text;
3359 else
3360 goto next_sibling;
3361 } else {
3362 /*
3363 * Old behaviour.
3364 */
3365 if (textNode == NULL)
3366 textNode = cur;
3367 goto end_of_text;
3368 }
3369 } else if ((cur->type == XML_COMMENT_NODE) ||
3370 (cur->type == XML_PI_NODE))
3371 {
3372 /*
3373 * Remove processing instructions and comments.
3374 */
3375 deleteNode = cur;
3376 if ((cur->next == NULL) ||
3377 (cur->next->type == XML_ELEMENT_NODE))
3378 goto end_of_text;
3379 else
3380 goto next_sibling;
3381 } else {
3382 textNode = NULL;
3383 /*
3384 * Invalid node-type for this data-model.
3385 */
3387 "Invalid type of node for the XSLT data model.\n");
3388 cctxt->style->errors++;
3389 goto next_sibling;
3390 }
3391
3392end_of_text:
3393 if (textNode) {
3394 value = textNode->content;
3395 /*
3396 * At this point all adjacent text/CDATA-section nodes
3397 * have been merged.
3398 *
3399 * Strip whitespace-only text-nodes.
3400 * (cctxt->inode->stripWhitespace)
3401 */
3402 if ((value == NULL) || (*value == 0) ||
3403 (((cctxt->inode->stripWhitespace) ||
3404 (! cctxt->inode->preserveWhitespace)) &&
3405 IS_BLANK(*value) &&
3407 {
3408 if (textNode != cur) {
3409 xmlUnlinkNode(textNode);
3410 xmlFreeNode(textNode);
3411 } else
3412 deleteNode = textNode;
3413 textNode = NULL;
3414 goto next_sibling;
3415 }
3416 /*
3417 * Convert CDATA-section nodes to text-nodes.
3418 * TODO: Can this produce problems?
3419 */
3420 if (textNode->type != XML_TEXT_NODE) {
3421 textNode->type = XML_TEXT_NODE;
3422 textNode->name = xmlStringText;
3423 }
3424 if (internalize &&
3425 (textNode->content != NULL) &&
3426 (!xmlDictOwns(style->dict, textNode->content)))
3427 {
3428 /*
3429 * Internalize the string.
3430 */
3431 value = (xmlChar *) xmlDictLookup(style->dict,
3432 textNode->content, -1);
3433 xmlNodeSetContent(textNode, NULL);
3434 textNode->content = value;
3435 }
3436 textNode = NULL;
3437 /*
3438 * Note that "disable-output-escaping" of the xsl:text
3439 * element will be applied at a later level, when
3440 * XSLT elements are processed.
3441 */
3442 }
3443
3444next_sibling:
3445 if (cur->type == XML_ELEMENT_NODE) {
3446 xsltCompilerNodePop(cctxt, cur);
3447 }
3448 if (cur == node)
3449 break;
3450 if (cur->next != NULL) {
3451 cur = cur->next;
3452 } else {
3453 cur = cur->parent;
3454 inXSLText = 0;
3455 goto next_sibling;
3456 };
3457 }
3458 if (deleteNode != NULL) {
3459#ifdef WITH_XSLT_DEBUG_PARSING
3461 "xsltParsePreprocessStylesheetTree: removing node\n");
3462#endif
3463 xmlUnlinkNode(deleteNode);
3464 xmlFreeNode(deleteNode);
3465 }
3466 return(0);
3467
3468internal_err:
3469 return(-1);
3470}
3471
3472#endif /* XSLT_REFACTORED */
3473
3474#ifdef XSLT_REFACTORED
3475#else
3476static void
3478{
3479 xmlNodePtr deleteNode, styleelem;
3480 int internalize = 0;
3481
3482 if ((style == NULL) || (cur == NULL))
3483 return;
3484
3485 if ((cur->doc != NULL) && (style->dict != NULL) &&
3486 (cur->doc->dict == style->dict))
3487 internalize = 1;
3488 else
3489 style->internalized = 0;
3490
3491 if ((cur != NULL) && (IS_XSLT_ELEM(cur)) &&
3492 (IS_XSLT_NAME(cur, "stylesheet"))) {
3493 styleelem = cur;
3494 } else {
3495 styleelem = NULL;
3496 }
3497
3498 /*
3499 * This content comes from the stylesheet
3500 * For stylesheets, the set of whitespace-preserving
3501 * element names consists of just xsl:text.
3502 */
3503 deleteNode = NULL;
3504 while (cur != NULL) {
3505 if (deleteNode != NULL) {
3506#ifdef WITH_XSLT_DEBUG_BLANKS
3508 "xsltPreprocessStylesheet: removing ignorable blank node\n");
3509#endif
3510 xmlUnlinkNode(deleteNode);
3511 xmlFreeNode(deleteNode);
3512 deleteNode = NULL;
3513 }
3514 if (cur->type == XML_ELEMENT_NODE) {
3515 int exclPrefixes;
3516 /*
3517 * Internalize attributes values.
3518 */
3519 if ((internalize) && (cur->properties != NULL)) {
3520 xmlAttrPtr attr = cur->properties;
3521 xmlNodePtr txt;
3522
3523 while (attr != NULL) {
3524 txt = attr->children;
3525 if ((txt != NULL) && (txt->type == XML_TEXT_NODE) &&
3526 (txt->content != NULL) &&
3527 (!xmlDictOwns(style->dict, txt->content)))
3528 {
3529 xmlChar *tmp;
3530
3531 /*
3532 * internalize the text string, goal is to speed
3533 * up operations and minimize used space by compiled
3534 * stylesheets.
3535 */
3536 tmp = (xmlChar *) xmlDictLookup(style->dict,
3537 txt->content, -1);
3538 if (tmp != txt->content) {
3539 xmlNodeSetContent(txt, NULL);
3540 txt->content = tmp;
3541 }
3542 }
3543 attr = attr->next;
3544 }
3545 }
3546 if (IS_XSLT_ELEM(cur)) {
3547 exclPrefixes = 0;
3548 if (IS_XSLT_NAME(cur, "text")) {
3549 for (;exclPrefixes > 0;exclPrefixes--)
3551 goto skip_children;
3552 }
3553 } else {
3554 exclPrefixes = xsltParseStylesheetExcludePrefix(style, cur, 0);
3555 }
3556
3557 if ((cur->nsDef != NULL) && (style->exclPrefixNr > 0)) {
3558 xmlNsPtr ns = cur->nsDef, prev = NULL, next;
3559 xmlNodePtr root = NULL;
3560 int i, moved;
3561
3562 root = xmlDocGetRootElement(cur->doc);
3563 if ((root != NULL) && (root != cur)) {
3564 while (ns != NULL) {
3565 moved = 0;
3566 next = ns->next;
3567 for (i = 0;i < style->exclPrefixNr;i++) {
3568 if ((ns->prefix != NULL) &&
3569 (xmlStrEqual(ns->href,
3570 style->exclPrefixTab[i]))) {
3571 /*
3572 * Move the namespace definition on the root
3573 * element to avoid duplicating it without
3574 * loosing it.
3575 */
3576 if (prev == NULL) {
3577 cur->nsDef = ns->next;
3578 } else {
3579 prev->next = ns->next;
3580 }
3581 ns->next = root->nsDef;
3582 root->nsDef = ns;
3583 moved = 1;
3584 break;
3585 }
3586 }
3587 if (moved == 0)
3588 prev = ns;
3589 ns = next;
3590 }
3591 }
3592 }
3593 /*
3594 * If we have prefixes locally, recurse and pop them up when
3595 * going back
3596 */
3597 if (exclPrefixes > 0) {
3599 for (;exclPrefixes > 0;exclPrefixes--)
3601 goto skip_children;
3602 }
3603 } else if (cur->type == XML_TEXT_NODE) {
3604 if (IS_BLANK_NODE(cur)) {
3605 if (xmlNodeGetSpacePreserve(cur->parent) != 1) {
3606 deleteNode = cur;
3607 }
3608 } else if ((cur->content != NULL) && (internalize) &&
3609 (!xmlDictOwns(style->dict, cur->content))) {
3610 xmlChar *tmp;
3611
3612 /*
3613 * internalize the text string, goal is to speed
3614 * up operations and minimize used space by compiled
3615 * stylesheets.
3616 */
3617 tmp = (xmlChar *) xmlDictLookup(style->dict, cur->content, -1);
3618 xmlNodeSetContent(cur, NULL);
3619 cur->content = tmp;
3620 }
3621 } else if ((cur->type != XML_ELEMENT_NODE) &&
3622 (cur->type != XML_CDATA_SECTION_NODE)) {
3623 deleteNode = cur;
3624 goto skip_children;
3625 }
3626
3627 /*
3628 * Skip to next node. In case of a namespaced element children of
3629 * the stylesheet and not in the XSLT namespace and not an extension
3630 * element, ignore its content.
3631 */
3632 if ((cur->type == XML_ELEMENT_NODE) && (cur->ns != NULL) &&
3633 (styleelem != NULL) && (cur->parent == styleelem) &&
3634 (!xmlStrEqual(cur->ns->href, XSLT_NAMESPACE)) &&
3635 (!xsltCheckExtURI(style, cur->ns->href))) {
3636 goto skip_children;
3637 } else if (cur->children != NULL) {
3638 cur = cur->children;
3639 continue;
3640 }
3641
3642skip_children:
3643 if (cur->next != NULL) {
3644 cur = cur->next;
3645 continue;
3646 }
3647 do {
3648
3649 cur = cur->parent;
3650 if (cur == NULL)
3651 break;
3652 if (cur == (xmlNodePtr) style->doc) {
3653 cur = NULL;
3654 break;
3655 }
3656 if (cur->next != NULL) {
3657 cur = cur->next;
3658 break;
3659 }
3660 } while (cur != NULL);
3661 }
3662 if (deleteNode != NULL) {
3663#ifdef WITH_XSLT_DEBUG_PARSING
3665 "xsltPreprocessStylesheet: removing ignorable blank node\n");
3666#endif
3667 xmlUnlinkNode(deleteNode);
3668 xmlFreeNode(deleteNode);
3669 }
3670}
3671#endif /* end of else XSLT_REFACTORED */
3672
3681static void
3683 xmlNodePtr cur;
3684 const xmlChar *URI;
3685
3686 if (style == NULL)
3687 return;
3688 /*
3689 * TODO: basically if the stylesheet uses the same prefix for different
3690 * patterns, well they may be in problem, hopefully they will get
3691 * a warning first.
3692 */
3693 /*
3694 * TODO: Eliminate the use of the hash for XPath expressions.
3695 * An expression should be evaluated in the context of the in-scope
3696 * namespaces; eliminate the restriction of an XML document to contain
3697 * no duplicate prefixes for different namespace names.
3698 *
3699 */
3700 cur = xmlDocGetRootElement(style->doc);
3701 while (cur != NULL) {
3702 if (cur->type == XML_ELEMENT_NODE) {
3703 xmlNsPtr ns = cur->nsDef;
3704 while (ns != NULL) {
3705 if (ns->prefix != NULL) {
3706 if (style->nsHash == NULL) {
3707 style->nsHash = xmlHashCreate(10);
3708 if (style->nsHash == NULL) {
3710 "xsltGatherNamespaces: failed to create hash table\n");
3711 style->errors++;
3712 return;
3713 }
3714 }
3715 URI = xmlHashLookup(style->nsHash, ns->prefix);
3716 if ((URI != NULL) && (!xmlStrEqual(URI, ns->href))) {
3718 "Namespaces prefix %s used for multiple namespaces\n",ns->prefix);
3719 style->warnings++;
3720 } else if (URI == NULL) {
3722 (void *) ns->href, NULL);
3723
3724#ifdef WITH_XSLT_DEBUG_PARSING
3726 "Added namespace: %s mapped to %s\n", ns->prefix, ns->href);
3727#endif
3728 }
3729 }
3730 ns = ns->next;
3731 }
3732 }
3733
3734 /*
3735 * Skip to next node
3736 */
3737 if (cur->children != NULL) {
3738 if (cur->children->type != XML_ENTITY_DECL) {
3739 cur = cur->children;
3740 continue;
3741 }
3742 }
3743 if (cur->next != NULL) {
3744 cur = cur->next;
3745 continue;
3746 }
3747
3748 do {
3749 cur = cur->parent;
3750 if (cur == NULL)
3751 break;
3752 if (cur == (xmlNodePtr) style->doc) {
3753 cur = NULL;
3754 break;
3755 }
3756 if (cur->next != NULL) {
3757 cur = cur->next;
3758 break;
3759 }
3760 } while (cur != NULL);
3761 }
3762}
3763
3764#ifdef XSLT_REFACTORED
3765
3766static xsltStyleType
3767xsltGetXSLTElementTypeByNode(xsltCompilerCtxtPtr cctxt,
3768 xmlNodePtr node)
3769{
3770 if ((node == NULL) || (node->type != XML_ELEMENT_NODE) ||
3771 (node->name == NULL))
3772 return(0);
3773
3774 if (node->name[0] == 'a') {
3775 if (IS_XSLT_NAME(node, "apply-templates"))
3777 else if (IS_XSLT_NAME(node, "attribute"))
3778 return(XSLT_FUNC_ATTRIBUTE);
3779 else if (IS_XSLT_NAME(node, "apply-imports"))
3780 return(XSLT_FUNC_APPLYIMPORTS);
3781 else if (IS_XSLT_NAME(node, "attribute-set"))
3782 return(0);
3783
3784 } else if (node->name[0] == 'c') {
3785 if (IS_XSLT_NAME(node, "choose"))
3786 return(XSLT_FUNC_CHOOSE);
3787 else if (IS_XSLT_NAME(node, "copy"))
3788 return(XSLT_FUNC_COPY);
3789 else if (IS_XSLT_NAME(node, "copy-of"))
3790 return(XSLT_FUNC_COPYOF);
3791 else if (IS_XSLT_NAME(node, "call-template"))
3792 return(XSLT_FUNC_CALLTEMPLATE);
3793 else if (IS_XSLT_NAME(node, "comment"))
3794 return(XSLT_FUNC_COMMENT);
3795
3796 } else if (node->name[0] == 'd') {
3797 if (IS_XSLT_NAME(node, "document"))
3798 return(XSLT_FUNC_DOCUMENT);
3799 else if (IS_XSLT_NAME(node, "decimal-format"))
3800 return(0);
3801
3802 } else if (node->name[0] == 'e') {
3803 if (IS_XSLT_NAME(node, "element"))
3804 return(XSLT_FUNC_ELEMENT);
3805
3806 } else if (node->name[0] == 'f') {
3807 if (IS_XSLT_NAME(node, "for-each"))
3808 return(XSLT_FUNC_FOREACH);
3809 else if (IS_XSLT_NAME(node, "fallback"))
3810 return(XSLT_FUNC_FALLBACK);
3811
3812 } else if (*(node->name) == 'i') {
3813 if (IS_XSLT_NAME(node, "if"))
3814 return(XSLT_FUNC_IF);
3815 else if (IS_XSLT_NAME(node, "include"))
3816 return(0);
3817 else if (IS_XSLT_NAME(node, "import"))
3818 return(0);
3819
3820 } else if (*(node->name) == 'k') {
3821 if (IS_XSLT_NAME(node, "key"))
3822 return(0);
3823
3824 } else if (*(node->name) == 'm') {
3825 if (IS_XSLT_NAME(node, "message"))
3826 return(XSLT_FUNC_MESSAGE);
3827
3828 } else if (*(node->name) == 'n') {
3829 if (IS_XSLT_NAME(node, "number"))
3830 return(XSLT_FUNC_NUMBER);
3831 else if (IS_XSLT_NAME(node, "namespace-alias"))
3832 return(0);
3833
3834 } else if (*(node->name) == 'o') {
3835 if (IS_XSLT_NAME(node, "otherwise"))
3836 return(XSLT_FUNC_OTHERWISE);
3837 else if (IS_XSLT_NAME(node, "output"))
3838 return(0);
3839
3840 } else if (*(node->name) == 'p') {
3841 if (IS_XSLT_NAME(node, "param"))
3842 return(XSLT_FUNC_PARAM);
3843 else if (IS_XSLT_NAME(node, "processing-instruction"))
3844 return(XSLT_FUNC_PI);
3845 else if (IS_XSLT_NAME(node, "preserve-space"))
3846 return(0);
3847
3848 } else if (*(node->name) == 's') {
3849 if (IS_XSLT_NAME(node, "sort"))
3850 return(XSLT_FUNC_SORT);
3851 else if (IS_XSLT_NAME(node, "strip-space"))
3852 return(0);
3853 else if (IS_XSLT_NAME(node, "stylesheet"))
3854 return(0);
3855
3856 } else if (node->name[0] == 't') {
3857 if (IS_XSLT_NAME(node, "text"))
3858 return(XSLT_FUNC_TEXT);
3859 else if (IS_XSLT_NAME(node, "template"))
3860 return(0);
3861 else if (IS_XSLT_NAME(node, "transform"))
3862 return(0);
3863
3864 } else if (*(node->name) == 'v') {
3865 if (IS_XSLT_NAME(node, "value-of"))
3866 return(XSLT_FUNC_VALUEOF);
3867 else if (IS_XSLT_NAME(node, "variable"))
3868 return(XSLT_FUNC_VARIABLE);
3869
3870 } else if (*(node->name) == 'w') {
3871 if (IS_XSLT_NAME(node, "when"))
3872 return(XSLT_FUNC_WHEN);
3873 if (IS_XSLT_NAME(node, "with-param"))
3874 return(XSLT_FUNC_WITHPARAM);
3875 }
3876 return(0);
3877}
3878
3890int
3891xsltParseAnyXSLTElem(xsltCompilerCtxtPtr cctxt, xmlNodePtr elem)
3892{
3893 if ((cctxt == NULL) || (elem == NULL) ||
3894 (elem->type != XML_ELEMENT_NODE))
3895 return(-1);
3896
3897 elem->psvi = NULL;
3898
3899 if (! (IS_XSLT_ELEM_FAST(elem)))
3900 return(-1);
3901 /*
3902 * Detection of handled content of extension instructions.
3903 */
3904 if (cctxt->inode->category == XSLT_ELEMENT_CATEGORY_EXTENSION) {
3905 cctxt->inode->extContentHandled = 1;
3906 }
3907
3908 xsltCompilerNodePush(cctxt, elem);
3909 /*
3910 * URGENT TODO: Find a way to speed up this annoying redundant
3911 * textual node-name and namespace comparison.
3912 */
3913 if (cctxt->inode->prev->curChildType != 0)
3914 cctxt->inode->type = cctxt->inode->prev->curChildType;
3915 else
3916 cctxt->inode->type = xsltGetXSLTElementTypeByNode(cctxt, elem);
3917 /*
3918 * Update the in-scope namespaces if needed.
3919 */
3920 if (elem->nsDef != NULL)
3921 cctxt->inode->inScopeNs =
3922 xsltCompilerBuildInScopeNsList(cctxt, elem);
3923 /*
3924 * xsltStylePreCompute():
3925 * This will compile the information found on the current
3926 * element's attributes. NOTE that this won't process the
3927 * children of the instruction.
3928 */
3929 xsltStylePreCompute(cctxt->style, elem);
3930 /*
3931 * TODO: How to react on errors in xsltStylePreCompute() ?
3932 */
3933
3934 /*
3935 * Validate the content model of the XSLT-element.
3936 */
3937 switch (cctxt->inode->type) {
3939 /* EMPTY */
3940 goto empty_content;
3942 /* <!-- Content: (xsl:sort | xsl:with-param)* --> */
3943 goto apply_templates;
3945 /* <!-- Content: template --> */
3946 goto sequence_constructor;
3948 /* <!-- Content: xsl:with-param* --> */
3949 goto call_template;
3950 case XSLT_FUNC_CHOOSE:
3951 /* <!-- Content: (xsl:when+, xsl:otherwise?) --> */
3952 goto choose;
3953 case XSLT_FUNC_COMMENT:
3954 /* <!-- Content: template --> */
3955 goto sequence_constructor;
3956 case XSLT_FUNC_COPY:
3957 /* <!-- Content: template --> */
3958 goto sequence_constructor;
3959 case XSLT_FUNC_COPYOF:
3960 /* EMPTY */
3961 goto empty_content;
3962 case XSLT_FUNC_DOCUMENT: /* Extra one */
3963 /* ?? template ?? */
3964 goto sequence_constructor;
3965 case XSLT_FUNC_ELEMENT:
3966 /* <!-- Content: template --> */
3967 goto sequence_constructor;
3968 case XSLT_FUNC_FALLBACK:
3969 /* <!-- Content: template --> */
3970 goto sequence_constructor;
3971 case XSLT_FUNC_FOREACH:
3972 /* <!-- Content: (xsl:sort*, template) --> */
3973 goto for_each;
3974 case XSLT_FUNC_IF:
3975 /* <!-- Content: template --> */
3976 goto sequence_constructor;
3977 case XSLT_FUNC_OTHERWISE:
3978 /* <!-- Content: template --> */
3979 goto sequence_constructor;
3980 case XSLT_FUNC_MESSAGE:
3981 /* <!-- Content: template --> */
3982 goto sequence_constructor;
3983 case XSLT_FUNC_NUMBER:
3984 /* EMPTY */
3985 goto empty_content;
3986 case XSLT_FUNC_PARAM:
3987 /*
3988 * Check for redefinition.
3989 */
3990 if ((elem->psvi != NULL) && (cctxt->ivar != NULL)) {
3991 xsltVarInfoPtr ivar = cctxt->ivar;
3992
3993 do {
3994 if ((ivar->name ==
3995 ((xsltStyleItemParamPtr) elem->psvi)->name) &&
3996 (ivar->nsName ==
3997 ((xsltStyleItemParamPtr) elem->psvi)->ns))
3998 {
3999 elem->psvi = NULL;
4000 xsltTransformError(NULL, cctxt->style, elem,
4001 "Redefinition of variable or parameter '%s'.\n",
4002 ivar->name);
4003 cctxt->style->errors++;
4004 goto error;
4005 }
4006 ivar = ivar->prev;
4007 } while (ivar != NULL);
4008 }
4009 /* <!-- Content: template --> */
4010 goto sequence_constructor;
4011 case XSLT_FUNC_PI:
4012 /* <!-- Content: template --> */
4013 goto sequence_constructor;
4014 case XSLT_FUNC_SORT:
4015 /* EMPTY */
4016 goto empty_content;
4017 case XSLT_FUNC_TEXT:
4018 /* <!-- Content: #PCDATA --> */
4019 goto text;
4020 case XSLT_FUNC_VALUEOF:
4021 /* EMPTY */
4022 goto empty_content;
4023 case XSLT_FUNC_VARIABLE:
4024 /*
4025 * Check for redefinition.
4026 */
4027 if ((elem->psvi != NULL) && (cctxt->ivar != NULL)) {
4028 xsltVarInfoPtr ivar = cctxt->ivar;
4029
4030 do {
4031 if ((ivar->name ==
4032 ((xsltStyleItemVariablePtr) elem->psvi)->name) &&
4033 (ivar->nsName ==
4034 ((xsltStyleItemVariablePtr) elem->psvi)->ns))
4035 {
4036 elem->psvi = NULL;
4037 xsltTransformError(NULL, cctxt->style, elem,
4038 "Redefinition of variable or parameter '%s'.\n",
4039 ivar->name);
4040 cctxt->style->errors++;
4041 goto error;
4042 }
4043 ivar = ivar->prev;
4044 } while (ivar != NULL);
4045 }
4046 /* <!-- Content: template --> */
4047 goto sequence_constructor;
4048 case XSLT_FUNC_WHEN:
4049 /* <!-- Content: template --> */
4050 goto sequence_constructor;
4052 /* <!-- Content: template --> */
4053 goto sequence_constructor;
4054 default:
4055#ifdef WITH_XSLT_DEBUG_PARSING
4057 "xsltParseXSLTNode: Unhandled XSLT element '%s'.\n",
4058 elem->name);
4059#endif
4060 xsltTransformError(NULL, cctxt->style, elem,
4061 "xsltParseXSLTNode: Internal error; "
4062 "unhandled XSLT element '%s'.\n", elem->name);
4063 cctxt->style->errors++;
4064 goto internal_err;
4065 }
4066
4067apply_templates:
4068 /* <!-- Content: (xsl:sort | xsl:with-param)* --> */
4069 if (elem->children != NULL) {
4070 xmlNodePtr child = elem->children;
4071 do {
4072 if (child->type == XML_ELEMENT_NODE) {
4073 if (IS_XSLT_ELEM_FAST(child)) {
4074 if (xmlStrEqual(child->name, BAD_CAST "with-param")) {
4075 cctxt->inode->curChildType = XSLT_FUNC_WITHPARAM;
4076 xsltParseAnyXSLTElem(cctxt, child);
4077 } else if (xmlStrEqual(child->name, BAD_CAST "sort")) {
4078 cctxt->inode->curChildType = XSLT_FUNC_SORT;
4079 xsltParseAnyXSLTElem(cctxt, child);
4080 } else
4081 xsltParseContentError(cctxt->style, child);
4082 } else
4083 xsltParseContentError(cctxt->style, child);
4084 }
4085 child = child->next;
4086 } while (child != NULL);
4087 }
4088 goto exit;
4089
4090call_template:
4091 /* <!-- Content: xsl:with-param* --> */
4092 if (elem->children != NULL) {
4093 xmlNodePtr child = elem->children;
4094 do {
4095 if (child->type == XML_ELEMENT_NODE) {
4096 if (IS_XSLT_ELEM_FAST(child)) {
4098
4099 type = xsltGetXSLTElementTypeByNode(cctxt, child);
4100 if (type == XSLT_FUNC_WITHPARAM) {
4101 cctxt->inode->curChildType = XSLT_FUNC_WITHPARAM;
4102 xsltParseAnyXSLTElem(cctxt, child);
4103 } else {
4104 xsltParseContentError(cctxt->style, child);
4105 }
4106 } else
4107 xsltParseContentError(cctxt->style, child);
4108 }
4109 child = child->next;
4110 } while (child != NULL);
4111 }
4112 goto exit;
4113
4114text:
4115 if (elem->children != NULL) {
4116 xmlNodePtr child = elem->children;
4117 do {
4118 if ((child->type != XML_TEXT_NODE) &&
4119 (child->type != XML_CDATA_SECTION_NODE))
4120 {
4121 xsltTransformError(NULL, cctxt->style, elem,
4122 "The XSLT 'text' element must have only character "
4123 "data as content.\n");
4124 }
4125 child = child->next;
4126 } while (child != NULL);
4127 }
4128 goto exit;
4129
4130empty_content:
4131 if (elem->children != NULL) {
4132 xmlNodePtr child = elem->children;
4133 /*
4134 * Relaxed behaviour: we will allow whitespace-only text-nodes.
4135 */
4136 do {
4137 if (((child->type != XML_TEXT_NODE) &&
4138 (child->type != XML_CDATA_SECTION_NODE)) ||
4139 (! IS_BLANK_NODE(child)))
4140 {
4141 xsltTransformError(NULL, cctxt->style, elem,
4142 "This XSLT element must have no content.\n");
4143 cctxt->style->errors++;
4144 break;
4145 }
4146 child = child->next;
4147 } while (child != NULL);
4148 }
4149 goto exit;
4150
4151choose:
4152 /* <!-- Content: (xsl:when+, xsl:otherwise?) --> */
4153 /*
4154 * TODO: text-nodes in between are *not* allowed in XSLT 1.0.
4155 * The old behaviour did not check this.
4156 * NOTE: In XSLT 2.0 they are stripped beforehand
4157 * if whitespace-only (regardless of xml:space).
4158 */
4159 if (elem->children != NULL) {
4160 xmlNodePtr child = elem->children;
4161 int nbWhen = 0, nbOtherwise = 0, err = 0;
4162 do {
4163 if (child->type == XML_ELEMENT_NODE) {
4164 if (IS_XSLT_ELEM_FAST(child)) {
4166
4167 type = xsltGetXSLTElementTypeByNode(cctxt, child);
4168 if (type == XSLT_FUNC_WHEN) {
4169 nbWhen++;
4170 if (nbOtherwise) {
4171 xsltParseContentError(cctxt->style, child);
4172 err = 1;
4173 break;
4174 }
4175 cctxt->inode->curChildType = XSLT_FUNC_WHEN;
4176 xsltParseAnyXSLTElem(cctxt, child);
4177 } else if (type == XSLT_FUNC_OTHERWISE) {
4178 if (! nbWhen) {
4179 xsltParseContentError(cctxt->style, child);
4180 err = 1;
4181 break;
4182 }
4183 if (nbOtherwise) {
4184 xsltTransformError(NULL, cctxt->style, elem,
4185 "The XSLT 'choose' element must not contain "
4186 "more than one XSLT 'otherwise' element.\n");
4187 cctxt->style->errors++;
4188 err = 1;
4189 break;
4190 }
4191 nbOtherwise++;
4192 cctxt->inode->curChildType = XSLT_FUNC_OTHERWISE;
4193 xsltParseAnyXSLTElem(cctxt, child);
4194 } else
4195 xsltParseContentError(cctxt->style, child);
4196 } else
4197 xsltParseContentError(cctxt->style, child);
4198 }
4199 /*
4200 else
4201 xsltParseContentError(cctxt, child);
4202 */
4203 child = child->next;
4204 } while (child != NULL);
4205 if ((! err) && (! nbWhen)) {
4206 xsltTransformError(NULL, cctxt->style, elem,
4207 "The XSLT element 'choose' must contain at least one "
4208 "XSLT element 'when'.\n");
4209 cctxt->style->errors++;
4210 }
4211 }
4212 goto exit;
4213
4214for_each:
4215 /* <!-- Content: (xsl:sort*, template) --> */
4216 /*
4217 * NOTE: Text-nodes before xsl:sort are *not* allowed in XSLT 1.0.
4218 * The old behaviour did not allow this, but it catched this
4219 * only at transformation-time.
4220 * In XSLT 2.0 they are stripped beforehand if whitespace-only
4221 * (regardless of xml:space).
4222 */
4223 if (elem->children != NULL) {
4224 xmlNodePtr child = elem->children;
4225 /*
4226 * Parse xsl:sort first.
4227 */
4228 do {
4229 if ((child->type == XML_ELEMENT_NODE) &&
4230 IS_XSLT_ELEM_FAST(child))
4231 {
4232 if (xsltGetXSLTElementTypeByNode(cctxt, child) ==
4234 {
4235 cctxt->inode->curChildType = XSLT_FUNC_SORT;
4236 xsltParseAnyXSLTElem(cctxt, child);
4237 } else
4238 break;
4239 } else
4240 break;
4241 child = child->next;
4242 } while (child != NULL);
4243 /*
4244 * Parse the sequece constructor.
4245 */
4246 if (child != NULL)
4247 xsltParseSequenceConstructor(cctxt, child);
4248 }
4249 goto exit;
4250
4251sequence_constructor:
4252 /*
4253 * Parse the sequence constructor.
4254 */
4255 if (elem->children != NULL)
4256 xsltParseSequenceConstructor(cctxt, elem->children);
4257
4258 /*
4259 * Register information for vars/params. Only needed if there
4260 * are any following siblings.
4261 */
4262 if ((elem->next != NULL) &&
4263 ((cctxt->inode->type == XSLT_FUNC_VARIABLE) ||
4264 (cctxt->inode->type == XSLT_FUNC_PARAM)))
4265 {
4266 if ((elem->psvi != NULL) &&
4267 (((xsltStyleBasicItemVariablePtr) elem->psvi)->name))
4268 {
4269 xsltCompilerVarInfoPush(cctxt, elem,
4270 ((xsltStyleBasicItemVariablePtr) elem->psvi)->name,
4271 ((xsltStyleBasicItemVariablePtr) elem->psvi)->ns);
4272 }
4273 }
4274
4275error:
4276exit:
4277 xsltCompilerNodePop(cctxt, elem);
4278 return(0);
4279
4280internal_err:
4281 xsltCompilerNodePop(cctxt, elem);
4282 return(-1);
4283}
4284
4295static xsltStyleItemUknownPtr
4296xsltForwardsCompatUnkownItemCreate(xsltCompilerCtxtPtr cctxt)
4297{
4298 xsltStyleItemUknownPtr item;
4299
4300 item = (xsltStyleItemUknownPtr) xmlMalloc(sizeof(xsltStyleItemUknown));
4301 if (item == NULL) {
4302 xsltTransformError(NULL, cctxt->style, NULL,
4303 "Internal error in xsltForwardsCompatUnkownItemCreate(): "
4304 "Failed to allocate memory.\n");
4305 cctxt->style->errors++;
4306 return(NULL);
4307 }
4308 memset(item, 0, sizeof(xsltStyleItemUknown));
4309 item->type = XSLT_FUNC_UNKOWN_FORWARDS_COMPAT;
4310 /*
4311 * Store it in the stylesheet.
4312 */
4313 item->next = cctxt->style->preComps;
4314 cctxt->style->preComps = (xsltElemPreCompPtr) item;
4315 return(item);
4316}
4317
4332static int
4333xsltParseUnknownXSLTElem(xsltCompilerCtxtPtr cctxt,
4334 xmlNodePtr node)
4335{
4336 if ((cctxt == NULL) || (node == NULL) || (node->type != XML_ELEMENT_NODE))
4337 return(-1);
4338
4339 /*
4340 * Detection of handled content of extension instructions.
4341 */
4342 if (cctxt->inode->category == XSLT_ELEMENT_CATEGORY_EXTENSION) {
4343 cctxt->inode->extContentHandled = 1;
4344 }
4345 if (cctxt->inode->forwardsCompat == 0) {
4346 /*
4347 * We are not in forwards-compatible mode, so raise an error.
4348 */
4349 xsltTransformError(NULL, cctxt->style, node,
4350 "Unknown XSLT element '%s'.\n", node->name);
4351 cctxt->style->errors++;
4352 return(1);
4353 }
4354 /*
4355 * Forwards-compatible mode.
4356 * ------------------------
4357 *
4358 * Parse/compile xsl:fallback elements.
4359 *
4360 * QUESTION: Do we have to raise an error if there's no xsl:fallback?
4361 * ANSWER: No, since in the stylesheet the fallback behaviour might
4362 * also be provided by using the XSLT function "element-available".
4363 */
4364 if (cctxt->unknownItem == NULL) {
4365 /*
4366 * Create a singleton for all unknown XSLT instructions.
4367 */
4368 cctxt->unknownItem = xsltForwardsCompatUnkownItemCreate(cctxt);
4369 if (cctxt->unknownItem == NULL) {
4370 node->psvi = NULL;
4371 return(-1);
4372 }
4373 }
4374 node->psvi = cctxt->unknownItem;
4375 if (node->children == NULL)
4376 return(0);
4377 else {
4378 xmlNodePtr child = node->children;
4379
4380 xsltCompilerNodePush(cctxt, node);
4381 /*
4382 * Update the in-scope namespaces if needed.
4383 */
4384 if (node->nsDef != NULL)
4385 cctxt->inode->inScopeNs =
4386 xsltCompilerBuildInScopeNsList(cctxt, node);
4387 /*
4388 * Parse all xsl:fallback children.
4389 */
4390 do {
4391 if ((child->type == XML_ELEMENT_NODE) &&
4392 IS_XSLT_ELEM_FAST(child) &&
4393 IS_XSLT_NAME(child, "fallback"))
4394 {
4395 cctxt->inode->curChildType = XSLT_FUNC_FALLBACK;
4396 xsltParseAnyXSLTElem(cctxt, child);
4397 }
4398 child = child->next;
4399 } while (child != NULL);
4400
4401 xsltCompilerNodePop(cctxt, node);
4402 }
4403 return(0);
4404}
4405
4415void
4416xsltParseSequenceConstructor(xsltCompilerCtxtPtr cctxt, xmlNodePtr cur)
4417{
4419 xmlNodePtr deleteNode = NULL;
4420
4421 if (cctxt == NULL) {
4423 "xsltParseSequenceConstructor: Bad arguments\n");
4424 cctxt->style->errors++;
4425 return;
4426 }
4427 /*
4428 * Detection of handled content of extension instructions.
4429 */
4430 if (cctxt->inode->category == XSLT_ELEMENT_CATEGORY_EXTENSION) {
4431 cctxt->inode->extContentHandled = 1;
4432 }
4433 if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL))
4434 return;
4435 /*
4436 * This is the content reffered to as a "template".
4437 * E.g. an xsl:element has such content model:
4438 * <xsl:element
4439 * name = { qname }
4440 * namespace = { uri-reference }
4441 * use-attribute-sets = qnames>
4442 * <!-- Content: template -->
4443 *
4444 * NOTE that in XSLT-2 the term "template" was abandoned due to
4445 * confusion with xsl:template and the term "sequence constructor"
4446 * was introduced instead.
4447 *
4448 * The following XSLT-instructions are allowed to appear:
4449 * xsl:apply-templates, xsl:call-template, xsl:apply-imports,
4450 * xsl:for-each, xsl:value-of, xsl:copy-of, xsl:number,
4451 * xsl:choose, xsl:if, xsl:text, xsl:copy, xsl:variable,
4452 * xsl:message, xsl:fallback,
4453 * xsl:processing-instruction, xsl:comment, xsl:element
4454 * xsl:attribute.
4455 * Additional allowed content:
4456 * 1) extension instructions
4457 * 2) literal result elements
4458 * 3) PCDATA
4459 *
4460 * NOTE that this content model does *not* allow xsl:param.
4461 */
4462 while (cur != NULL) {
4463 cctxt->style->principal->opCount += 1;
4464
4465 if (deleteNode != NULL) {
4466#ifdef WITH_XSLT_DEBUG_BLANKS
4468 "xsltParseSequenceConstructor: removing xsl:text element\n");
4469#endif
4470 xmlUnlinkNode(deleteNode);
4471 xmlFreeNode(deleteNode);
4472 deleteNode = NULL;
4473 }
4474 if (cur->type == XML_ELEMENT_NODE) {
4475
4476 if (cur->psvi == xsltXSLTTextMarker) {
4477 /*
4478 * xsl:text elements
4479 * --------------------------------------------------------
4480 */
4481 xmlNodePtr tmp;
4482
4483 cur->psvi = NULL;
4484 /*
4485 * Mark the xsl:text element for later deletion.
4486 */
4487 deleteNode = cur;
4488 /*
4489 * Validate content.
4490 */
4491 tmp = cur->children;
4492 if (tmp) {
4493 /*
4494 * We don't expect more than one text-node in the
4495 * content, since we already merged adjacent
4496 * text/CDATA-nodes and eliminated PI/comment-nodes.
4497 */
4498 if ((tmp->type == XML_TEXT_NODE) ||
4499 (tmp->next == NULL))
4500 {
4501 /*
4502 * Leave the contained text-node in the tree.
4503 */
4504 xmlUnlinkNode(tmp);
4505 if (xmlAddPrevSibling(cur, tmp) == NULL) {
4507 "out of memory\n");
4508 xmlFreeNode(tmp);
4509 }
4510 } else {
4511 tmp = NULL;
4512 xsltTransformError(NULL, cctxt->style, cur,
4513 "Element 'xsl:text': Invalid type "
4514 "of node found in content.\n");
4515 cctxt->style->errors++;
4516 }
4517 }
4518 if (cur->properties) {
4519 xmlAttrPtr attr;
4520 /*
4521 * TODO: We need to report errors for
4522 * invalid attrs.
4523 */
4524 attr = cur->properties;
4525 do {
4526 if ((attr->ns == NULL) &&
4527 (attr->name != NULL) &&
4528 (attr->name[0] == 'd') &&
4530 BAD_CAST "disable-output-escaping"))
4531 {
4532 /*
4533 * Attr "disable-output-escaping".
4534 * XSLT-2: This attribute is deprecated.
4535 */
4536 if ((attr->children != NULL) &&
4537 xmlStrEqual(attr->children->content,
4538 BAD_CAST "yes"))
4539 {
4540 /*
4541 * Disable output escaping for this
4542 * text node.
4543 */
4544 if (tmp)
4545 tmp->name = xmlStringTextNoenc;
4546 } else if ((attr->children == NULL) ||
4547 (attr->children->content == NULL) ||
4548 (!xmlStrEqual(attr->children->content,
4549 BAD_CAST "no")))
4550 {
4551 xsltTransformError(NULL, cctxt->style,
4552 cur,
4553 "Attribute 'disable-output-escaping': "
4554 "Invalid value. Expected is "
4555 "'yes' or 'no'.\n");
4556 cctxt->style->errors++;
4557 }
4558 break;
4559 }
4560 attr = attr->next;
4561 } while (attr != NULL);
4562 }
4563 } else if (IS_XSLT_ELEM_FAST(cur)) {
4564 /*
4565 * TODO: Using the XSLT-marker is still not stable yet.
4566 */
4567 /* if (cur->psvi == xsltXSLTElemMarker) { */
4568 /*
4569 * XSLT instructions
4570 * --------------------------------------------------------
4571 */
4572 cur->psvi = NULL;
4573 type = xsltGetXSLTElementTypeByNode(cctxt, cur);
4574 switch (type) {
4579 case XSLT_FUNC_CHOOSE:
4580 case XSLT_FUNC_COMMENT:
4581 case XSLT_FUNC_COPY:
4582 case XSLT_FUNC_COPYOF:
4583 case XSLT_FUNC_DOCUMENT: /* Extra one */
4584 case XSLT_FUNC_ELEMENT:
4585 case XSLT_FUNC_FALLBACK:
4586 case XSLT_FUNC_FOREACH:
4587 case XSLT_FUNC_IF:
4588 case XSLT_FUNC_MESSAGE:
4589 case XSLT_FUNC_NUMBER:
4590 case XSLT_FUNC_PI:
4591 case XSLT_FUNC_TEXT:
4592 case XSLT_FUNC_VALUEOF:
4593 case XSLT_FUNC_VARIABLE:
4594 /*
4595 * Parse the XSLT element.
4596 */
4597 cctxt->inode->curChildType = type;
4598 xsltParseAnyXSLTElem(cctxt, cur);
4599 break;
4600 default:
4601 xsltParseUnknownXSLTElem(cctxt, cur);
4602 cur = cur->next;
4603 continue;
4604 }
4605 } else {
4606 /*
4607 * Non-XSLT elements
4608 * -----------------
4609 */
4610 xsltCompilerNodePush(cctxt, cur);
4611 /*
4612 * Update the in-scope namespaces if needed.
4613 */
4614 if (cur->nsDef != NULL)
4615 cctxt->inode->inScopeNs =
4616 xsltCompilerBuildInScopeNsList(cctxt, cur);
4617 /*
4618 * The current element is either a literal result element
4619 * or an extension instruction.
4620 *
4621 * Process attr "xsl:extension-element-prefixes".
4622 * FUTURE TODO: IIRC in XSLT 2.0 this attribute must be
4623 * processed by the implementor of the extension function;
4624 * i.e., it won't be handled by the XSLT processor.
4625 */
4626 /* SPEC 1.0:
4627 * "exclude-result-prefixes" is only allowed on literal
4628 * result elements and "xsl:exclude-result-prefixes"
4629 * on xsl:stylesheet/xsl:transform.
4630 * SPEC 2.0:
4631 * "There are a number of standard attributes
4632 * that may appear on any XSLT element: specifically
4633 * version, exclude-result-prefixes,
4634 * extension-element-prefixes, xpath-default-namespace,
4635 * default-collation, and use-when."
4636 *
4637 * SPEC 2.0:
4638 * For literal result elements:
4639 * "xsl:version, xsl:exclude-result-prefixes,
4640 * xsl:extension-element-prefixes,
4641 * xsl:xpath-default-namespace,
4642 * xsl:default-collation, or xsl:use-when."
4643 */
4644 if (cur->properties)
4645 cctxt->inode->extElemNs =
4646 xsltParseExtElemPrefixes(cctxt,
4647 cur, cctxt->inode->extElemNs,
4648 XSLT_ELEMENT_CATEGORY_LRE);
4649 /*
4650 * Eval if we have an extension instruction here.
4651 */
4652 if ((cur->ns != NULL) &&
4653 (cctxt->inode->extElemNs != NULL) &&
4654 (xsltCheckExtPrefix(cctxt->style, cur->ns->href) == 1))
4655 {
4656 /*
4657 * Extension instructions
4658 * ----------------------------------------------------
4659 * Mark the node information.
4660 */
4661 cctxt->inode->category = XSLT_ELEMENT_CATEGORY_EXTENSION;
4662 cctxt->inode->extContentHandled = 0;
4663 if (cur->psvi != NULL) {
4664 cur->psvi = NULL;
4665 /*
4666 * TODO: Temporary sanity check.
4667 */
4668 xsltTransformError(NULL, cctxt->style, cur,
4669 "Internal error in xsltParseSequenceConstructor(): "
4670 "Occupied PSVI field.\n");
4671 cctxt->style->errors++;
4672 cur = cur->next;
4673 continue;
4674 }
4675 cur->psvi = (void *)
4676 xsltPreComputeExtModuleElement(cctxt->style, cur);
4677
4678 if (cur->psvi == NULL) {
4679 /*
4680 * OLD COMMENT: "Unknown element, maybe registered
4681 * at the context level. Mark it for later
4682 * recognition."
4683 * QUESTION: What does the xsltExtMarker mean?
4684 * ANSWER: It is used in
4685 * xsltApplySequenceConstructor() at
4686 * transformation-time to look out for extension
4687 * registered in the transformation context.
4688 */
4689 cur->psvi = (void *) xsltExtMarker;
4690 }
4691 /*
4692 * BIG NOTE: Now the ugly part. In previous versions
4693 * of Libxslt (until 1.1.16), all the content of an
4694 * extension instruction was processed and compiled without
4695 * the need of the extension-author to explicitely call
4696 * such a processing;.We now need to mimic this old
4697 * behaviour in order to avoid breaking old code
4698 * on the extension-author's side.
4699 * The mechanism:
4700 * 1) If the author does *not* set the
4701 * compile-time-flag @extContentHandled, then we'll
4702 * parse the content assuming that it's a "template"
4703 * (or "sequence constructor in XSLT 2.0 terms).
4704 * NOTE: If the extension is registered at
4705 * transformation-time only, then there's no way of
4706 * knowing that content shall be valid, and we'll
4707 * process the content the same way.
4708 * 2) If the author *does* set the flag, then we'll assume
4709 * that the author has handled the parsing him/herself
4710 * (e.g. called xsltParseSequenceConstructor(), etc.
4711 * explicitely in his/her code).
4712 */
4713 if ((cur->children != NULL) &&
4714 (cctxt->inode->extContentHandled == 0))
4715 {
4716 /*
4717 * Default parsing of the content using the
4718 * sequence-constructor model.
4719 */
4720 xsltParseSequenceConstructor(cctxt, cur->children);
4721 }
4722 } else {
4723 /*
4724 * Literal result element
4725 * ----------------------------------------------------
4726 * Allowed XSLT attributes:
4727 * xsl:extension-element-prefixes CDATA #IMPLIED
4728 * xsl:exclude-result-prefixes CDATA #IMPLIED
4729 * TODO: xsl:use-attribute-sets %qnames; #IMPLIED
4730 * xsl:version NMTOKEN #IMPLIED
4731 */
4732 cur->psvi = NULL;
4733 cctxt->inode->category = XSLT_ELEMENT_CATEGORY_LRE;
4734 if (cur->properties != NULL) {
4735 xmlAttrPtr attr = cur->properties;
4736 /*
4737 * Attribute "xsl:exclude-result-prefixes".
4738 */
4739 cctxt->inode->exclResultNs =
4740 xsltParseExclResultPrefixes(cctxt, cur,
4741 cctxt->inode->exclResultNs,
4742 XSLT_ELEMENT_CATEGORY_LRE);
4743 /*
4744 * Attribute "xsl:version".
4745 */
4746 xsltParseAttrXSLTVersion(cctxt, cur,
4747 XSLT_ELEMENT_CATEGORY_LRE);
4748 /*
4749 * Report invalid XSLT attributes.
4750 * For XSLT 1.0 only xsl:use-attribute-sets is allowed
4751 * next to xsl:version, xsl:exclude-result-prefixes and
4752 * xsl:extension-element-prefixes.
4753 *
4754 * Mark all XSLT attributes, in order to skip such
4755 * attributes when instantiating the LRE.
4756 */
4757 do {
4758 if ((attr->psvi != xsltXSLTAttrMarker) &&
4759 IS_XSLT_ATTR_FAST(attr))
4760 {
4761 if (! xmlStrEqual(attr->name,
4762 BAD_CAST "use-attribute-sets"))
4763 {
4764 xsltTransformError(NULL, cctxt->style,
4765 cur,
4766 "Unknown XSLT attribute '%s'.\n",
4767 attr->name);
4768 cctxt->style->errors++;
4769 } else {
4770 /*
4771 * XSLT attr marker.
4772 */
4773 attr->psvi = (void *) xsltXSLTAttrMarker;
4774 }
4775 }
4776 attr = attr->next;
4777 } while (attr != NULL);
4778 }
4779 /*
4780 * Create/reuse info for the literal result element.
4781 */
4782 if (cctxt->inode->nsChanged)
4783 xsltLREInfoCreate(cctxt, cur, 1);
4784 cur->psvi = cctxt->inode->litResElemInfo;
4785 /*
4786 * Apply ns-aliasing on the element and on its attributes.
4787 */
4788 if (cctxt->hasNsAliases)
4789 xsltLREBuildEffectiveNs(cctxt, cur);
4790 /*
4791 * Compile attribute value templates (AVT).
4792 */
4793 if (cur->properties) {
4794 xmlAttrPtr attr = cur->properties;
4795
4796 while (attr != NULL) {
4797 xsltCompileAttr(cctxt->style, attr);
4798 attr = attr->next;
4799 }
4800 }
4801 /*
4802 * Parse the content, which is defined to be a "template"
4803 * (or "sequence constructor" in XSLT 2.0 terms).
4804 */
4805 if (cur->children != NULL) {
4806 xsltParseSequenceConstructor(cctxt, cur->children);
4807 }
4808 }
4809 /*
4810 * Leave the non-XSLT element.
4811 */
4812 xsltCompilerNodePop(cctxt, cur);
4813 }
4814 }
4815 cur = cur->next;
4816 }
4817 if (deleteNode != NULL) {
4818#ifdef WITH_XSLT_DEBUG_BLANKS
4820 "xsltParseSequenceConstructor: removing xsl:text element\n");
4821#endif
4822 xmlUnlinkNode(deleteNode);
4823 xmlFreeNode(deleteNode);
4824 deleteNode = NULL;
4825 }
4826}
4827
4842void
4844 if ((style == NULL) || (templ == NULL) ||
4845 (templ->type == XML_NAMESPACE_DECL))
4846 return;
4847
4848 /*
4849 * Detection of handled content of extension instructions.
4850 */
4851 if (XSLT_CCTXT(style)->inode->category == XSLT_ELEMENT_CATEGORY_EXTENSION) {
4852 XSLT_CCTXT(style)->inode->extContentHandled = 1;
4853 }
4854
4855 if (templ->children != NULL) {
4856 xmlNodePtr child = templ->children;
4857 /*
4858 * Process xsl:param elements, which can only occur as the
4859 * immediate children of xsl:template (well, and of any
4860 * user-defined extension instruction if needed).
4861 */
4862 do {
4863 style->principal->opCount += 1;
4864
4865 if ((child->type == XML_ELEMENT_NODE) &&
4866 IS_XSLT_ELEM_FAST(child) &&
4867 IS_XSLT_NAME(child, "param"))
4868 {
4869 XSLT_CCTXT(style)->inode->curChildType = XSLT_FUNC_PARAM;
4870 xsltParseAnyXSLTElem(XSLT_CCTXT(style), child);
4871 } else
4872 break;
4873 child = child->next;
4874 } while (child != NULL);
4875 /*
4876 * Parse the content and register the pattern.
4877 */
4878 xsltParseSequenceConstructor(XSLT_CCTXT(style), child);
4879 }
4880}
4881
4882#else /* XSLT_REFACTORED */
4883
4893void
4895 xmlNodePtr cur, delete;
4896
4897 if ((style == NULL) || (templ == NULL) ||
4898 (templ->type == XML_NAMESPACE_DECL)) return;
4899
4900 /*
4901 * This content comes from the stylesheet
4902 * For stylesheets, the set of whitespace-preserving
4903 * element names consists of just xsl:text.
4904 */
4905 cur = templ->children;
4906 delete = NULL;
4907 while (cur != NULL) {
4908 style->principal->opCount += 1;
4909
4910 if (delete != NULL) {
4911#ifdef WITH_XSLT_DEBUG_BLANKS
4913 "xsltParseTemplateContent: removing text\n");
4914#endif
4915 xmlUnlinkNode(delete);
4916 xmlFreeNode(delete);
4917 delete = NULL;
4918 }
4919 if (IS_XSLT_ELEM(cur)) {
4921
4922 if (IS_XSLT_NAME(cur, "text")) {
4923 /*
4924 * TODO: Processing of xsl:text should be moved to
4925 * xsltPreprocessStylesheet(), since otherwise this
4926 * will be performed for every multiply included
4927 * stylesheet; i.e. this here is not skipped with
4928 * the use of the style->nopreproc flag.
4929 */
4930 if (cur->children != NULL) {
4931 xmlChar *prop;
4932 xmlNodePtr text = cur->children, next;
4933 int noesc = 0;
4934
4935 prop = xmlGetNsProp(cur,
4936 (const xmlChar *)"disable-output-escaping",
4937 NULL);
4938 if (prop != NULL) {
4939#ifdef WITH_XSLT_DEBUG_PARSING
4941 "Disable escaping: %s\n", text->content);
4942#endif
4943 if (xmlStrEqual(prop, (const xmlChar *)"yes")) {
4944 noesc = 1;
4945 } else if (!xmlStrEqual(prop,
4946 (const xmlChar *)"no")){
4948 "xsl:text: disable-output-escaping allows only yes or no\n");
4949 style->warnings++;
4950
4951 }
4952 xmlFree(prop);
4953 }
4954
4955 while (text != NULL) {
4956 if (text->type == XML_COMMENT_NODE) {
4957 text = text->next;
4958 continue;
4959 }
4960 if ((text->type != XML_TEXT_NODE) &&
4961 (text->type != XML_CDATA_SECTION_NODE)) {
4963 "xsltParseTemplateContent: xslt:text content problem\n");
4964 style->errors++;
4965 break;
4966 }
4967 if ((noesc) && (text->type != XML_CDATA_SECTION_NODE))
4968 text->name = xmlStringTextNoenc;
4969 text = text->next;
4970 }
4971
4972 /*
4973 * replace xsl:text by the list of childs
4974 */
4975 if (text == NULL) {
4976 text = cur->children;
4977 while (text != NULL) {
4978 if ((style->internalized) &&
4979 (text->content != NULL) &&
4980 (!xmlDictOwns(style->dict, text->content))) {
4981
4982 /*
4983 * internalize the text string
4984 */
4985 if (text->doc->dict != NULL) {
4986 const xmlChar *tmp;
4987
4988 tmp = xmlDictLookup(text->doc->dict,
4989 text->content, -1);
4990 if (tmp != text->content) {
4991 xmlNodeSetContent(text, NULL);
4992 text->content = (xmlChar *) tmp;
4993 }
4994 }
4995 }
4996
4997 next = text->next;
4998 xmlUnlinkNode(text);
4999 if (xmlAddPrevSibling(cur, text) == NULL) {
5001 "out of memory\n");
5002 xmlFreeNode(text);
5003 }
5004 text = next;
5005 }
5006 }
5007 }
5008 delete = cur;
5009 goto skip_children;
5010 }
5011 }
5012 else if ((cur->ns != NULL) && (style->nsDefs != NULL) &&
5013 (xsltCheckExtPrefix(style, cur->ns->prefix)))
5014 {
5015 /*
5016 * okay this is an extension element compile it too
5017 */
5019 }
5020 else if (cur->type == XML_ELEMENT_NODE)
5021 {
5022 /*
5023 * This is an element which will be output as part of the
5024 * template exectution, precompile AVT if found.
5025 */
5026 if ((cur->ns == NULL) && (style->defaultAlias != NULL)) {
5027 cur->ns = xmlSearchNsByHref(cur->doc, cur,
5028 style->defaultAlias);
5029 }
5030 if (cur->properties != NULL) {
5031 xmlAttrPtr attr = cur->properties;
5032
5033 while (attr != NULL) {
5035 attr = attr->next;
5036 }
5037 }
5038 }
5039 /*
5040 * Skip to next node
5041 */
5042 if (cur->children != NULL) {
5043 if (cur->children->type != XML_ENTITY_DECL) {
5044 cur = cur->children;
5045 continue;
5046 }
5047 }
5048skip_children:
5049 if (cur->next != NULL) {
5050 cur = cur->next;
5051 continue;
5052 }
5053
5054 do {
5055 cur = cur->parent;
5056 if (cur == NULL)
5057 break;
5058 if (cur == templ) {
5059 cur = NULL;
5060 break;
5061 }
5062 if (cur->next != NULL) {
5063 cur = cur->next;
5064 break;
5065 }
5066 } while (cur != NULL);
5067 }
5068 if (delete != NULL) {
5069#ifdef WITH_XSLT_DEBUG_PARSING
5071 "xsltParseTemplateContent: removing text\n");
5072#endif
5073 xmlUnlinkNode(delete);
5074 xmlFreeNode(delete);
5075 delete = NULL;
5076 }
5077
5078 /*
5079 * Skip the first params
5080 */
5081 cur = templ->children;
5082 while (cur != NULL) {
5083 if ((IS_XSLT_ELEM(cur)) && (!(IS_XSLT_NAME(cur, "param"))))
5084 break;
5085 cur = cur->next;
5086 }
5087
5088 /*
5089 * Browse the remainder of the template
5090 */
5091 while (cur != NULL) {
5092 if ((IS_XSLT_ELEM(cur)) && (IS_XSLT_NAME(cur, "param"))) {
5093 xmlNodePtr param = cur;
5094
5096 "xsltParseTemplateContent: ignoring misplaced param element\n");
5097 if (style != NULL) style->warnings++;
5098 cur = cur->next;
5099 xmlUnlinkNode(param);
5100 xmlFreeNode(param);
5101 } else
5102 break;
5103 }
5104}
5105
5106#endif /* else XSLT_REFACTORED */
5107
5119static void
5121 xmlChar *prop = NULL;
5122 xmlChar *use = NULL;
5123 xmlChar *match = NULL;
5124 xmlChar *name = NULL;
5125 xmlChar *nameURI = NULL;
5126
5127 if ((style == NULL) || (key == NULL) || (key->type != XML_ELEMENT_NODE))
5128 return;
5129
5130 /*
5131 * Get arguments
5132 */
5133 prop = xmlGetNsProp(key, (const xmlChar *)"name", NULL);
5134 if (prop != NULL) {
5135 const xmlChar *URI;
5136
5137 /*
5138 * TODO: Don't use xsltGetQNameURI().
5139 */
5140 URI = xsltGetQNameURI(key, &prop);
5141 if (prop == NULL) {
5142 if (style != NULL) style->errors++;
5143 goto error;
5144 } else {
5145 name = prop;
5146 if (URI != NULL)
5147 nameURI = xmlStrdup(URI);
5148 }
5149#ifdef WITH_XSLT_DEBUG_PARSING
5151 "xsltParseStylesheetKey: name %s\n", name);
5152#endif
5153 } else {
5155 "xsl:key : error missing name\n");
5156 if (style != NULL) style->errors++;
5157 goto error;
5158 }
5159
5160 match = xmlGetNsProp(key, (const xmlChar *)"match", NULL);
5161 if (match == NULL) {
5163 "xsl:key : error missing match\n");
5164 if (style != NULL) style->errors++;
5165 goto error;
5166 }
5167
5168 use = xmlGetNsProp(key, (const xmlChar *)"use", NULL);
5169 if (use == NULL) {
5171 "xsl:key : error missing use\n");
5172 if (style != NULL) style->errors++;
5173 goto error;
5174 }
5175
5176 /*
5177 * register the keys
5178 */
5179 xsltAddKey(style, name, nameURI, match, use, key);
5180
5181
5182error:
5183 if (use != NULL)
5184 xmlFree(use);
5185 if (match != NULL)
5186 xmlFree(match);
5187 if (name != NULL)
5188 xmlFree(name);
5189 if (nameURI != NULL)
5190 xmlFree(nameURI);
5191
5192 if (key->children != NULL) {
5193 xsltParseContentError(style, key->children);
5194 }
5195}
5196
5197#ifdef XSLT_REFACTORED
5211static void
5212xsltParseXSLTTemplate(xsltCompilerCtxtPtr cctxt, xmlNodePtr templNode) {
5213 xsltTemplatePtr templ;
5214 xmlChar *prop;
5215 double priority;
5216
5217 if ((cctxt == NULL) || (templNode == NULL) ||
5218 (templNode->type != XML_ELEMENT_NODE))
5219 return;
5220
5221 /*
5222 * Create and link the structure
5223 */
5224 templ = xsltNewTemplate();
5225 if (templ == NULL)
5226 return;
5227
5228 xsltCompilerNodePush(cctxt, templNode);
5229 if (templNode->nsDef != NULL)
5230 cctxt->inode->inScopeNs =
5231 xsltCompilerBuildInScopeNsList(cctxt, templNode);
5232
5233 templ->next = cctxt->style->templates;
5234 cctxt->style->templates = templ;
5235 templ->style = cctxt->style;
5236
5237 /*
5238 * Attribute "mode".
5239 */
5240 prop = xmlGetNsProp(templNode, (const xmlChar *)"mode", NULL);
5241 if (prop != NULL) {
5242 const xmlChar *modeURI;
5243
5244 /*
5245 * TODO: We need a standardized function for extraction
5246 * of namespace names and local names from QNames.
5247 * Don't use xsltGetQNameURI() as it cannot channe�
5248 * reports through the context.
5249 */
5250 modeURI = xsltGetQNameURI(templNode, &prop);
5251 if (prop == NULL) {
5252 cctxt->style->errors++;
5253 goto error;
5254 }
5255 templ->mode = xmlDictLookup(cctxt->style->dict, prop, -1);
5256 xmlFree(prop);
5257 prop = NULL;
5258 if (xmlValidateNCName(templ->mode, 0)) {
5259 xsltTransformError(NULL, cctxt->style, templNode,
5260 "xsl:template: Attribute 'mode': The local part '%s' "
5261 "of the value is not a valid NCName.\n", templ->name);
5262 cctxt->style->errors++;
5263 goto error;
5264 }
5265 if (modeURI != NULL)
5266 templ->modeURI = xmlDictLookup(cctxt->style->dict, modeURI, -1);
5267#ifdef WITH_XSLT_DEBUG_PARSING
5269 "xsltParseXSLTTemplate: mode %s\n", templ->mode);
5270#endif
5271 }
5272 /*
5273 * Attribute "match".
5274 */
5275 prop = xmlGetNsProp(templNode, (const xmlChar *)"match", NULL);
5276 if (prop != NULL) {
5277 templ->match = prop;
5278 prop = NULL;
5279 }
5280 /*
5281 * Attribute "priority".
5282 */
5283 prop = xmlGetNsProp(templNode, (const xmlChar *)"priority", NULL);
5284 if (prop != NULL) {
5285 priority = xmlXPathStringEvalNumber(prop);
5286 templ->priority = (float) priority;
5287 xmlFree(prop);
5288 prop = NULL;
5289 }
5290 /*
5291 * Attribute "name".
5292 */
5293 prop = xmlGetNsProp(templNode, (const xmlChar *)"name", NULL);
5294 if (prop != NULL) {
5295 const xmlChar *nameURI;
5296 xsltTemplatePtr curTempl;
5297
5298 /*
5299 * TODO: Don't use xsltGetQNameURI().
5300 */
5301 nameURI = xsltGetQNameURI(templNode, &prop);
5302 if (prop == NULL) {
5303 cctxt->style->errors++;
5304 goto error;
5305 }
5306 templ->name = xmlDictLookup(cctxt->style->dict, prop, -1);
5307 xmlFree(prop);
5308 prop = NULL;
5309 if (xmlValidateNCName(templ->name, 0)) {
5310 xsltTransformError(NULL, cctxt->style, templNode,
5311 "xsl:template: Attribute 'name': The local part '%s' of "
5312 "the value is not a valid NCName.\n", templ->name);
5313 cctxt->style->errors++;
5314 goto error;
5315 }
5316 if (nameURI != NULL)
5317 templ->nameURI = xmlDictLookup(cctxt->style->dict, nameURI, -1);
5318 curTempl = templ->next;
5319 while (curTempl != NULL) {
5320 if ((nameURI != NULL && xmlStrEqual(curTempl->name, templ->name) &&
5321 xmlStrEqual(curTempl->nameURI, nameURI) ) ||
5322 (nameURI == NULL && curTempl->nameURI == NULL &&
5323 xmlStrEqual(curTempl->name, templ->name)))
5324 {
5325 xsltTransformError(NULL, cctxt->style, templNode,
5326 "xsl:template: error duplicate name '%s'\n", templ->name);
5327 cctxt->style->errors++;
5328 goto error;
5329 }
5330 curTempl = curTempl->next;
5331 }
5332 }
5333 if (templNode->children != NULL) {
5334 xsltParseTemplateContent(cctxt->style, templNode);
5335 /*
5336 * MAYBE TODO: Custom behaviour: In order to stay compatible with
5337 * Xalan and MSXML(.NET), we could allow whitespace
5338 * to appear before an xml:param element; this whitespace
5339 * will additionally become part of the "template".
5340 * NOTE that this is totally deviates from the spec, but
5341 * is the de facto behaviour of Xalan and MSXML(.NET).
5342 * Personally I wouldn't allow this, since if we have:
5343 * <xsl:template ...xml:space="preserve">
5344 * <xsl:param name="foo"/>
5345 * <xsl:param name="bar"/>
5346 * <xsl:param name="zoo"/>
5347 * ... the whitespace between every xsl:param would be
5348 * added to the result tree.
5349 */
5350 }
5351
5352 templ->elem = templNode;
5353 templ->content = templNode->children;
5354 xsltAddTemplate(cctxt->style, templ, templ->mode, templ->modeURI);
5355
5356error:
5357 xsltCompilerNodePop(cctxt, templNode);
5358 return;
5359}
5360
5361#else /* XSLT_REFACTORED */
5362
5371static void
5374 xmlChar *prop;
5375 xmlChar *mode = NULL;
5376 xmlChar *modeURI = NULL;
5377 double priority;
5378
5379 if ((style == NULL) || (template == NULL) ||
5380 (template->type != XML_ELEMENT_NODE))
5381 return;
5382
5383 if (style->principal->opLimit > 0) {
5384 if (style->principal->opCount > style->principal->opLimit) {
5386 "XSLT parser operation limit exceeded\n");
5387 style->errors++;
5388 return;
5389 }
5390 }
5391
5392 /*
5393 * Create and link the structure
5394 */
5395 ret = xsltNewTemplate();
5396 if (ret == NULL)
5397 return;
5398 ret->next = style->templates;
5399 style->templates = ret;
5400 ret->style = style;
5401
5402 /*
5403 * Get inherited namespaces
5404 */
5405 /*
5406 * TODO: Apply the optimized in-scope-namespace mechanism
5407 * as for the other XSLT instructions.
5408 */
5409 xsltGetInheritedNsList(style, ret, template);
5410
5411 /*
5412 * Get arguments
5413 */
5414 prop = xmlGetNsProp(template, (const xmlChar *)"mode", NULL);
5415 if (prop != NULL) {
5416 const xmlChar *URI;
5417
5418 /*
5419 * TODO: Don't use xsltGetQNameURI().
5420 */
5421 URI = xsltGetQNameURI(template, &prop);
5422 if (prop == NULL) {
5423 if (style != NULL) style->errors++;
5424 goto error;
5425 } else {
5426 mode = prop;
5427 if (URI != NULL)
5428 modeURI = xmlStrdup(URI);
5429 }
5430 ret->mode = xmlDictLookup(style->dict, mode, -1);
5431 ret->modeURI = xmlDictLookup(style->dict, modeURI, -1);
5432#ifdef WITH_XSLT_DEBUG_PARSING
5434 "xsltParseStylesheetTemplate: mode %s\n", mode);
5435#endif
5436 if (mode != NULL) xmlFree(mode);
5437 if (modeURI != NULL) xmlFree(modeURI);
5438 }
5439 prop = xmlGetNsProp(template, (const xmlChar *)"match", NULL);
5440 if (prop != NULL) {
5441 if (ret->match != NULL) xmlFree(ret->match);
5442 ret->match = prop;
5443 }
5444
5445 prop = xmlGetNsProp(template, (const xmlChar *)"priority", NULL);
5446 if (prop != NULL) {
5447 priority = xmlXPathStringEvalNumber(prop);
5448 ret->priority = (float) priority;
5449 xmlFree(prop);
5450 }
5451
5452 prop = xmlGetNsProp(template, (const xmlChar *)"name", NULL);
5453 if (prop != NULL) {
5454 const xmlChar *URI;
5455
5456 /*
5457 * TODO: Don't use xsltGetQNameURI().
5458 */
5459 URI = xsltGetQNameURI(template, &prop);
5460 if (prop == NULL) {
5461 if (style != NULL) style->errors++;
5462 goto error;
5463 } else {
5464 if (xmlValidateNCName(prop,0)) {
5465 xsltTransformError(NULL, style, template,
5466 "xsl:template : error invalid name '%s'\n", prop);
5467 if (style != NULL) style->errors++;
5468 xmlFree(prop);
5469 goto error;
5470 }
5471 ret->name = xmlDictLookup(style->dict, BAD_CAST prop, -1);
5472 xmlFree(prop);
5473 prop = NULL;
5474 if (URI != NULL)
5475 ret->nameURI = xmlDictLookup(style->dict, BAD_CAST URI, -1);
5476 else
5477 ret->nameURI = NULL;
5478 }
5479 }
5480
5481 /*
5482 * parse the content and register the pattern
5483 */
5485 ret->elem = template;
5486 ret->content = template->children;
5487 xsltAddTemplate(style, ret, ret->mode, ret->modeURI);
5488
5489error:
5490 return;
5491}
5492
5493#endif /* else XSLT_REFACTORED */
5494
5495#ifdef XSLT_REFACTORED
5496
5504static xsltStyleItemIncludePtr
5505xsltCompileXSLTIncludeElem(xsltCompilerCtxtPtr cctxt, xmlNodePtr node) {
5506 xsltStyleItemIncludePtr item;
5507
5508 if ((cctxt == NULL) || (node == NULL) || (node->type != XML_ELEMENT_NODE))
5509 return(NULL);
5510
5511 node->psvi = NULL;
5512 item = (xsltStyleItemIncludePtr) xmlMalloc(sizeof(xsltStyleItemInclude));
5513 if (item == NULL) {
5514 xsltTransformError(NULL, cctxt->style, node,
5515 "xsltIncludeComp : malloc failed\n");
5516 cctxt->style->errors++;
5517 return(NULL);
5518 }
5519 memset(item, 0, sizeof(xsltStyleItemInclude));
5520
5521 node->psvi = item;
5522 item->inst = node;
5523 item->type = XSLT_FUNC_INCLUDE;
5524
5525 item->next = cctxt->style->preComps;
5526 cctxt->style->preComps = (xsltElemPreCompPtr) item;
5527
5528 return(item);
5529}
5530
5531static int
5532xsltParseFindTopLevelElem(xsltCompilerCtxtPtr cctxt,
5533 xmlNodePtr cur,
5534 const xmlChar *name,
5535 const xmlChar *namespaceURI,
5536 int breakOnOtherElem,
5537 xmlNodePtr *resultNode)
5538{
5539 if (name == NULL)
5540 return(-1);
5541
5542 *resultNode = NULL;
5543 while (cur != NULL) {
5544 if (cur->type == XML_ELEMENT_NODE) {
5545 if ((cur->ns != NULL) && (cur->name != NULL)) {
5546 if ((*(cur->name) == *name) &&
5547 xmlStrEqual(cur->name, name) &&
5548 xmlStrEqual(cur->ns->href, namespaceURI))
5549 {
5550 *resultNode = cur;
5551 return(1);
5552 }
5553 }
5554 if (breakOnOtherElem)
5555 break;
5556 }
5557 cur = cur->next;
5558 }
5559 *resultNode = cur;
5560 return(0);
5561}
5562
5563static int
5564xsltParseTopLevelXSLTElem(xsltCompilerCtxtPtr cctxt,
5565 xmlNodePtr node,
5567{
5568 int ret = 0;
5569
5570 /*
5571 * TODO: The reason why this function exists:
5572 * due to historical reasons some of the
5573 * top-level declarations are processed by functions
5574 * in other files. Since we need still to set
5575 * up the node-info and generate information like
5576 * in-scope namespaces, this is a wrapper around
5577 * those old parsing functions.
5578 */
5579 xsltCompilerNodePush(cctxt, node);
5580 if (node->nsDef != NULL)
5581 cctxt->inode->inScopeNs =
5582 xsltCompilerBuildInScopeNsList(cctxt, node);
5583 cctxt->inode->type = type;
5584
5585 switch (type) {
5586 case XSLT_FUNC_INCLUDE:
5587 {
5588 int oldIsInclude;
5589
5590 if (xsltCompileXSLTIncludeElem(cctxt, node) == NULL)
5591 goto exit;
5592 /*
5593 * Mark this stylesheet tree as being currently included.
5594 */
5595 oldIsInclude = cctxt->isInclude;
5596 cctxt->isInclude = 1;
5597
5598 if (xsltParseStylesheetInclude(cctxt->style, node) != 0) {
5599 cctxt->style->errors++;
5600 }
5601 cctxt->isInclude = oldIsInclude;
5602 }
5603 break;
5604 case XSLT_FUNC_PARAM:
5605 xsltStylePreCompute(cctxt->style, node);
5606 xsltParseGlobalParam(cctxt->style, node);
5607 break;
5608 case XSLT_FUNC_VARIABLE:
5609 xsltStylePreCompute(cctxt->style, node);
5610 xsltParseGlobalVariable(cctxt->style, node);
5611 break;
5612 case XSLT_FUNC_ATTRSET:
5614 break;
5615 default:
5616 xsltTransformError(NULL, cctxt->style, node,
5617 "Internal error: (xsltParseTopLevelXSLTElem) "
5618 "Cannot handle this top-level declaration.\n");
5619 cctxt->style->errors++;
5620 ret = -1;
5621 }
5622
5623exit:
5624 xsltCompilerNodePop(cctxt, node);
5625
5626 return(ret);
5627}
5628
5629#if 0
5630static int
5631xsltParseRemoveWhitespace(xmlNodePtr node)
5632{
5633 if ((node == NULL) || (node->children == NULL))
5634 return(0);
5635 else {
5636 xmlNodePtr delNode = NULL, child = node->children;
5637
5638 do {
5639 if (delNode) {
5640 xmlUnlinkNode(delNode);
5641 xmlFreeNode(delNode);
5642 delNode = NULL;
5643 }
5644 if (((child->type == XML_TEXT_NODE) ||
5645 (child->type == XML_CDATA_SECTION_NODE)) &&
5647 delNode = child;
5648 child = child->next;
5649 } while (child != NULL);
5650 if (delNode) {
5651 xmlUnlinkNode(delNode);
5652 xmlFreeNode(delNode);
5653 delNode = NULL;
5654 }
5655 }
5656 return(0);
5657}
5658#endif
5659
5660static int
5661xsltParseXSLTStylesheetElemCore(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)
5662{
5663#ifdef WITH_XSLT_DEBUG_PARSING
5664 int templates = 0;
5665#endif
5666 xmlNodePtr cur, start = NULL;
5668
5669 if ((cctxt == NULL) || (node == NULL) ||
5670 (node->type != XML_ELEMENT_NODE))
5671 return(-1);
5672
5673 style = cctxt->style;
5674 /*
5675 * At this stage all import declarations of all stylesheet modules
5676 * with the same stylesheet level have been processed.
5677 * Now we can safely parse the rest of the declarations.
5678 */
5679 if (IS_XSLT_ELEM_FAST(node) && IS_XSLT_NAME(node, "include"))
5680 {
5682 /*
5683 * URGENT TODO: Make this work with simplified stylesheets!
5684 * I.e., when we won't find an xsl:stylesheet element.
5685 */
5686 /*
5687 * This is as include declaration.
5688 */
5689 include = ((xsltStyleItemIncludePtr) node->psvi)->include;
5690 if (include == NULL) {
5691 /* TODO: raise error? */
5692 return(-1);
5693 }
5694 /*
5695 * TODO: Actually an xsl:include should locate an embedded
5696 * stylesheet as well; so the document-element won't always
5697 * be the element where the actual stylesheet is rooted at.
5698 * But such embedded stylesheets are not supported by Libxslt yet.
5699 */
5700 node = xmlDocGetRootElement(include->doc);
5701 if (node == NULL) {
5702 return(-1);
5703 }
5704 }
5705
5706 if (node->children == NULL)
5707 return(0);
5708 /*
5709 * Push the xsl:stylesheet/xsl:transform element.
5710 */
5711 xsltCompilerNodePush(cctxt, node);
5712 cctxt->inode->isRoot = 1;
5713 cctxt->inode->nsChanged = 0;
5714 /*
5715 * Start with the naked dummy info for literal result elements.
5716 */
5717 cctxt->inode->litResElemInfo = cctxt->inodeList->litResElemInfo;
5718
5719 /*
5720 * In every case, we need to have
5721 * the in-scope namespaces of the element, where the
5722 * stylesheet is rooted at, regardless if it's an XSLT
5723 * instruction or a literal result instruction (or if
5724 * this is an embedded stylesheet).
5725 */
5726 cctxt->inode->inScopeNs =
5727 xsltCompilerBuildInScopeNsList(cctxt, node);
5728
5729 /*
5730 * Process attributes of xsl:stylesheet/xsl:transform.
5731 * --------------------------------------------------
5732 * Allowed are:
5733 * id = id
5734 * extension-element-prefixes = tokens
5735 * exclude-result-prefixes = tokens
5736 * version = number (mandatory)
5737 */
5738 if (xsltParseAttrXSLTVersion(cctxt, node,
5739 XSLT_ELEMENT_CATEGORY_XSLT) == 0)
5740 {
5741 /*
5742 * Attribute "version".
5743 * XSLT 1.0: "An xsl:stylesheet element *must* have a version
5744 * attribute, indicating the version of XSLT that the
5745 * stylesheet requires".
5746 * The root element of a simplified stylesheet must also have
5747 * this attribute.
5748 */
5749#ifdef XSLT_REFACTORED_MANDATORY_VERSION
5750 if (isXsltElem)
5751 xsltTransformError(NULL, cctxt->style, node,
5752 "The attribute 'version' is missing.\n");
5753 cctxt->style->errors++;
5754#else
5755 /* OLD behaviour. */
5756 xsltTransformError(NULL, cctxt->style, node,
5757 "xsl:version is missing: document may not be a stylesheet\n");
5758 cctxt->style->warnings++;
5759#endif
5760 }
5761 /*
5762 * The namespaces declared by the attributes
5763 * "extension-element-prefixes" and
5764 * "exclude-result-prefixes" are local to *this*
5765 * stylesheet tree; i.e., they are *not* visible to
5766 * other stylesheet-modules, whether imported or included.
5767 *
5768 * Attribute "extension-element-prefixes".
5769 */
5770 cctxt->inode->extElemNs =
5771 xsltParseExtElemPrefixes(cctxt, node, NULL,
5772 XSLT_ELEMENT_CATEGORY_XSLT);
5773 /*
5774 * Attribute "exclude-result-prefixes".
5775 */
5776 cctxt->inode->exclResultNs =
5777 xsltParseExclResultPrefixes(cctxt, node, NULL,
5778 XSLT_ELEMENT_CATEGORY_XSLT);
5779 /*
5780 * Create/reuse info for the literal result element.
5781 */
5782 if (cctxt->inode->nsChanged)
5783 xsltLREInfoCreate(cctxt, node, 0);
5784 /*
5785 * Processed top-level elements:
5786 * ----------------------------
5787 * xsl:variable, xsl:param (QName, in-scope ns,
5788 * expression (vars allowed))
5789 * xsl:attribute-set (QName, in-scope ns)
5790 * xsl:strip-space, xsl:preserve-space (XPath NameTests,
5791 * in-scope ns)
5792 * I *think* global scope, merge with includes
5793 * xsl:output (QName, in-scope ns)
5794 * xsl:key (QName, in-scope ns, pattern,
5795 * expression (vars *not* allowed))
5796 * xsl:decimal-format (QName, needs in-scope ns)
5797 * xsl:namespace-alias (in-scope ns)
5798 * global scope, merge with includes
5799 * xsl:template (last, QName, pattern)
5800 *
5801 * (whitespace-only text-nodes have *not* been removed
5802 * yet; this will be done in xsltParseSequenceConstructor)
5803 *
5804 * Report misplaced child-nodes first.
5805 */
5806 cur = node->children;
5807 while (cur != NULL) {
5808 if (cur->type == XML_TEXT_NODE) {
5810 "Misplaced text node (content: '%s').\n",
5811 (cur->content != NULL) ? cur->content : BAD_CAST "");
5812 style->errors++;
5813 } else if (cur->type != XML_ELEMENT_NODE) {
5814 xsltTransformError(NULL, style, cur, "Misplaced node.\n");
5815 style->errors++;
5816 }
5817 cur = cur->next;
5818 }
5819 /*
5820 * Skip xsl:import elements; they have been processed
5821 * already.
5822 */
5823 cur = node->children;
5824 while ((cur != NULL) && xsltParseFindTopLevelElem(cctxt, cur,
5825 BAD_CAST "import", XSLT_NAMESPACE, 1, &cur) == 1)
5826 cur = cur->next;
5827 if (cur == NULL)
5828 goto exit;
5829
5830 start = cur;
5831 /*
5832 * Process all top-level xsl:param elements.
5833 */
5834 while ((cur != NULL) &&
5835 xsltParseFindTopLevelElem(cctxt, cur,
5836 BAD_CAST "param", XSLT_NAMESPACE, 0, &cur) == 1)
5837 {
5838 xsltParseTopLevelXSLTElem(cctxt, cur, XSLT_FUNC_PARAM);
5839 cur = cur->next;
5840 }
5841 /*
5842 * Process all top-level xsl:variable elements.
5843 */
5844 cur = start;
5845 while ((cur != NULL) &&
5846 xsltParseFindTopLevelElem(cctxt, cur,
5847 BAD_CAST "variable", XSLT_NAMESPACE, 0, &cur) == 1)
5848 {
5849 xsltParseTopLevelXSLTElem(cctxt, cur, XSLT_FUNC_VARIABLE);
5850 cur = cur->next;
5851 }
5852 /*
5853 * Process all the rest of top-level elements.
5854 */
5855 cur = start;
5856 while (cur != NULL) {
5857 /*
5858 * Process element nodes.
5859 */
5860 if (cur->type == XML_ELEMENT_NODE) {
5861 if (cur->ns == NULL) {
5863 "Unexpected top-level element in no namespace.\n");
5864 style->errors++;
5865 cur = cur->next;
5866 continue;
5867 }
5868 /*
5869 * Process all XSLT elements.
5870 */
5871 if (IS_XSLT_ELEM_FAST(cur)) {
5872 /*
5873 * xsl:import is only allowed at the beginning.
5874 */
5875 if (IS_XSLT_NAME(cur, "import")) {
5877 "Misplaced xsl:import element.\n");
5878 style->errors++;
5879 cur = cur->next;
5880 continue;
5881 }
5882 /*
5883 * TODO: Change the return type of the parsing functions
5884 * to int.
5885 */
5886 if (IS_XSLT_NAME(cur, "template")) {
5887#ifdef WITH_XSLT_DEBUG_PARSING
5888 templates++;
5889#endif
5890 /*
5891 * TODO: Is the position of xsl:template in the
5892 * tree significant? If not it would be easier to
5893 * parse them at a later stage.
5894 */
5895 xsltParseXSLTTemplate(cctxt, cur);
5896 } else if (IS_XSLT_NAME(cur, "variable")) {
5897 /* NOP; done already */
5898 } else if (IS_XSLT_NAME(cur, "param")) {
5899 /* NOP; done already */
5900 } else if (IS_XSLT_NAME(cur, "include")) {
5901 if (cur->psvi != NULL)
5902 xsltParseXSLTStylesheetElemCore(cctxt, cur);
5903 else {
5905 "Internal error: "
5906 "(xsltParseXSLTStylesheetElemCore) "
5907 "The xsl:include element was not compiled.\n");
5908 style->errors++;
5909 }
5910 } else if (IS_XSLT_NAME(cur, "strip-space")) {
5911 /* No node info needed. */
5913 } else if (IS_XSLT_NAME(cur, "preserve-space")) {
5914 /* No node info needed. */
5916 } else if (IS_XSLT_NAME(cur, "output")) {
5917 /* No node-info needed. */
5919 } else if (IS_XSLT_NAME(cur, "key")) {
5920 /* TODO: node-info needed for expressions ? */
5922 } else if (IS_XSLT_NAME(cur, "decimal-format")) {
5923 /* No node-info needed. */
5925 } else if (IS_XSLT_NAME(cur, "attribute-set")) {
5926 xsltParseTopLevelXSLTElem(cctxt, cur,
5927 XSLT_FUNC_ATTRSET);
5928 } else if (IS_XSLT_NAME(cur, "namespace-alias")) {
5929 /* NOP; done already */
5930 } else {
5931 if (cctxt->inode->forwardsCompat) {
5932 /*
5933 * Forwards-compatible mode:
5934 *
5935 * XSLT-1: "if it is a top-level element and
5936 * XSLT 1.0 does not allow such elements as top-level
5937 * elements, then the element must be ignored along
5938 * with its content;"
5939 */
5940 /*
5941 * TODO: I don't think we should generate a warning.
5942 */
5944 "Forwards-compatible mode: Ignoring unknown XSLT "
5945 "element '%s'.\n", cur->name);
5946 style->warnings++;
5947 } else {
5949 "Unknown XSLT element '%s'.\n", cur->name);
5950 style->errors++;
5951 }
5952 }
5953 } else {
5954 xsltTopLevelFunction function;
5955
5956 /*
5957 * Process non-XSLT elements, which are in a
5958 * non-NULL namespace.
5959 */
5960 /*
5961 * QUESTION: What does xsltExtModuleTopLevelLookup()
5962 * do exactly?
5963 */
5964 function = xsltExtModuleTopLevelLookup(cur->name,
5965 cur->ns->href);
5966 if (function != NULL)
5967 function(style, cur);
5968#ifdef WITH_XSLT_DEBUG_PARSING
5970 "xsltParseXSLTStylesheetElemCore : User-defined "
5971 "data element '%s'.\n", cur->name);
5972#endif
5973 }
5974 }
5975 cur = cur->next;
5976 }
5977
5978exit:
5979
5980#ifdef WITH_XSLT_DEBUG_PARSING
5982 "### END of parsing top-level elements of doc '%s'.\n",
5983 node->doc->URL);
5985 "### Templates: %d\n", templates);
5986#ifdef XSLT_REFACTORED
5988 "### Max inodes: %d\n", cctxt->maxNodeInfos);
5990 "### Max LREs : %d\n", cctxt->maxLREs);
5991#endif /* XSLT_REFACTORED */
5992#endif /* WITH_XSLT_DEBUG_PARSING */
5993
5994 xsltCompilerNodePop(cctxt, node);
5995 return(0);
5996}
5997
6020static int
6021xsltParseXSLTStylesheetElem(xsltCompilerCtxtPtr cctxt, xmlNodePtr node)
6022{
6023 xmlNodePtr cur, start;
6024
6025 if ((cctxt == NULL) || (node == NULL) || (node->type != XML_ELEMENT_NODE))
6026 return(-1);
6027
6028 if (node->children == NULL)
6029 goto exit;
6030
6031 /*
6032 * Process top-level elements:
6033 * xsl:import (must be first)
6034 * xsl:include (this is just a pre-processing)
6035 */
6036 cur = node->children;
6037 /*
6038 * Process xsl:import elements.
6039 * XSLT 1.0: "The xsl:import element children must precede all
6040 * other element children of an xsl:stylesheet element,
6041 * including any xsl:include element children."
6042 */
6043 while ((cur != NULL) &&
6044 xsltParseFindTopLevelElem(cctxt, cur,
6045 BAD_CAST "import", XSLT_NAMESPACE, 1, &cur) == 1)
6046 {
6047 if (xsltParseStylesheetImport(cctxt->style, cur) != 0) {
6048 cctxt->style->errors++;
6049 }
6050 cur = cur->next;
6051 }
6052 if (cur == NULL)
6053 goto exit;
6054 start = cur;
6055 /*
6056 * Pre-process all xsl:include elements.
6057 */
6058 cur = start;
6059 while ((cur != NULL) &&
6060 xsltParseFindTopLevelElem(cctxt, cur,
6061 BAD_CAST "include", XSLT_NAMESPACE, 0, &cur) == 1)
6062 {
6063 xsltParseTopLevelXSLTElem(cctxt, cur, XSLT_FUNC_INCLUDE);
6064 cur = cur->next;
6065 }
6066 /*
6067 * Pre-process all xsl:namespace-alias elements.
6068 * URGENT TODO: This won't work correctly: the order of included
6069 * aliases and aliases defined here is significant.
6070 */
6071 cur = start;
6072 while ((cur != NULL) &&
6073 xsltParseFindTopLevelElem(cctxt, cur,
6074 BAD_CAST "namespace-alias", XSLT_NAMESPACE, 0, &cur) == 1)
6075 {
6076 xsltNamespaceAlias(cctxt->style, cur);
6077 cur = cur->next;
6078 }
6079
6080 if (cctxt->isInclude) {
6081 /*
6082 * If this stylesheet is intended for inclusion, then
6083 * we will process only imports and includes.
6084 */
6085 goto exit;
6086 }
6087 /*
6088 * Now parse the rest of the top-level elements.
6089 */
6090 xsltParseXSLTStylesheetElemCore(cctxt, node);
6091exit:
6092
6093 return(0);
6094}
6095
6096#else /* XSLT_REFACTORED */
6097
6105static void
6107 xmlNodePtr cur;
6108 xmlChar *prop;
6109#ifdef WITH_XSLT_DEBUG_PARSING
6110 int templates = 0;
6111#endif
6112
6113 if ((top == NULL) || (top->type != XML_ELEMENT_NODE))
6114 return;
6115
6116 if (style->principal->opLimit > 0) {
6117 if (style->principal->opCount > style->principal->opLimit) {
6119 "XSLT parser operation limit exceeded\n");
6120 style->errors++;
6121 return;
6122 }
6123 }
6124
6125 prop = xmlGetNsProp(top, (const xmlChar *)"version", NULL);
6126 if (prop == NULL) {
6128 "xsl:version is missing: document may not be a stylesheet\n");
6129 if (style != NULL) style->warnings++;
6130 } else {
6131 if ((!xmlStrEqual(prop, (const xmlChar *)"1.0")) &&
6132 (!xmlStrEqual(prop, (const xmlChar *)"1.1"))) {
6134 "xsl:version: only 1.1 features are supported\n");
6135 if (style != NULL) {
6136 style->forwards_compatible = 1;
6137 style->warnings++;
6138 }
6139 }
6140 xmlFree(prop);
6141 }
6142
6143 /*
6144 * process xsl:import elements
6145 */
6146 cur = top->children;
6147 while (cur != NULL) {
6148 style->principal->opCount += 1;
6149
6150 if (IS_BLANK_NODE(cur)) {
6151 cur = cur->next;
6152 continue;
6153 }
6154 if (IS_XSLT_ELEM(cur) && IS_XSLT_NAME(cur, "import")) {
6156 if (style != NULL) style->errors++;
6157 } else
6158 break;
6159 cur = cur->next;
6160 }
6161
6162 /*
6163 * process other top-level elements
6164 */
6165 while (cur != NULL) {
6166 style->principal->opCount += 1;
6167
6168 if (IS_BLANK_NODE(cur)) {
6169 cur = cur->next;
6170 continue;
6171 }
6172 if (cur->type == XML_TEXT_NODE) {
6173 if (cur->content != NULL) {
6175 "misplaced text node: '%s'\n", cur->content);
6176 }
6177 if (style != NULL) style->errors++;
6178 cur = cur->next;
6179 continue;
6180 }
6181 if ((cur->type == XML_ELEMENT_NODE) && (cur->ns == NULL)) {
6183 "Found a top-level element %s with null namespace URI\n",
6184 cur->name);
6185 if (style != NULL) style->errors++;
6186 cur = cur->next;
6187 continue;
6188 }
6189 if ((cur->type == XML_ELEMENT_NODE) && (!(IS_XSLT_ELEM(cur)))) {
6190 xsltTopLevelFunction function;
6191
6192 function = xsltExtModuleTopLevelLookup(cur->name,
6193 cur->ns->href);
6194 if (function != NULL)
6195 function(style, cur);
6196
6197#ifdef WITH_XSLT_DEBUG_PARSING
6199 "xsltParseStylesheetTop : found foreign element %s\n",
6200 cur->name);
6201#endif
6202 cur = cur->next;
6203 continue;
6204 }
6205 if (IS_XSLT_NAME(cur, "import")) {
6207 "xsltParseStylesheetTop: ignoring misplaced import element\n");
6208 if (style != NULL) style->errors++;
6209 } else if (IS_XSLT_NAME(cur, "include")) {
6211 if (style != NULL) style->errors++;
6212 } else if (IS_XSLT_NAME(cur, "strip-space")) {
6214 } else if (IS_XSLT_NAME(cur, "preserve-space")) {
6216 } else if (IS_XSLT_NAME(cur, "output")) {
6218 } else if (IS_XSLT_NAME(cur, "key")) {
6220 } else if (IS_XSLT_NAME(cur, "decimal-format")) {
6222 } else if (IS_XSLT_NAME(cur, "attribute-set")) {
6224 } else if (IS_XSLT_NAME(cur, "variable")) {
6226 } else if (IS_XSLT_NAME(cur, "param")) {
6228 } else if (IS_XSLT_NAME(cur, "template")) {
6229#ifdef WITH_XSLT_DEBUG_PARSING
6230 templates++;
6231#endif
6233 } else if (IS_XSLT_NAME(cur, "namespace-alias")) {
6235 } else {
6236 if ((style != NULL) && (style->forwards_compatible == 0)) {
6238 "xsltParseStylesheetTop: unknown %s element\n",
6239 cur->name);
6240 if (style != NULL) style->errors++;
6241 }
6242 }
6243 cur = cur->next;
6244 }
6245#ifdef WITH_XSLT_DEBUG_PARSING
6247 "parsed %d templates\n", templates);
6248#endif
6249}
6250
6251#endif /* else of XSLT_REFACTORED */
6252
6253#ifdef XSLT_REFACTORED
6264static int
6265xsltParseSimplifiedStylesheetTree(xsltCompilerCtxtPtr cctxt,
6266 xmlDocPtr doc,
6267 xmlNodePtr node)
6268{
6269 xsltTemplatePtr templ;
6270
6271 if ((cctxt == NULL) || (node == NULL))
6272 return(-1);
6273
6274 if (xsltParseAttrXSLTVersion(cctxt, node, 0) == XSLT_ELEMENT_CATEGORY_LRE)
6275 {
6276 /*
6277 * TODO: Adjust report, since this might be an
6278 * embedded stylesheet.
6279 */
6280 xsltTransformError(NULL, cctxt->style, node,
6281 "The attribute 'xsl:version' is missing; cannot identify "
6282 "this document as an XSLT stylesheet document.\n");
6283 cctxt->style->errors++;
6284 return(1);
6285 }
6286
6287#ifdef WITH_XSLT_DEBUG_PARSING
6289 "xsltParseSimplifiedStylesheetTree: document is stylesheet\n");
6290#endif
6291
6292 /*
6293 * Create and link the template
6294 */
6295 templ = xsltNewTemplate();
6296 if (templ == NULL) {
6297 return(-1);
6298 }
6299 templ->next = cctxt->style->templates;
6300 cctxt->style->templates = templ;
6301 templ->match = xmlStrdup(BAD_CAST "/");
6302
6303 /*
6304 * Note that we push the document-node in this special case.
6305 */
6306 xsltCompilerNodePush(cctxt, (xmlNodePtr) doc);
6307 /*
6308 * In every case, we need to have
6309 * the in-scope namespaces of the element, where the
6310 * stylesheet is rooted at, regardless if it's an XSLT
6311 * instruction or a literal result instruction (or if
6312 * this is an embedded stylesheet).
6313 */
6314 cctxt->inode->inScopeNs =
6315 xsltCompilerBuildInScopeNsList(cctxt, node);
6316 /*
6317 * Parse the content and register the match-pattern.
6318 */
6319 xsltParseSequenceConstructor(cctxt, node);
6320 xsltCompilerNodePop(cctxt, (xmlNodePtr) doc);
6321
6322 templ->elem = (xmlNodePtr) doc;
6323 templ->content = node;
6324 xsltAddTemplate(cctxt->style, templ, NULL, NULL);
6325 cctxt->style->literal_result = 1;
6326 return(0);
6327}
6328
6329#ifdef XSLT_REFACTORED_XSLT_NSCOMP
6339int
6340xsltRestoreDocumentNamespaces(xsltNsMapPtr ns, xmlDocPtr doc)
6341{
6342 if (doc == NULL)
6343 return(-1);
6344 /*
6345 * Revert the changes we have applied to the namespace-URIs of
6346 * ns-decls.
6347 */
6348 while (ns != NULL) {
6349 if ((ns->doc == doc) && (ns->ns != NULL)) {
6350 ns->ns->href = ns->origNsName;
6351 ns->origNsName = NULL;
6352 ns->ns = NULL;
6353 }
6354 ns = ns->next;
6355 }
6356 return(0);
6357}
6358#endif /* XSLT_REFACTORED_XSLT_NSCOMP */
6359
6375{
6376 xsltCompilerCtxtPtr cctxt;
6377 xmlNodePtr cur;
6378 int oldIsSimplifiedStylesheet;
6379
6381
6382 if ((style == NULL) || (doc == NULL))
6383 return(NULL);
6384
6385 cctxt = XSLT_CCTXT(style);
6386
6387 cur = xmlDocGetRootElement(doc);
6388 if (cur == NULL) {
6389 xsltTransformError(NULL, style, (xmlNodePtr) doc,
6390 "xsltParseStylesheetProcess : empty stylesheet\n");
6391 return(NULL);
6392 }
6393 oldIsSimplifiedStylesheet = cctxt->simplified;
6394
6395 if ((IS_XSLT_ELEM(cur)) &&
6396 ((IS_XSLT_NAME(cur, "stylesheet")) ||
6397 (IS_XSLT_NAME(cur, "transform")))) {
6398#ifdef WITH_XSLT_DEBUG_PARSING
6400 "xsltParseStylesheetProcess : found stylesheet\n");
6401#endif
6402 cctxt->simplified = 0;
6403 style->literal_result = 0;
6404 } else {
6405 cctxt->simplified = 1;
6406 style->literal_result = 1;
6407 }
6408 /*
6409 * Pre-process the stylesheet if not already done before.
6410 * This will remove PIs and comments, merge adjacent
6411 * text nodes, internalize strings, etc.
6412 */
6413 if (! style->nopreproc)
6414 xsltParsePreprocessStylesheetTree(cctxt, cur);
6415 /*
6416 * Parse and compile the stylesheet.
6417 */
6418 if (style->literal_result == 0) {
6419 if (xsltParseXSLTStylesheetElem(cctxt, cur) != 0)
6420 return(NULL);
6421 } else {
6422 if (xsltParseSimplifiedStylesheetTree(cctxt, doc, cur) != 0)
6423 return(NULL);
6424 }
6425
6426 cctxt->simplified = oldIsSimplifiedStylesheet;
6427
6428 return(style);
6429}
6430
6431#else /* XSLT_REFACTORED */
6432
6448 xmlNodePtr cur;
6449
6451
6452 if (doc == NULL)
6453 return(NULL);
6454 if (ret == NULL)
6455 return(ret);
6456
6457 /*
6458 * First steps, remove blank nodes,
6459 * locate the xsl:stylesheet element and the
6460 * namespace declaration.
6461 */
6462 cur = xmlDocGetRootElement(doc);
6463 if (cur == NULL) {
6464 xsltTransformError(NULL, ret, (xmlNodePtr) doc,
6465 "xsltParseStylesheetProcess : empty stylesheet\n");
6466 return(NULL);
6467 }
6468
6469 if ((IS_XSLT_ELEM(cur)) &&
6470 ((IS_XSLT_NAME(cur, "stylesheet")) ||
6471 (IS_XSLT_NAME(cur, "transform")))) {
6472#ifdef WITH_XSLT_DEBUG_PARSING
6474 "xsltParseStylesheetProcess : found stylesheet\n");
6475#endif
6476 ret->literal_result = 0;
6479 } else {
6482 ret->literal_result = 1;
6483 }
6484 if (!ret->nopreproc) {
6486 }
6487 if (ret->literal_result == 0) {
6489 } else {
6490 xmlChar *prop;
6491 xsltTemplatePtr template;
6492
6493 /*
6494 * the document itself might be the template, check xsl:version
6495 */
6496 prop = xmlGetNsProp(cur, (const xmlChar *)"version", XSLT_NAMESPACE);
6497 if (prop == NULL) {
6499 "xsltParseStylesheetProcess : document is not a stylesheet\n");
6500 return(NULL);
6501 }
6502
6503#ifdef WITH_XSLT_DEBUG_PARSING
6505 "xsltParseStylesheetProcess : document is stylesheet\n");
6506#endif
6507
6508 if ((!xmlStrEqual(prop, (const xmlChar *)"1.0")) &&
6509 (!xmlStrEqual(prop, (const xmlChar *)"1.1"))) {
6511 "xsl:version: only 1.1 features are supported\n");
6512 ret->forwards_compatible = 1;
6513 ret->warnings++;
6514 }
6515 xmlFree(prop);
6516
6517 /*
6518 * Create and link the template
6519 */
6520 template = xsltNewTemplate();
6521 if (template == NULL) {
6522 return(NULL);
6523 }
6524 template->next = ret->templates;
6525 ret->templates = template;
6526 template->match = xmlStrdup((const xmlChar *)"/");
6527
6528 /*
6529 * parse the content and register the pattern
6530 */
6531 xsltParseTemplateContent(ret, (xmlNodePtr) doc);
6532 template->elem = (xmlNodePtr) doc;
6533 template->content = doc->children;
6534 xsltAddTemplate(ret, template, NULL, NULL);
6535 ret->literal_result = 1;
6536 }
6537
6538 return(ret);
6539}
6540
6541#endif /* else of XSLT_REFACTORED */
6542
6556 xsltStylesheetPtr parentStyle) {
6557 xsltStylesheetPtr retStyle;
6558
6559 if (doc == NULL)
6560 return(NULL);
6561
6562 retStyle = xsltNewStylesheetInternal(parentStyle);
6563 if (retStyle == NULL)
6564 return(NULL);
6565
6566 if (xsltParseStylesheetUser(retStyle, doc) != 0) {
6567 xsltFreeStylesheet(retStyle);
6568 return(NULL);
6569 }
6570
6571 return(retStyle);
6572}
6573
6583int
6585 if ((style == NULL) || (doc == NULL))
6586 return(-1);
6587
6588 /*
6589 * Adjust the string dict.
6590 */
6591 if (doc->dict != NULL) {
6592 xmlDictFree(style->dict);
6593 style->dict = doc->dict;
6594#ifdef WITH_XSLT_DEBUG
6596 "reusing dictionary from %s for stylesheet\n",
6597 doc->URL);
6598#endif
6599 xmlDictReference(style->dict);
6600 }
6601
6602 /*
6603 * TODO: Eliminate xsltGatherNamespaces(); we must not restrict
6604 * the stylesheet to containt distinct namespace prefixes.
6605 */
6607
6608#ifdef XSLT_REFACTORED
6609 {
6610 xsltCompilerCtxtPtr cctxt;
6611 xsltStylesheetPtr oldCurSheet;
6612
6613 if (style->parent == NULL) {
6614 xsltPrincipalStylesheetDataPtr principalData;
6615 /*
6616 * Create extra data for the principal stylesheet.
6617 */
6618 principalData = xsltNewPrincipalStylesheetData();
6619 if (principalData == NULL) {
6620 return(-1);
6621 }
6622 style->principalData = principalData;
6623 /*
6624 * Create the compilation context
6625 * ------------------------------
6626 * (only once; for the principal stylesheet).
6627 * This is currently the only function where the
6628 * compilation context is created.
6629 */
6630 cctxt = xsltCompilationCtxtCreate(style);
6631 if (cctxt == NULL) {
6632 return(-1);
6633 }
6634 style->compCtxt = (void *) cctxt;
6635 cctxt->style = style;
6636 cctxt->dict = style->dict;
6637 cctxt->psData = principalData;
6638 /*
6639 * Push initial dummy node info.
6640 */
6641 cctxt->depth = -1;
6642 xsltCompilerNodePush(cctxt, (xmlNodePtr) doc);
6643 } else {
6644 /*
6645 * Imported stylesheet.
6646 */
6647 cctxt = style->parent->compCtxt;
6648 style->compCtxt = cctxt;
6649 }
6650 /*
6651 * Save the old and set the current stylesheet structure in the
6652 * compilation context.
6653 */
6654 oldCurSheet = cctxt->style;
6655 cctxt->style = style;
6656
6657 style->doc = doc;
6659
6660 cctxt->style = oldCurSheet;
6661 if (style->parent == NULL) {
6662 /*
6663 * Pop the initial dummy node info.
6664 */
6665 xsltCompilerNodePop(cctxt, (xmlNodePtr) doc);
6666 } else {
6667 /*
6668 * Clear the compilation context of imported
6669 * stylesheets.
6670 * TODO: really?
6671 */
6672 /* style->compCtxt = NULL; */
6673 }
6674
6675#ifdef XSLT_REFACTORED_XSLT_NSCOMP
6676 if (style->errors != 0) {
6677 /*
6678 * Restore all changes made to namespace URIs of ns-decls.
6679 */
6680 if (cctxt->psData->nsMap)
6681 xsltRestoreDocumentNamespaces(cctxt->psData->nsMap, doc);
6682 }
6683#endif
6684
6685 if (style->parent == NULL) {
6686 xsltCompilationCtxtFree(style->compCtxt);
6687 style->compCtxt = NULL;
6688 }
6689 }
6690
6691#else /* XSLT_REFACTORED */
6692 /*
6693 * Old behaviour.
6694 */
6695 style->doc = doc;
6696 if (xsltParseStylesheetProcess(style, doc) == NULL) {
6697 style->doc = NULL;
6698 return(-1);
6699 }
6700#endif /* else of XSLT_REFACTORED */
6701
6702 if (style->parent == NULL)
6704
6705 if (style->errors != 0) {
6706 /*
6707 * Detach the doc from the stylesheet; otherwise the doc
6708 * will be freed in xsltFreeStylesheet().
6709 */
6710 style->doc = NULL;
6711 /*
6712 * Cleanup the doc if its the main stylesheet.
6713 */
6714 if (style->parent == NULL)
6715 xsltCleanupStylesheetTree(doc, xmlDocGetRootElement(doc));
6716 return(-1);
6717 }
6718
6719 return(0);
6720}
6721
6738
6740}
6741
6755 xmlDocPtr doc;
6756
6758
6759 if (filename == NULL)
6760 return(NULL);
6761
6762#ifdef WITH_XSLT_DEBUG_PARSING
6764 "xsltParseStylesheetFile : parse %s\n", filename);
6765#endif
6766
6767 /*
6768 * Security framework check
6769 */
6771 if (sec != NULL) {
6772 int res;
6773
6774 res = xsltCheckRead(sec, NULL, filename);
6775 if (res <= 0) {
6776 if (res == 0)
6778 "xsltParseStylesheetFile: read rights for %s denied\n",
6779 filename);
6780 return(NULL);
6781 }
6782 }
6783
6786 if (doc == NULL) {
6788 "xsltParseStylesheetFile : cannot parse %s\n", filename);
6789 return(NULL);
6790 }
6792 if (ret == NULL) {
6793 xmlFreeDoc(doc);
6794 return(NULL);
6795 }
6796
6797 return(ret);
6798}
6799
6800/************************************************************************
6801 * *
6802 * Handling of Stylesheet PI *
6803 * *
6804 ************************************************************************/
6805
6806#define CUR (*cur)
6807#define SKIP(val) cur += (val)
6808#define NXT(val) cur[(val)]
6809#define SKIP_BLANKS \
6810 while (IS_BLANK(CUR)) NEXT
6811#define NEXT ((*cur) ? cur++ : cur)
6812
6823static xmlChar *
6825 const xmlChar *cur;
6826 const xmlChar *start;
6827 xmlChar *val;
6828 xmlChar tmp;
6829 xmlChar *href = NULL;
6830 int isXml = 0;
6831
6832 if (value == NULL)
6833 return(NULL);
6834
6835 cur = value;
6836 while (CUR != 0) {
6838 if ((CUR == 't') && (NXT(1) == 'y') && (NXT(2) == 'p') &&
6839 (NXT(3) == 'e')) {
6840 SKIP(4);
6842 if (CUR != '=')
6843 continue;
6844 NEXT;
6845 if ((CUR != '\'') && (CUR != '"'))
6846 continue;
6847 tmp = CUR;
6848 NEXT;
6849 start = cur;
6850 while ((CUR != 0) && (CUR != tmp))
6851 NEXT;
6852 if (CUR != tmp)
6853 continue;
6855 NEXT;
6856 if (val == NULL)
6857 return(NULL);
6858 if ((xmlStrcasecmp(val, BAD_CAST "text/xml")) &&
6859 (xmlStrcasecmp(val, BAD_CAST "text/xsl")) &&
6860 (xmlStrcasecmp(val, BAD_CAST "application/xslt+xml"))) {
6861 xmlFree(val);
6862 break;
6863 }
6864 isXml = 1;
6865 xmlFree(val);
6866 } else if ((CUR == 'h') && (NXT(1) == 'r') && (NXT(2) == 'e') &&
6867 (NXT(3) == 'f')) {
6868 SKIP(4);
6870 if (CUR != '=')
6871 continue;
6872 NEXT;
6873 if ((CUR != '\'') && (CUR != '"'))
6874 continue;
6875 tmp = CUR;
6876 NEXT;
6877 start = cur;
6878 while ((CUR != 0) && (CUR != tmp))
6879 NEXT;
6880 if (CUR != tmp)
6881 continue;
6882 if (href == NULL)
6883 href = xmlStrndup(start, cur - start);
6884 NEXT;
6885 } else {
6886 while ((CUR != 0) && (!IS_BLANK(CUR)))
6887 NEXT;
6888 }
6889
6890 }
6891
6892 if (!isXml) {
6893 if (href != NULL)
6894 xmlFree(href);
6895 href = NULL;
6896 }
6897 return(href);
6898}
6899
6915xsltLoadStylesheetPI(xmlDocPtr doc) {
6916 xmlNodePtr child;
6918 xmlChar *href = NULL;
6919 xmlURIPtr URI;
6920
6922
6923 if (doc == NULL)
6924 return(NULL);
6925
6926 /*
6927 * Find the text/xml stylesheet PI id any before the root
6928 */
6929 child = doc->children;
6930 while ((child != NULL) && (child->type != XML_ELEMENT_NODE)) {
6931 if ((child->type == XML_PI_NODE) &&
6932 (xmlStrEqual(child->name, BAD_CAST "xml-stylesheet"))) {
6933 href = xsltParseStylesheetPI(child->content);
6934 if (href != NULL)
6935 break;
6936 }
6937 child = child->next;
6938 }
6939
6940 /*
6941 * If found check the href to select processing
6942 */
6943 if (href != NULL) {
6944#ifdef WITH_XSLT_DEBUG_PARSING
6946 "xsltLoadStylesheetPI : found PI href=%s\n", href);
6947#endif
6948 URI = xmlParseURI((const char *) href);
6949 if (URI == NULL) {
6951 "xml-stylesheet : href %s is not valid\n", href);
6952 xmlFree(href);
6953 return(NULL);
6954 }
6955 if ((URI->fragment != NULL) && (URI->scheme == NULL) &&
6956 (URI->opaque == NULL) && (URI->authority == NULL) &&
6957 (URI->server == NULL) && (URI->user == NULL) &&
6958 (URI->path == NULL) && (URI->query == NULL)) {
6959 xmlAttrPtr ID;
6960
6961#ifdef WITH_XSLT_DEBUG_PARSING
6963 "xsltLoadStylesheetPI : Reference to ID %s\n", href);
6964#endif
6965 if (URI->fragment[0] == '#')
6966 ID = xmlGetID(doc, (const xmlChar *) &(URI->fragment[1]));
6967 else
6968 ID = xmlGetID(doc, (const xmlChar *) URI->fragment);
6969 if (ID == NULL) {
6971 "xml-stylesheet : no ID %s found\n", URI->fragment);
6972 } else {
6973 xmlDocPtr fake;
6974 xmlNodePtr subtree, newtree;
6975 xmlNsPtr ns;
6976
6977#ifdef WITH_XSLT_DEBUG
6979 "creating new document from %s for embedded stylesheet\n",
6980 doc->URL);
6981#endif
6982 /*
6983 * move the subtree in a new document passed to
6984 * the stylesheet analyzer
6985 */
6986 subtree = ID->parent;
6987 fake = xmlNewDoc(NULL);
6988 if (fake != NULL) {
6989 /*
6990 * Should the dictionary still be shared even though
6991 * the nodes are being copied rather than moved?
6992 */
6993 fake->dict = doc->dict;
6994 xmlDictReference(doc->dict);
6995#ifdef WITH_XSLT_DEBUG
6997 "reusing dictionary from %s for embedded stylesheet\n",
6998 doc->URL);
6999#endif
7000
7001 newtree = xmlDocCopyNode(subtree, fake, 1);
7002
7003 fake->URL = xmlNodeGetBase(doc, subtree->parent);
7004#ifdef WITH_XSLT_DEBUG
7006 "set base URI for embedded stylesheet as %s\n",
7007 fake->URL);
7008#endif
7009
7010 /*
7011 * Add all namespaces in scope of embedded stylesheet to
7012 * root element of newly created stylesheet document
7013 */
7014 while ((subtree = subtree->parent) != (xmlNodePtr)doc) {
7015 for (ns = subtree->ns; ns; ns = ns->next) {
7016 xmlNewNs(newtree, ns->href, ns->prefix);
7017 }
7018 }
7019
7020 xmlAddChild((xmlNodePtr)fake, newtree);
7022 if (ret == NULL)
7023 xmlFreeDoc(fake);
7024 }
7025 }
7026 } else {
7027 xmlChar *URL, *base;
7028
7029 /*
7030 * Reference to an external stylesheet
7031 */
7032
7033 base = xmlNodeGetBase(doc, (xmlNodePtr) doc);
7034 URL = xmlBuildURI(href, base);
7035 if (URL != NULL) {
7036#ifdef WITH_XSLT_DEBUG_PARSING
7038 "xsltLoadStylesheetPI : fetching %s\n", URL);
7039#endif
7041 xmlFree(URL);
7042 } else {
7043#ifdef WITH_XSLT_DEBUG_PARSING
7045 "xsltLoadStylesheetPI : fetching %s\n", href);
7046#endif
7048 }
7049 if (base != NULL)
7050 xmlFree(base);
7051 }
7052 xmlFreeURI(URI);
7053 xmlFree(href);
7054 }
7055 return(ret);
7056}
int xsltCheckExtURI(xsltStylesheetPtr style, const xmlChar *URI)
Definition: extensions.c:1243
int xsltCheckExtPrefix(xsltStylesheetPtr style, const xmlChar *URI)
Definition: extensions.c:1183
xsltElemPreCompPtr xsltPreComputeExtModuleElement(xsltStylesheetPtr style, xmlNodePtr inst)
Definition: extensions.c:1583
void xsltShutdownExts(xsltStylesheetPtr style)
Definition: extensions.c:1158
void xsltInitGlobals(void)
Definition: extensions.c:2282
void xsltFreeExts(xsltStylesheetPtr style)
Definition: extensions.c:501
int xsltRegisterExtPrefix(xsltStylesheetPtr style, const xmlChar *prefix, const xmlChar *URI)
Definition: extensions.c:525
xsltTopLevelFunction xsltExtModuleTopLevelLookup(const xmlChar *name, const xmlChar *URI)
Definition: extensions.c:1881
void xsltRegisterAllExtras(void)
Definition: extra.c:167
void xsltFreeStylePreComps(xsltStylesheetPtr style)
Definition: preproc.c:1951
void xsltStylePreCompute(xsltStylesheetPtr style, xmlNodePtr inst)
Definition: preproc.c:2191
const xmlChar * xsltExtMarker
Definition: preproc.c:48
_STLP_BEGIN_NAMESPACE _STLP_INLINE_LOOP _Function for_each(_InputIter __first, _InputIter __last, _Function __f)
Definition: _algo.h:59
_STLP_INLINE_LOOP _STLP_STD::pair< _InputIter1, _InputIter2 > mismatch(_InputIter1 __first1, _InputIter1 __last1, _InputIter2 __first2)
Definition: _algobase.h:522
Arabic default style
Definition: afstyles.h:94
void xsltFreeAVTList(void *avt)
Definition: attrvt.c:131
void xsltCompileAttr(xsltStylesheetPtr style, xmlAttrPtr attr)
Definition: attrvt.c:177
const WCHAR * alias
Definition: main.c:67
Definition: list.h:37
static SIZE_T const char const D3D_SHADER_MACRO ID3DInclude * include
Definition: asm.c:31
#define NULL
Definition: types.h:112
void xsltResolveStylesheetAttributeSet(xsltStylesheetPtr style)
Definition: attributes.c:701
void xsltParseStylesheetAttributeSet(xsltStylesheetPtr style, xmlNodePtr cur)
Definition: attributes.c:368
void xsltFreeAttributeSetsHashes(xsltStylesheetPtr style)
Definition: attributes.c:1237
int xsltAddTemplate(xsltStylesheetPtr style, xsltTemplatePtr cur, const xmlChar *mode, const xmlChar *modeURI)
Definition: pattern.c:2030
void xsltFreeTemplateHashes(xsltStylesheetPtr style)
Definition: pattern.c:2512
xsltSecurityPrefsPtr xsltGetDefaultSecurityPrefs(void)
Definition: security.c:180
int xsltCheckRead(xsltSecurityPrefsPtr sec, xsltTransformContextPtr ctxt, const xmlChar *URL)
Definition: security.c:419
const UINT template
Definition: action.c:7511
const WCHAR * text
Definition: package.c:1794
void xsltFreeStyleDocuments(xsltStylesheetPtr style)
Definition: documents.c:208
xsltDocLoaderFunc xsltDocDefaultLoader
Definition: documents.c:108
@ XSLT_LOAD_START
Definition: documents.h:54
return ret
Definition: mutex.c:146
r parent
Definition: btrfs.c:3010
void(* xsltTopLevelFunction)(xsltStylesheetPtr style, xmlNodePtr inst)
Definition: extensions.h:183
FxCollectionEntry * cur
GLuint start
Definition: gl.h:1545
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLuint GLuint end
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLuint res
Definition: glext.h:9613
GLdouble GLdouble GLdouble GLdouble top
Definition: glext.h:10859
GLenum mode
Definition: glext.h:6217
const GLint * first
Definition: glext.h:5794
GLuint GLfloat * val
Definition: glext.h:7180
GLuint64EXT * result
Definition: glext.h:11304
GLuint GLuint num
Definition: glext.h:9618
GLfloat param
Definition: glext.h:5796
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
#define ATTRIBUTE_UNUSED
Definition: i386-dis.c:36
static int prefixes
Definition: i386-dis.c:276
int xsltParseStylesheetImport(xsltStylesheetPtr style, xmlNodePtr cur)
Definition: imports.c:116
int xsltParseStylesheetInclude(xsltStylesheetPtr style, xmlNodePtr cur)
Definition: imports.c:205
xsltStylesheetPtr xsltNextImport(xsltStylesheetPtr cur)
Definition: imports.c:297
const char * filename
Definition: ioapi.h:137
int xsltAddKey(xsltStylesheetPtr style, const xmlChar *name, const xmlChar *nameURI, const xmlChar *match, const xmlChar *use, xmlNodePtr inst)
Definition: keys.c:281
void xsltFreeKeys(xsltStylesheetPtr style)
Definition: keys.c:203
XMLPUBFUN void xmlFreeRMutex(xmlRMutexPtr tok)
Definition: threads.c:275
XMLPUBFUN xmlRMutexPtr xmlNewRMutex(void)
Definition: threads.c:248
if(dx< 0)
Definition: linetemp.h:194
char templates[]
Definition: meshbuilder.c:39
#define error(str)
Definition: mkdosfs.c:1605
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define for
Definition: utility.h:88
static size_t elem
Definition: string.c:71
static float(__cdecl *square_half_float)(float x
static HWND child
Definition: cursoricon.c:298
static int priority
Definition: timer.c:163
void xsltFreeNamespaceAliasHashes(xsltStylesheetPtr style)
Definition: namespaces.c:831
void xsltNamespaceAlias(xsltStylesheetPtr style, xmlNodePtr node)
Definition: namespaces.c:75
XMLPUBVAR const xmlChar xmlStringTextNoenc[]
XMLPUBVAR const xmlChar xmlStringText[]
static unsigned __int64 next
Definition: rand_nt.c:6
#define err(...)
const WCHAR * str
#define ID
Definition: ruserpass.c:36
#define exit(n)
Definition: config.h:202
void xmlDictFree(xmlDictPtr dict)
Definition: dict.c:333
int xmlDictOwns(xmlDictPtr dict, const xmlChar *str)
Definition: dict.c:376
int xmlDictReference(xmlDictPtr dict)
Definition: dict.c:317
xmlDictPtr xmlDictCreate(void)
Definition: dict.c:262
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 xmlHashFree(xmlHashTablePtr hash, xmlHashDeallocator dealloc)
Definition: hash.c:229
void * xmlHashLookup(xmlHashTablePtr hash, const xmlChar *key)
Definition: hash.c:739
xmlHashTablePtr xmlHashCreate(int size)
Definition: hash.c:160
int xmlHashUpdateEntry(xmlHashTablePtr hash, const xmlChar *key, void *payload, xmlHashDeallocator dealloc)
Definition: hash.c:678
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
Definition: uri.h:34
char * authority
Definition: uri.h:37
char * server
Definition: uri.h:38
char * opaque
Definition: uri.h:36
char * user
Definition: uri.h:39
char * path
Definition: uri.h:41
char * scheme
Definition: uri.h:35
char * query
Definition: uri.h:42
char * fragment
Definition: uri.h:43
xmlChar * decimalPoint
const xmlChar * nsUri
xmlChar * patternSeparator
struct _xsltDecimalFormat * next
xmlFreeFunc deallocate
union _xsltRuntimeExtra::@3691 val
xsltDecimalFormatPtr decimalFormat
xmlNodePtr elem
struct _xsltTemplate * next
xmlNodePtr content
const xmlChar * modeURI
const xmlChar * name
const xmlChar * mode
struct _xsltStylesheet * style
xmlChar * match
const xmlChar * nameURI
xsltRuntimeExtraPtr extras
Definition: cookie.c:202
WCHAR * name
Definition: cookie.c:203
char * name
Definition: compiler.c:66
struct define * next
Definition: compiler.c:65
Definition: format.c:58
Definition: fs.h:78
uacpi_u8 type
Definition: interpreter.c:38
Definition: copy.c:22
Definition: match.c:28
Definition: name.c:39
WCHAR * name
Definition: name.c:42
Definition: mxnamespace.c:38
BSTR prefix
Definition: mxnamespace.c:39
#define max(a, b)
Definition: svc.c:63
Character const *const prefix
Definition: tempnam.cpp:195
Definition: dlist.c:348
Definition: pdh_main.c:96
XMLPUBFUN xmlChar * xmlBuildURI(const xmlChar *URI, const xmlChar *base)
Definition: uri.c:1902
XMLPUBFUN void xmlFreeURI(xmlURIPtr uri)
Definition: uri.c:1396
XMLPUBFUN xmlURIPtr xmlParseURI(const char *str)
Definition: uri.c:947
XMLPUBFUN xmlAttrPtr xmlGetID(xmlDocPtr doc, const xmlChar *ID)
Definition: valid.c:2719
void xsltParseGlobalVariable(xsltStylesheetPtr style, xmlNodePtr cur)
Definition: variables.c:2051
void xsltParseGlobalParam(xsltStylesheetPtr style, xmlNodePtr cur)
Definition: variables.c:2114
void xsltFreeStackElemList(xsltStackElemPtr elem)
Definition: variables.c:626
XMLPUBFUN xmlChar * xmlStrndup(const xmlChar *cur, int len)
Definition: xmlstring.c:45
XMLPUBFUN int xmlStrcasecmp(const xmlChar *str1, const xmlChar *str2)
Definition: xmlstring.c:277
#define BAD_CAST
Definition: xmlstring.h:35
XMLPUBFUN int xmlStrEqual(const xmlChar *str1, const xmlChar *str2)
Definition: xmlstring.c:162
unsigned char xmlChar
Definition: xmlstring.h:28
XMLPUBFUN xmlChar * xmlStrdup(const xmlChar *cur)
Definition: xmlstring.c:69
#define LIBXML_VERSION
Definition: xmlversion.h:39
xsltStyleType
@ XSLT_FUNC_WHEN
@ XSLT_FUNC_CALLTEMPLATE
@ XSLT_FUNC_ELEMENT
@ XSLT_FUNC_APPLYIMPORTS
@ XSLT_FUNC_DOCUMENT
@ XSLT_FUNC_CHOOSE
@ XSLT_FUNC_VARIABLE
@ XSLT_FUNC_WITHPARAM
@ XSLT_FUNC_APPLYTEMPLATES
@ XSLT_FUNC_TEXT
@ XSLT_FUNC_ATTRIBUTE
@ XSLT_FUNC_COPYOF
@ XSLT_FUNC_FOREACH
@ XSLT_FUNC_PI
@ XSLT_FUNC_VALUEOF
@ XSLT_FUNC_NUMBER
@ XSLT_FUNC_SORT
@ XSLT_FUNC_COMMENT
@ XSLT_FUNC_IF
@ XSLT_FUNC_COPY
@ XSLT_FUNC_PARAM
xsltElemPreComp * xsltElemPreCompPtr
#define XSLT_PAT_NO_PRIORITY
xsltStylesheet * xsltStylesheetPtr
xsltRuntimeExtra * xsltRuntimeExtraPtr
xsltTemplate * xsltTemplatePtr
void xsltInit(void)
Definition: xslt.c:216
xsltStylesheetPtr xsltNewStylesheet(void)
Definition: xslt.c:810
xsltStylesheetPtr xsltParseStylesheetProcess(xsltStylesheetPtr ret, xmlDocPtr doc)
Definition: xslt.c:6447
static xsltStylesheetPtr xsltNewStylesheetInternal(xsltStylesheetPtr parent)
Definition: xslt.c:745
int xsltAllocateExtraCtxt(xsltTransformContextPtr ctxt)
Definition: xslt.c:840
static void xsltParseStylesheetStripSpace(xsltStylesheetPtr style, xmlNodePtr cur)
Definition: xslt.c:1673
const int xsltLibxsltVersion
Definition: xslt.c:53
xsltStylesheetPtr xsltLoadStylesheetPI(xmlDocPtr doc)
Definition: xslt.c:6915
void xsltUninit(void)
Definition: xslt.c:232
static void xsltParseStylesheetKey(xsltStylesheetPtr style, xmlNodePtr key)
Definition: xslt.c:5120
#define NEXT
Definition: xslt.c:6811
const char * xsltEngineVersion
Definition: xslt.c:52
static xmlChar * exclPrefixPop(xsltStylesheetPtr style)
Definition: xslt.c:185
static void xsltFreeTemplateList(xsltTemplatePtr template)
Definition: xslt.c:460
static int xsltGetInheritedNsList(xsltStylesheetPtr style, xsltTemplatePtr template, xmlNodePtr node)
Definition: xslt.c:1101
static void xsltFreeDecimalFormat(xsltDecimalFormatPtr self)
Definition: xslt.c:293
xsltStylesheetPtr xsltParseStylesheetFile(const xmlChar *filename)
Definition: xslt.c:6752
int xsltIsBlank(xmlChar *str)
Definition: xslt.c:249
void xsltFreeStylesheet(xsltStylesheetPtr style)
Definition: xslt.c:965
#define SKIP_BLANKS
Definition: xslt.c:6809
void xsltParseStylesheetOutput(xsltStylesheetPtr style, xmlNodePtr cur)
Definition: xslt.c:1185
static void xsltParseStylesheetTop(xsltStylesheetPtr style, xmlNodePtr top)
Definition: xslt.c:6106
const int xsltLibxmlVersion
Definition: xslt.c:54
void xsltParseTemplateContent(xsltStylesheetPtr style, xmlNodePtr templ)
Definition: xslt.c:4894
static void xsltFreeTemplate(xsltTemplatePtr template)
Definition: xslt.c:430
xsltDecimalFormatPtr xsltDecimalFormatGetByQName(xsltStylesheetPtr style, const xmlChar *nsUri, const xmlChar *name)
Definition: xslt.c:379
static void xsltParseStylesheetPreserveSpace(xsltStylesheetPtr style, xmlNodePtr cur)
Definition: xslt.c:1532
static void xsltParseStylesheetDecimalFormat(xsltStylesheetPtr style, xmlNodePtr cur)
Definition: xslt.c:1405
int xsltParseStylesheetUser(xsltStylesheetPtr style, xmlDocPtr doc)
Definition: xslt.c:6584
#define IS_BLANK_NODE(n)
Definition: xslt.c:108
xsltStylesheetPtr xsltParseStylesheetDoc(xmlDocPtr doc)
Definition: xslt.c:6736
static void xsltPreprocessStylesheet(xsltStylesheetPtr style, xmlNodePtr cur)
Definition: xslt.c:3477
static void xsltFreeStylesheetList(xsltStylesheetPtr style)
Definition: xslt.c:888
static void xsltGatherNamespaces(xsltStylesheetPtr style)
Definition: xslt.c:3682
int xsltAllocateExtra(xsltStylesheetPtr style)
Definition: xslt.c:824
xsltStylesheetPtr xsltParseStylesheetImportedDoc(xmlDocPtr doc, xsltStylesheetPtr parentStyle)
Definition: xslt.c:6555
#define IS_BLANK(c)
Definition: xslt.c:102
static int xsltParseStylesheetExcludePrefix(xsltStylesheetPtr style, xmlNodePtr cur, int isXsltElem)
Definition: xslt.c:1743
static int initialized
Definition: xslt.c:208
xsltDecimalFormatPtr xsltDecimalFormatGetByName(xsltStylesheetPtr style, xmlChar *name)
Definition: xslt.c:349
static void xsltFreeDecimalFormatList(xsltStylesheetPtr self)
Definition: xslt.c:323
#define SKIP(val)
Definition: xslt.c:6807
static xsltDecimalFormatPtr xsltNewDecimalFormat(const xmlChar *nsUri, xmlChar *name)
Definition: xslt.c:265
static int xsltCleanupStylesheetTree(xmlDocPtr doc ATTRIBUTE_UNUSED, xmlNodePtr rootElem ATTRIBUTE_UNUSED)
Definition: xslt.c:910
static void xsltParseStylesheetExtPrefix(xsltStylesheetPtr style, xmlNodePtr cur, int isXsltElem)
Definition: xslt.c:1607
static xmlChar * xsltParseStylesheetPI(const xmlChar *value)
Definition: xslt.c:6824
static xsltTemplatePtr xsltNewTemplate(void)
Definition: xslt.c:409
static int exclPrefixPush(xsltStylesheetPtr style, xmlChar *value)
Definition: xslt.c:150
static void xsltParseStylesheetTemplate(xsltStylesheetPtr style, xmlNodePtr template)
Definition: xslt.c:5372
static void xsltParseContentError(xsltStylesheetPtr style, xmlNodePtr node)
Definition: xslt.c:120
#define NXT(val)
Definition: xslt.c:6808
#define CUR
Definition: xslt.c:6806
#define XSLT_PARSE_OPTIONS
Definition: xslt.h:54
#define XSLT_NAMESPACE
Definition: xslt.h:46
#define LIBXSLT_VERSION
Definition: xsltconfig.h:30
#define LIBXSLT_VERSION_EXTRA
Definition: xsltconfig.h:44
#define LIBXSLT_VERSION_STRING
Definition: xsltconfig.h:37
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
xmlGenericErrorFunc xsltGenericDebug
Definition: xsltutils.c:632
void * xsltGenericDebugContext
Definition: xsltutils.c:633
void * xsltGenericErrorContext
Definition: xsltutils.c:587
#define IS_XSLT_NAME(n, val)
Definition: xsltutils.h:60
#define IS_XSLT_ELEM(n)
Definition: xsltutils.h:51