1 //------------------------------------------------------------------------------ 2 // <copyright file="ApplyTemplatesAction.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.Collections; 13 using System.Xml; 14 using System.Xml.XPath; 15 16 internal class ApplyTemplatesAction : ContainerAction { 17 private const int ProcessedChildren = 2; 18 private const int ProcessNextNode = 3; 19 private const int PositionAdvanced = 4; 20 private const int TemplateProcessed = 5; 21 22 private int selectKey = Compiler.InvalidQueryKey; 23 private XmlQualifiedName mode; 24 25 // 26 // <xsl:template match="*|/" [mode="?"]> 27 // <xsl:apply-templates [mode="?"]/> 28 // </xsl:template> 29 // 30 31 private static ApplyTemplatesAction s_BuiltInRule = new ApplyTemplatesAction(); 32 BuiltInRule()33 internal static ApplyTemplatesAction BuiltInRule() { 34 Debug.Assert(s_BuiltInRule != null); 35 return s_BuiltInRule; 36 } 37 BuiltInRule(XmlQualifiedName mode)38 internal static ApplyTemplatesAction BuiltInRule(XmlQualifiedName mode) { 39 return(mode == null || mode.IsEmpty) ? BuiltInRule() : new ApplyTemplatesAction(mode); 40 } 41 ApplyTemplatesAction()42 internal ApplyTemplatesAction() {} 43 ApplyTemplatesAction(XmlQualifiedName mode)44 private ApplyTemplatesAction(XmlQualifiedName mode) { 45 Debug.Assert(mode != null); 46 this.mode = mode; 47 } 48 Compile(Compiler compiler)49 internal override void Compile(Compiler compiler) { 50 CompileAttributes(compiler); 51 CompileContent(compiler); 52 } 53 CompileAttribute(Compiler compiler)54 internal override bool CompileAttribute(Compiler compiler) { 55 string name = compiler.Input.LocalName; 56 string value = compiler.Input.Value; 57 if (Ref.Equal(name, compiler.Atoms.Select )) { 58 this.selectKey = compiler.AddQuery(value); 59 } 60 else if (Ref.Equal(name, compiler.Atoms.Mode )) { 61 Debug.Assert(this.mode == null); 62 if (compiler.AllowBuiltInMode && value == "*") { 63 this.mode = Compiler.BuiltInMode; 64 } 65 else { 66 this.mode = compiler.CreateXPathQName(value); 67 } 68 } 69 else { 70 return false; 71 } 72 73 return true; 74 } 75 CompileContent(Compiler compiler)76 private void CompileContent(Compiler compiler) { 77 NavigatorInput input = compiler.Input; 78 79 if (compiler.Recurse()) { 80 do { 81 switch (input.NodeType) { 82 case XPathNodeType.Element: 83 compiler.PushNamespaceScope(); 84 string nspace = input.NamespaceURI; 85 string name = input.LocalName; 86 87 if (Ref.Equal(nspace, input.Atoms.UriXsl)) { 88 if (Ref.Equal(name, input.Atoms.Sort)) { 89 AddAction(compiler.CreateSortAction()); 90 } 91 else if (Ref.Equal(name, input.Atoms.WithParam)) { 92 WithParamAction par = compiler.CreateWithParamAction(); 93 CheckDuplicateParams(par.Name); 94 AddAction(par); 95 } 96 else { 97 throw compiler.UnexpectedKeyword(); 98 } 99 } 100 else { 101 throw compiler.UnexpectedKeyword(); 102 } 103 compiler.PopScope(); 104 break; 105 106 case XPathNodeType.Comment: 107 case XPathNodeType.ProcessingInstruction: 108 case XPathNodeType.Whitespace: 109 case XPathNodeType.SignificantWhitespace: 110 break; 111 112 default: 113 throw XsltException.Create(Res.Xslt_InvalidContents, "apply-templates"); 114 } 115 } 116 while (compiler.Advance()); 117 118 compiler.ToParent(); 119 } 120 } 121 Execute(Processor processor, ActionFrame frame)122 internal override void Execute(Processor processor, ActionFrame frame) { 123 Debug.Assert(processor != null && frame != null); 124 125 switch (frame.State) { 126 case Initialized: 127 processor.ResetParams(); 128 processor.InitSortArray(); 129 if (this.containedActions != null && this.containedActions.Count > 0) { 130 processor.PushActionFrame(frame); 131 frame.State = ProcessedChildren; 132 break; 133 } 134 goto case ProcessedChildren; 135 case ProcessedChildren: 136 if (this.selectKey == Compiler.InvalidQueryKey) { 137 if (! frame.Node.HasChildren) { 138 frame.Finished(); 139 break; 140 } 141 frame.InitNewNodeSet(frame.Node.SelectChildren(XPathNodeType.All)); 142 } 143 else { 144 frame.InitNewNodeSet(processor.StartQuery(frame.NodeSet, this.selectKey)); 145 } 146 if (processor.SortArray.Count != 0) { 147 frame.SortNewNodeSet(processor, processor.SortArray); 148 } 149 frame.State = ProcessNextNode; 150 goto case ProcessNextNode; 151 152 case ProcessNextNode: 153 Debug.Assert(frame.State == ProcessNextNode); 154 Debug.Assert(frame.NewNodeSet != null); 155 156 if (frame.NewNextNode(processor)) { 157 frame.State = PositionAdvanced; 158 goto case PositionAdvanced; 159 } 160 else { 161 frame.Finished(); 162 break; 163 } 164 165 case PositionAdvanced: 166 Debug.Assert(frame.State == PositionAdvanced); 167 168 processor.PushTemplateLookup(frame.NewNodeSet, this.mode, /*importsOf:*/null); 169 170 frame.State = TemplateProcessed; 171 break; 172 173 case TemplateProcessed: 174 frame.State = ProcessNextNode; 175 goto case ProcessNextNode; 176 177 default: 178 Debug.Fail("Invalid ApplyTemplatesAction execution state"); 179 break; 180 } 181 } 182 } 183 } 184