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