Updates referencesource to .NET 4.7
[mono.git] / mcs / class / referencesource / System.Data.SqlXml / System / Xml / Xsl / XsltOld / ContainerAction.cs
1 //------------------------------------------------------------------------------
2 // <copyright file="ContainerAction.cs" company="Microsoft">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 // <owner current="true" primary="true">Microsoft</owner>
6 //------------------------------------------------------------------------------
7
8 namespace System.Xml.Xsl.XsltOld {
9     using Res = System.Xml.Utils.Res;
10     using System;
11     using System.Diagnostics;
12     using System.Text;
13     using System.Globalization;
14     using System.Xml;
15     using System.Xml.XPath;
16     using System.Xml.Xsl.Runtime;
17     using MS.Internal.Xml.XPath;
18     using System.Collections;
19     using System.Runtime.Versioning;
20
21     internal class NamespaceInfo {
22         internal String prefix;
23         internal String nameSpace;
24         internal int stylesheetId;
25
26         internal NamespaceInfo(String prefix, String nameSpace, int stylesheetId) {
27             this.prefix = prefix;
28             this.nameSpace = nameSpace;
29             this.stylesheetId = stylesheetId;
30         }
31     }
32
33     internal class ContainerAction : CompiledAction {
34         internal ArrayList      containedActions;
35         internal CopyCodeAction lastCopyCodeAction; // non null if last action is CopyCodeAction;
36
37         private  int  maxid = 0;
38
39         // Local execution states
40         protected const int ProcessingChildren = 1;
41
42         internal override void Compile(Compiler compiler) {
43             throw new NotImplementedException();
44         }
45
46         internal void CompileStylesheetAttributes(Compiler compiler) {
47             NavigatorInput input        = compiler.Input;
48             string         element      = input.LocalName;
49             string         badAttribute = null;
50             string         version      = null;
51
52             if (input.MoveToFirstAttribute()) {
53                 do {
54                     string nspace = input.NamespaceURI;
55                     string name   = input.LocalName;
56
57                     if (nspace.Length != 0) continue;
58
59                     if (Ref.Equal(name, input.Atoms.Version)) {
60                         version = input.Value;
61                         if (1 <= XmlConvert.ToXPathDouble(version)) {
62                             compiler.ForwardCompatibility = (version != "1.0");
63                         }
64                         else {
65                             // XmlConvert.ToXPathDouble(version) an be NaN!
66                             if (! compiler.ForwardCompatibility) {
67                                 throw XsltException.Create(Res.Xslt_InvalidAttrValue, "version", version);
68                             }
69                         }
70                     }
71                     else if (Ref.Equal(name, input.Atoms.ExtensionElementPrefixes)) {
72                         compiler.InsertExtensionNamespace(input.Value);
73                     }
74                     else if (Ref.Equal(name, input.Atoms.ExcludeResultPrefixes)) {
75                         compiler.InsertExcludedNamespace(input.Value);
76                     }
77                     else if (Ref.Equal(name, input.Atoms.Id)) {
78                         // Do nothing here.
79                     }
80                     else {
81                         // We can have version atribute later. For now remember this attribute and continue
82                         badAttribute = name;
83                     }
84                 }
85                 while( input.MoveToNextAttribute());
86                 input.ToParent();
87             }
88
89             if (version == null) {
90                 throw XsltException.Create(Res.Xslt_MissingAttribute, "version");
91             }
92
93             if (badAttribute != null && ! compiler.ForwardCompatibility) {
94                 throw XsltException.Create(Res.Xslt_InvalidAttribute, badAttribute, element);
95             }
96         }
97
98         internal void CompileSingleTemplate(Compiler compiler) {
99             NavigatorInput input = compiler.Input;
100
101             //
102             // find mandatory version attribute and launch compilation of single template
103             //
104
105             string version = null;
106
107             if (input.MoveToFirstAttribute()) {
108                 do {
109                     string nspace = input.NamespaceURI;
110                     string name   = input.LocalName;
111
112                     if (Ref.Equal(nspace, input.Atoms.UriXsl) &&
113                         Ref.Equal(name,   input.Atoms.Version)) {
114                         version = input.Value;
115                     }
116                 }
117                 while(input.MoveToNextAttribute());
118                 input.ToParent();
119             }
120
121             if (version == null) {
122                 if (Ref.Equal(input.LocalName, input.Atoms.Stylesheet) &&
123                     input.NamespaceURI == XmlReservedNs.NsWdXsl) {
124                     throw XsltException.Create(Res.Xslt_WdXslNamespace);
125                 }
126                 throw XsltException.Create(Res.Xslt_WrongStylesheetElement);
127             }
128
129             compiler.AddTemplate(compiler.CreateSingleTemplateAction());
130         }
131
132         /*
133          * CompileTopLevelElements
134          */
135         protected void CompileDocument(Compiler compiler, bool inInclude) {
136             NavigatorInput input = compiler.Input;
137
138             // SkipToElement :
139             while (input.NodeType != XPathNodeType.Element) {
140                 if (! compiler.Advance()) {
141                     throw XsltException.Create(Res.Xslt_WrongStylesheetElement);
142                 }
143             }
144
145             Debug.Assert(compiler.Input.NodeType == XPathNodeType.Element);
146             if (Ref.Equal(input.NamespaceURI, input.Atoms.UriXsl)) {
147                 if (
148                     ! Ref.Equal(input.LocalName, input.Atoms.Stylesheet) &&
149                     ! Ref.Equal(input.LocalName, input.Atoms.Transform)
150                 ) {
151                     throw XsltException.Create(Res.Xslt_WrongStylesheetElement);
152                 }
153                 compiler.PushNamespaceScope();
154                 CompileStylesheetAttributes(compiler);
155                 CompileTopLevelElements(compiler);
156                 if (! inInclude) {
157                     CompileImports(compiler);
158                 }
159             }
160             else {
161                 // single template
162                 compiler.PushLiteralScope();
163                 CompileSingleTemplate(compiler);
164             }
165
166             compiler.PopScope();
167         }
168
169         internal Stylesheet CompileImport(Compiler compiler, Uri uri, int id) {
170             NavigatorInput input = compiler.ResolveDocument(uri);
171             compiler.PushInputDocument(input);
172
173             try {
174                 compiler.PushStylesheet(new Stylesheet());
175                 compiler.Stylesheetid = id;
176                 CompileDocument(compiler, /*inInclude*/ false);
177             }
178             catch (XsltCompileException) {
179                 throw;
180             }
181             catch (Exception e) {
182                 throw new XsltCompileException(e, input.BaseURI, input.LineNumber, input.LinePosition);
183             }
184             finally {
185                 compiler.PopInputDocument();
186             }
187             return compiler.PopStylesheet();
188         }
189
190         private void CompileImports(Compiler compiler) {
191             ArrayList imports = compiler.CompiledStylesheet.Imports;
192             // We can't reverce imports order. Template lookup relyes on it after compilation
193             int saveStylesheetId = compiler.Stylesheetid;
194             for (int i = imports.Count - 1; 0 <= i; i --) {   // Imports should be compiled in reverse order
195                 Uri uri = imports[i] as Uri;
196                 Debug.Assert(uri != null);
197                 imports[i] = CompileImport(compiler, uri, ++ this.maxid);
198             }
199             compiler.Stylesheetid = saveStylesheetId;
200         }
201
202         // SxS: This method does not take any resource name and does not expose any resources to the caller.
203         // It's OK to suppress the SxS warning.
204         [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
205         [ResourceExposure(ResourceScope.None)]
206         void CompileInclude(Compiler compiler) {
207             Uri uri = compiler.ResolveUri(compiler.GetSingleAttribute(compiler.Input.Atoms.Href));
208             string resolved = uri.ToString();
209             if (compiler.IsCircularReference(resolved)) {
210                 throw XsltException.Create(Res.Xslt_CircularInclude, resolved);
211             }
212
213             NavigatorInput input = compiler.ResolveDocument(uri);
214             compiler.PushInputDocument(input);
215
216             try {
217                 CompileDocument(compiler, /*inInclude*/ true);
218             }
219             catch (XsltCompileException) {
220                 throw;
221             }
222             catch (Exception e) {
223                 throw new XsltCompileException(e, input.BaseURI, input.LineNumber, input.LinePosition);
224             }
225             finally {
226                 compiler.PopInputDocument();
227             }
228             CheckEmpty(compiler);
229         }
230
231         internal void CompileNamespaceAlias(Compiler compiler) {
232             NavigatorInput input   = compiler.Input;
233             string         element = input.LocalName;
234             string namespace1 = null, namespace2 = null;
235             string prefix1 = null   , prefix2 = null;
236             if (input.MoveToFirstAttribute()) {
237                 do {
238                     string nspace = input.NamespaceURI;
239                     string name   = input.LocalName;
240
241                     if (nspace.Length != 0) continue;
242
243                     if (Ref.Equal(name,input.Atoms.StylesheetPrefix)) {
244                         prefix1    = input.Value;
245                         namespace1 = compiler.GetNsAlias(ref prefix1);
246                     }
247                     else if (Ref.Equal(name,input.Atoms.ResultPrefix)){
248                         prefix2    = input.Value;
249                         namespace2 = compiler.GetNsAlias(ref prefix2);
250                     }
251                     else {
252                         if (! compiler.ForwardCompatibility) {
253                             throw XsltException.Create(Res.Xslt_InvalidAttribute, name, element);
254                         }
255                     }
256                 }
257                 while(input.MoveToNextAttribute());
258                 input.ToParent();
259             }
260
261             CheckRequiredAttribute(compiler, namespace1, "stylesheet-prefix");
262             CheckRequiredAttribute(compiler, namespace2, "result-prefix"    );
263             CheckEmpty(compiler);
264
265             //String[] resultarray = { prefix2, namespace2 };
266             compiler.AddNamespaceAlias( namespace1, new NamespaceInfo(prefix2, namespace2, compiler.Stylesheetid));
267         }
268
269         internal void CompileKey(Compiler compiler){
270             NavigatorInput input    = compiler.Input;
271             string         element  = input.LocalName;
272             int            MatchKey = Compiler.InvalidQueryKey;
273             int            UseKey   = Compiler.InvalidQueryKey;
274
275             XmlQualifiedName Name = null;
276             if (input.MoveToFirstAttribute()) {
277                 do {
278                     string nspace = input.NamespaceURI;
279                     string name   = input.LocalName;
280                     string value  = input.Value;
281
282                     if (nspace.Length != 0) continue;
283
284                                         if (Ref.Equal(name, input.Atoms.Name)) {
285                         Name = compiler.CreateXPathQName(value);
286                     }
287                     else if (Ref.Equal(name, input.Atoms.Match)) {
288                         MatchKey = compiler.AddQuery(value, /*allowVars:*/false, /*allowKey*/false, /*pattern*/true);
289                     }
290                     else if (Ref.Equal(name, input.Atoms.Use)) {
291                         UseKey = compiler.AddQuery(value, /*allowVars:*/false, /*allowKey*/false, /*pattern*/false);
292                     }
293                     else {
294                         if (! compiler.ForwardCompatibility) {
295                             throw XsltException.Create(Res.Xslt_InvalidAttribute, name, element);
296                         }
297                     }
298                 }
299                 while(input.MoveToNextAttribute());
300                 input.ToParent();
301             }
302
303             CheckRequiredAttribute(compiler, MatchKey != Compiler.InvalidQueryKey, "match");
304             CheckRequiredAttribute(compiler, UseKey   != Compiler.InvalidQueryKey, "use"  );
305             CheckRequiredAttribute(compiler, Name     != null                    , "name" );
306             // It is a breaking change to check for emptiness, SQLBUDT 324364
307             //CheckEmpty(compiler);
308
309             compiler.InsertKey(Name, MatchKey, UseKey);
310         }
311
312         protected void CompileDecimalFormat(Compiler compiler){
313             NumberFormatInfo info   = new NumberFormatInfo();
314             DecimalFormat    format = new DecimalFormat(info, '#', '0', ';');
315             XmlQualifiedName  Name  = null;
316             NavigatorInput   input  = compiler.Input;
317             if (input.MoveToFirstAttribute()) {
318                 do {
319                     if (input.Prefix.Length != 0) continue;
320
321                     string name   = input.LocalName;
322                     string value  = input.Value;
323
324                     if (Ref.Equal(name, input.Atoms.Name)) {
325                         Name = compiler.CreateXPathQName(value);
326                     }
327                     else if (Ref.Equal(name, input.Atoms.DecimalSeparator)) {
328                         info.NumberDecimalSeparator = value;
329                     }
330                     else if (Ref.Equal(name, input.Atoms.GroupingSeparator)) {
331                         info.NumberGroupSeparator = value;
332                     }
333                     else if (Ref.Equal(name, input.Atoms.Infinity)) {
334                         info.PositiveInfinitySymbol = value;
335                     }
336                     else if (Ref.Equal(name, input.Atoms.MinusSign)) {
337                         info.NegativeSign = value;
338                     }
339                     else if (Ref.Equal(name, input.Atoms.NaN)) {
340                         info.NaNSymbol = value;
341                     }
342                     else if (Ref.Equal(name, input.Atoms.Percent)) {
343                         info.PercentSymbol = value;
344                     }
345                     else if (Ref.Equal(name, input.Atoms.PerMille)) {
346                         info.PerMilleSymbol = value;
347                     }
348                     else if (Ref.Equal(name, input.Atoms.Digit)) {
349                         if (CheckAttribute(value.Length == 1, compiler)) {
350                             format.digit = value[0];
351                         }
352                     }
353                     else if (Ref.Equal(name, input.Atoms.ZeroDigit)) {
354                         if (CheckAttribute(value.Length == 1, compiler)) {
355                             format.zeroDigit = value[0];
356                         }
357                     }
358                     else if (Ref.Equal(name, input.Atoms.PatternSeparator)) {
359                         if (CheckAttribute(value.Length == 1, compiler)) {
360                             format.patternSeparator = value[0];
361                         }
362                     }
363                 }
364                 while(input.MoveToNextAttribute());
365                 input.ToParent();
366             }
367             info.NegativeInfinitySymbol = String.Concat(info.NegativeSign, info.PositiveInfinitySymbol);
368             if (Name == null) {
369                 Name = new XmlQualifiedName();
370             }
371             compiler.AddDecimalFormat(Name, format);
372             CheckEmpty(compiler);
373         }
374
375         internal bool CheckAttribute(bool valid, Compiler compiler) {
376             if (! valid) {
377                 if (! compiler.ForwardCompatibility) {
378                     throw XsltException.Create(Res.Xslt_InvalidAttrValue, compiler.Input.LocalName, compiler.Input.Value);
379                 }
380                 return false;
381             }
382             return true;
383         }
384
385         protected void CompileSpace(Compiler compiler, bool preserve){
386             String value = compiler.GetSingleAttribute(compiler.Input.Atoms.Elements);
387             String[] elements = XmlConvert.SplitString(value);
388             for (int i = 0; i < elements.Length; i++){
389                 double defaultPriority = NameTest(elements[i]);
390                 compiler.CompiledStylesheet.AddSpace(compiler, elements[i], defaultPriority, preserve);
391             }
392             CheckEmpty(compiler);
393         }
394
395         double NameTest(String name) {
396             if (name == "*") {
397                 return -0.5;
398             }
399             int idx = name.Length - 2;
400             if (0 <= idx && name[idx] == ':' && name[idx + 1] == '*') {
401                 if (! PrefixQName.ValidatePrefix(name.Substring(0, idx))) {
402                     throw XsltException.Create(Res.Xslt_InvalidAttrValue, "elements", name);
403                 }
404                 return -0.25;
405             }
406             else {
407                 string prefix, localname;
408                 PrefixQName.ParseQualifiedName(name, out prefix, out localname);
409                 return 0;
410             }
411         }
412
413         // SxS: This method does not take any resource name and does not expose any resources to the caller.
414         // It's OK to suppress the SxS warning.
415         [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
416         [ResourceExposure(ResourceScope.None)]
417         protected void CompileTopLevelElements(Compiler compiler) {
418             // Navigator positioned at parent root, need to move to child and then back
419             if (compiler.Recurse() == false) {
420                 return;
421             }
422
423             NavigatorInput input    = compiler.Input;
424             bool notFirstElement    = false;
425             do {
426                 switch (input.NodeType) {
427                 case XPathNodeType.Element:
428                     string name   = input.LocalName;
429                     string nspace = input.NamespaceURI;
430
431                     if (Ref.Equal(nspace, input.Atoms.UriXsl)) {
432                         if (Ref.Equal(name, input.Atoms.Import)) {
433                             if (notFirstElement) {
434                                 throw XsltException.Create(Res.Xslt_NotFirstImport);
435                             }
436                             // We should compile imports in reverse order after all toplevel elements.
437                             // remember it now and return to it in CompileImpoorts();
438                             Uri uri = compiler.ResolveUri(compiler.GetSingleAttribute(compiler.Input.Atoms.Href));
439                             string resolved = uri.ToString();
440                             if (compiler.IsCircularReference(resolved)) {
441                                 throw XsltException.Create(Res.Xslt_CircularInclude, resolved);
442                             }
443                             compiler.CompiledStylesheet.Imports.Add(uri);
444                             CheckEmpty(compiler);
445                         }
446                         else if (Ref.Equal(name, input.Atoms.Include)) {
447                             notFirstElement = true;
448                             CompileInclude(compiler);
449                         }
450                         else {
451                             notFirstElement = true;
452                             compiler.PushNamespaceScope();
453                             if (Ref.Equal(name, input.Atoms.StripSpace)) {
454                                 CompileSpace(compiler, false);
455                             }
456                             else if (Ref.Equal(name, input.Atoms.PreserveSpace)) {
457                                 CompileSpace(compiler, true);
458                             }
459                             else if (Ref.Equal(name, input.Atoms.Output)) {
460                                 CompileOutput(compiler);
461                             }
462                             else if (Ref.Equal(name, input.Atoms.Key)) {
463                                 CompileKey(compiler);
464                             }
465                             else if (Ref.Equal(name, input.Atoms.DecimalFormat)) {
466                                 CompileDecimalFormat(compiler);
467                             }
468                             else if (Ref.Equal(name, input.Atoms.NamespaceAlias)) {
469                                 CompileNamespaceAlias(compiler);
470                             }
471                             else if (Ref.Equal(name, input.Atoms.AttributeSet)) {
472                                 compiler.AddAttributeSet(compiler.CreateAttributeSetAction());
473                             }
474                             else if (Ref.Equal(name, input.Atoms.Variable)) {
475                                 VariableAction action = compiler.CreateVariableAction(VariableType.GlobalVariable);
476                                 if (action != null) {
477                                     AddAction(action);
478                                 }
479                             }
480                             else if (Ref.Equal(name, input.Atoms.Param)) {
481                                 VariableAction action = compiler.CreateVariableAction(VariableType.GlobalParameter);
482                                 if (action != null) {
483                                     AddAction(action);
484                                 }
485                             }
486                             else if (Ref.Equal(name, input.Atoms.Template)) {
487                                 compiler.AddTemplate(compiler.CreateTemplateAction());
488                             }
489                             else {
490                                 if (!compiler.ForwardCompatibility) {
491                                     throw compiler.UnexpectedKeyword();
492                                 }
493                             }
494                             compiler.PopScope();
495                         }
496                     }
497 #if !DISABLE_XSLT_SCRIPT
498                     else if (nspace == input.Atoms.UrnMsxsl && name == input.Atoms.Script) {
499                         AddScript(compiler);
500                     }
501 #endif
502                     else {
503                         if (nspace.Length == 0) {
504                             throw XsltException.Create(Res.Xslt_NullNsAtTopLevel, input.Name);
505                         }
506                         // Ignoring non-recognized namespace per XSLT spec 2.2
507                     }
508                     break;
509
510                 case XPathNodeType.ProcessingInstruction:
511                 case XPathNodeType.Comment:
512                 case XPathNodeType.Whitespace:
513                 case XPathNodeType.SignificantWhitespace:
514                     break;
515
516                 default:
517                     throw XsltException.Create(Res.Xslt_InvalidContents, "stylesheet");
518                 }
519             }
520             while (compiler.Advance());
521
522             compiler.ToParent();
523         }
524
525         protected void CompileTemplate(Compiler compiler) {
526             do {
527                 CompileOnceTemplate(compiler);
528             }
529             while (compiler.Advance());
530         }
531
532         protected void CompileOnceTemplate(Compiler compiler) {
533             NavigatorInput input = compiler.Input;
534
535             if (input.NodeType == XPathNodeType.Element) {
536                 string nspace = input.NamespaceURI;
537
538                 if (Ref.Equal(nspace, input.Atoms.UriXsl)) {
539                     compiler.PushNamespaceScope();
540                     CompileInstruction(compiler);
541                     compiler.PopScope();
542                 }
543                 else {
544                     compiler.PushLiteralScope();
545                     compiler.InsertExtensionNamespace();
546                     if (compiler.IsExtensionNamespace(nspace)) {
547                         AddAction(compiler.CreateNewInstructionAction());
548                     }
549                     else {
550                         CompileLiteral(compiler);
551                     }
552                     compiler.PopScope();
553                 }
554             }
555             else {
556                 CompileLiteral(compiler);
557             }
558         }
559
560         void CompileInstruction(Compiler compiler) {
561             NavigatorInput input  = compiler.Input;
562             CompiledAction action = null;
563
564             Debug.Assert(Ref.Equal(input.NamespaceURI, input.Atoms.UriXsl));
565
566             string name = input.LocalName;
567
568             if (Ref.Equal(name, input.Atoms.ApplyImports)) {
569                 action = compiler.CreateApplyImportsAction();
570             }
571             else if (Ref.Equal(name, input.Atoms.ApplyTemplates)) {
572                 action = compiler.CreateApplyTemplatesAction();
573             }
574             else if (Ref.Equal(name, input.Atoms.Attribute)) {
575                 action = compiler.CreateAttributeAction();
576             }
577             else if (Ref.Equal(name, input.Atoms.CallTemplate)) {
578                 action = compiler.CreateCallTemplateAction();
579             }
580             else if (Ref.Equal(name, input.Atoms.Choose)) {
581                 action = compiler.CreateChooseAction();
582             }
583             else if (Ref.Equal(name, input.Atoms.Comment)) {
584                 action = compiler.CreateCommentAction();
585             }
586             else if (Ref.Equal(name, input.Atoms.Copy)) {
587                 action = compiler.CreateCopyAction();
588             }
589             else if (Ref.Equal(name, input.Atoms.CopyOf)) {
590                 action = compiler.CreateCopyOfAction();
591             }
592             else if (Ref.Equal(name, input.Atoms.Element)) {
593                 action = compiler.CreateElementAction();
594             }
595             else if (Ref.Equal(name, input.Atoms.Fallback)) {
596                 return;
597             }
598             else if (Ref.Equal(name, input.Atoms.ForEach)) {
599                 action = compiler.CreateForEachAction();
600             }
601             else if (Ref.Equal(name, input.Atoms.If)) {
602                 action = compiler.CreateIfAction(IfAction.ConditionType.ConditionIf);
603             }
604             else if (Ref.Equal(name, input.Atoms.Message)) {
605                 action = compiler.CreateMessageAction();
606             }
607             else if (Ref.Equal(name, input.Atoms.Number)) {
608                 action = compiler.CreateNumberAction();
609             }
610             else if (Ref.Equal(name, input.Atoms.ProcessingInstruction)) {
611                 action = compiler.CreateProcessingInstructionAction();
612             }
613             else if (Ref.Equal(name, input.Atoms.Text)) {
614                 action = compiler.CreateTextAction();
615             }
616             else if (Ref.Equal(name, input.Atoms.ValueOf)) {
617                 action = compiler.CreateValueOfAction();
618             }
619             else if (Ref.Equal(name, input.Atoms.Variable)) {
620                 action = compiler.CreateVariableAction(VariableType.LocalVariable);
621             }
622             else {
623                 if (compiler.ForwardCompatibility)
624                     action = compiler.CreateNewInstructionAction();
625                 else
626                     throw compiler.UnexpectedKeyword();
627             }
628
629             Debug.Assert(action != null);
630
631             AddAction(action);
632         }
633
634         void CompileLiteral(Compiler compiler) {
635             NavigatorInput input = compiler.Input;
636
637             switch (input.NodeType) {
638             case XPathNodeType.Element:
639                 this.AddEvent(compiler.CreateBeginEvent());
640                 CompileLiteralAttributesAndNamespaces(compiler);
641
642                 if (compiler.Recurse()) {
643                     CompileTemplate(compiler);
644                     compiler.ToParent();
645                 }
646
647                 this.AddEvent(new EndEvent(XPathNodeType.Element));
648                 break;
649
650             case XPathNodeType.Text:
651             case XPathNodeType.SignificantWhitespace:
652                 this.AddEvent(compiler.CreateTextEvent());
653                 break;
654             case XPathNodeType.Whitespace:
655             case XPathNodeType.ProcessingInstruction:
656             case XPathNodeType.Comment:
657                 break;
658
659             default:
660                 Debug.Assert(false, "Unexpected node type.");
661                 break;
662             }
663         }
664
665         void CompileLiteralAttributesAndNamespaces(Compiler compiler) {
666             NavigatorInput input = compiler.Input;
667
668             if (input.Navigator.MoveToAttribute("use-attribute-sets", input.Atoms.UriXsl)) {
669                 AddAction(compiler.CreateUseAttributeSetsAction());
670                 input.Navigator.MoveToParent();
671             }
672             compiler.InsertExcludedNamespace();
673
674             if (input.MoveToFirstNamespace()) {
675                 do {
676                     string uri = input.Value;
677
678                     if (uri == XmlReservedNs.NsXslt) {
679                         continue;
680                     }
681                     if (
682                         compiler.IsExcludedNamespace(uri) ||
683                         compiler.IsExtensionNamespace(uri) ||
684                         compiler.IsNamespaceAlias(uri)
685                     ) {
686                             continue;
687                     }
688                     this.AddEvent(new NamespaceEvent(input));
689                 }
690                 while (input.MoveToNextNamespace());
691                 input.ToParent();
692             }
693
694             if (input.MoveToFirstAttribute()) {
695                 do {
696
697                     // Skip everything from Xslt namespace
698                     if (Ref.Equal(input.NamespaceURI, input.Atoms.UriXsl)) {
699                         continue;
700                     }
701
702                     // Add attribute events
703                     this.AddEvent (compiler.CreateBeginEvent());
704                     this.AddEvents(compiler.CompileAvt(input.Value));
705                     this.AddEvent (new EndEvent(XPathNodeType.Attribute));
706                 }
707                 while (input.MoveToNextAttribute());
708                 input.ToParent();
709             }
710         }
711
712         void CompileOutput(Compiler compiler) {
713             Debug.Assert((object) this == (object) compiler.RootAction);
714             compiler.RootAction.Output.Compile(compiler);
715         }
716
717         internal void AddAction(Action action) {
718             if (this.containedActions == null) {
719                 this.containedActions = new ArrayList();
720             }
721             this.containedActions.Add(action);
722             lastCopyCodeAction = null;
723         }
724
725         private void EnsureCopyCodeAction() {
726             if(lastCopyCodeAction == null) {
727                 CopyCodeAction copyCode = new CopyCodeAction();
728                 AddAction(copyCode);
729                 lastCopyCodeAction = copyCode;
730             }
731         }
732
733         protected void AddEvent(Event copyEvent) {
734             EnsureCopyCodeAction();
735             lastCopyCodeAction.AddEvent(copyEvent);
736         }
737
738         protected void AddEvents(ArrayList copyEvents) {
739             EnsureCopyCodeAction();
740             lastCopyCodeAction.AddEvents(copyEvents);
741         }
742
743 #if !DISABLE_XSLT_SCRIPT
744         private void AddScript(Compiler compiler) {
745             NavigatorInput input = compiler.Input;
746
747             ScriptingLanguage lang = ScriptingLanguage.JScript;
748             string implementsNamespace = null;
749             if (input.MoveToFirstAttribute()) {
750                 do {
751                     if (input.LocalName == input.Atoms.Language) {
752                         string langName = input.Value;
753                         if (
754                             String.Compare(langName, "jscript"   , StringComparison.OrdinalIgnoreCase) == 0 ||
755                             String.Compare(langName, "javascript", StringComparison.OrdinalIgnoreCase) == 0
756                         ) {
757                             lang = ScriptingLanguage.JScript;
758                         } else if (
759                             String.Compare(langName, "c#"    , StringComparison.OrdinalIgnoreCase) == 0 ||
760                             String.Compare(langName, "csharp", StringComparison.OrdinalIgnoreCase) == 0
761                         ) {
762                             lang = ScriptingLanguage.CSharp;
763                         }
764 #if !FEATURE_PAL // visualbasic
765                         else if (
766                             String.Compare(langName, "vb"         , StringComparison.OrdinalIgnoreCase) == 0 ||
767                             String.Compare(langName, "visualbasic", StringComparison.OrdinalIgnoreCase) == 0
768                         ) {
769                             lang = ScriptingLanguage.VisualBasic;
770                         }
771 #endif // !FEATURE_PAL
772                         else {
773                             throw XsltException.Create(Res.Xslt_ScriptInvalidLanguage, langName);
774                         }
775                     }
776                     else if (input.LocalName == input.Atoms.ImplementsPrefix) {
777                         if(! PrefixQName.ValidatePrefix(input.Value))  {
778                             throw XsltException.Create(Res.Xslt_InvalidAttrValue, input.LocalName, input.Value);
779                         }
780                         implementsNamespace = compiler.ResolveXmlNamespace(input.Value);
781                     }
782                 }
783                 while (input.MoveToNextAttribute());
784                 input.ToParent();
785             }
786             if (implementsNamespace == null) {
787                 throw XsltException.Create(Res.Xslt_MissingAttribute, input.Atoms.ImplementsPrefix);
788             }
789             if (!input.Recurse() || input.NodeType != XPathNodeType.Text) {
790                 throw XsltException.Create(Res.Xslt_ScriptEmpty);
791             }
792             compiler.AddScript(input.Value, lang, implementsNamespace, input.BaseURI, input.LineNumber);
793             input.ToParent();
794         }
795 #endif
796
797         internal override void Execute(Processor processor, ActionFrame frame) {
798             Debug.Assert(processor != null && frame != null);
799
800             switch (frame.State) {
801             case Initialized:
802                 if (this.containedActions != null && this.containedActions.Count > 0) {
803                     processor.PushActionFrame(frame);
804                     frame.State = ProcessingChildren;
805                 }
806                 else {
807                     frame.Finished();
808                 }
809                 break;                              // Allow children to run
810
811             case ProcessingChildren:
812                 frame.Finished();
813                 break;
814
815             default:
816                 Debug.Fail("Invalid Container action execution state");
817                 break;
818             }
819         }
820
821         internal Action GetAction(int actionIndex) {
822             Debug.Assert(actionIndex == 0 || this.containedActions != null);
823
824             if (this.containedActions != null && actionIndex < this.containedActions.Count) {
825                 return (Action) this.containedActions[actionIndex];
826             }
827             else {
828                 return null;
829             }
830         }
831
832         internal void CheckDuplicateParams(XmlQualifiedName name) {
833             if (this.containedActions != null) {
834                 foreach(CompiledAction action in this.containedActions) {
835                     WithParamAction param = action as WithParamAction;
836                     if (param != null && param.Name == name) {
837                         throw XsltException.Create(Res.Xslt_DuplicateWithParam, name.ToString());
838                     }
839                 }
840             }
841         }
842
843         internal override void ReplaceNamespaceAlias(Compiler compiler){
844             if (this.containedActions == null) {
845                 return;
846             }
847             int count = this.containedActions.Count;
848             for(int i= 0; i < this.containedActions.Count; i++) {
849                 ((Action)this.containedActions[i]).ReplaceNamespaceAlias(compiler);
850             }
851         }
852     }
853 }