The Labs \ Source Viewer \ SSCLI \ System.Xml.Xsl.XsltOld \ TemplateAction

  1. //------------------------------------------------------------------------------
  2. // <copyright file="TemplateAction.cs" company="Microsoft">
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. // </copyright>
  14. //------------------------------------------------------------------------------
  15. namespace System.Xml.Xsl.XsltOld
  16. {
  17.     using Res = System.Xml.Utils.Res;
  18.     using System;
  19.     using System.Diagnostics;
  20.     using System.Collections;
  21.     using System.Xml;
  22.     using System.Xml.XPath;
  23.     using MS.Internal.Xml.XPath;
  24.     using System.Globalization;
  25.    
  26.     internal class TemplateAction : TemplateBaseAction
  27.     {
  28.         private int matchKey = Compiler.InvalidQueryKey;
  29.         private XmlQualifiedName name;
  30.         private double priority = double.NaN;
  31.         private XmlQualifiedName mode;
  32.         private int templateId;
  33.         private bool replaceNSAliasesDone;
  34.        
  35.         internal int MatchKey {
  36.             get { return this.matchKey; }
  37.         }
  38.        
  39.         internal XmlQualifiedName Name {
  40.             get { return this.name; }
  41.         }
  42.        
  43.         internal double Priority {
  44.             get { return this.priority; }
  45.         }
  46.        
  47.         internal XmlQualifiedName Mode {
  48.             get { return this.mode; }
  49.         }
  50.        
  51.         internal int TemplateId {
  52.             get { return this.templateId; }
  53.             set {
  54.                 Debug.Assert(this.templateId == 0);
  55.                 this.templateId = value;
  56.             }
  57.         }
  58.        
  59.         internal override void Compile(Compiler compiler)
  60.         {
  61.             CompileAttributes(compiler);
  62.             if (this.matchKey == Compiler.InvalidQueryKey) {
  63.                 if (this.name == null) {
  64.                     throw XsltException.Create(Res.Xslt_TemplateNoAttrib);
  65.                 }
  66.                 if (this.mode != null) {
  67.                     throw XsltException.Create(Res.Xslt_InvalidModeAttribute);
  68.                 }
  69.             }
  70.             compiler.BeginTemplate(this);
  71.            
  72.             if (compiler.Recurse()) {
  73.                 CompileParameters(compiler);
  74.                 CompileTemplate(compiler);
  75.                
  76.                 compiler.ToParent();
  77.             }
  78.            
  79.             compiler.EndTemplate();
  80.             AnalyzePriority(compiler);
  81.         }
  82.        
  83.         internal virtual void CompileSingle(Compiler compiler)
  84.         {
  85.                 /*allowVars:*/                /*allowKey:*/                /*pattern*/            this.matchKey = compiler.AddQuery("/", false, true, true);
  86.             this.priority = Compiler.RootPriority;
  87.            
  88.             CompileOnceTemplate(compiler);
  89.         }
  90.        
  91.         internal override bool CompileAttribute(Compiler compiler)
  92.         {
  93.             string name = compiler.Input.LocalName;
  94.             string value = compiler.Input.Value;
  95.            
  96.             if (Keywords.Equals(name, compiler.Atoms.Match)) {
  97.                 Debug.Assert(this.matchKey == Compiler.InvalidQueryKey);
  98.                     /*allowVars:*/                    /*allowKey:*/                    /*pattern*/                this.matchKey = compiler.AddQuery(value, false, true, true);
  99.             }
  100.             else if (Keywords.Equals(name, compiler.Atoms.Name)) {
  101.                 Debug.Assert(this.name == null);
  102.                 this.name = compiler.CreateXPathQName(value);
  103.             }
  104.             else if (Keywords.Equals(name, compiler.Atoms.Priority)) {
  105.                 Debug.Assert(Double.IsNaN(this.priority));
  106.                 this.priority = XmlConvert.ToXPathDouble(value);
  107.                 if (double.IsNaN(this.priority) && !compiler.ForwardCompatibility) {
  108.                     throw XsltException.Create(Res.Xslt_InvalidAttrValue, Keywords.s_Priority, value);
  109.                 }
  110.             }
  111.             else if (Keywords.Equals(name, compiler.Atoms.Mode)) {
  112.                 Debug.Assert(this.mode == null);
  113.                 if (compiler.AllowBuiltInMode && value == "*") {
  114.                     this.mode = Compiler.BuiltInMode;
  115.                 }
  116.                 else {
  117.                     this.mode = compiler.CreateXPathQName(value);
  118.                 }
  119.             }
  120.             else {
  121.                 return false;
  122.             }
  123.            
  124.             return true;
  125.         }
  126.        
  127.         private void AnalyzePriority(Compiler compiler)
  128.         {
  129.             NavigatorInput input = compiler.Input;
  130.            
  131.             if (!Double.IsNaN(this.priority) || this.matchKey == Compiler.InvalidQueryKey) {
  132.                 return;
  133.             }
  134.             // Split Unions:
  135.             TheQuery theQuery = (TheQuery)compiler.QueryStore[this.MatchKey];
  136.             CompiledXpathExpr expr = (CompiledXpathExpr)theQuery.CompiledQuery;
  137.             Query query = expr.QueryTree;
  138.             UnionExpr union;
  139.             while ((union = query as UnionExpr) != null) {
  140.                 Debug.Assert(!(union.qy2 is UnionExpr), "only qy1 can be union");
  141.                 TemplateAction copy = this.CloneWithoutName();
  142.                 compiler.QueryStore.Add(new TheQuery(new CompiledXpathExpr(union.qy2, expr.Expression, false), theQuery._ScopeManager));
  143.                 copy.matchKey = compiler.QueryStore.Count - 1;
  144.                 copy.priority = union.qy2.XsltDefaultPriority;
  145.                 compiler.AddTemplate(copy);
  146.                
  147.                 query = union.qy1;
  148.             }
  149.             if (expr.QueryTree != query) {
  150.                 // query was splitted and we need create new TheQuery for this template
  151.                 compiler.QueryStore[this.MatchKey] = new TheQuery(new CompiledXpathExpr(query, expr.Expression, false), theQuery._ScopeManager);
  152.             }
  153.             this.priority = query.XsltDefaultPriority;
  154.         }
  155.        
  156.         protected void CompileParameters(Compiler compiler)
  157.         {
  158.             NavigatorInput input = compiler.Input;
  159.             do {
  160.                 switch (input.NodeType) {
  161.                     case XPathNodeType.Element:
  162.                         if (Keywords.Equals(input.NamespaceURI, input.Atoms.XsltNamespace) && Keywords.Equals(input.LocalName, input.Atoms.Param)) {
  163.                             compiler.PushNamespaceScope();
  164.                             AddAction(compiler.CreateVariableAction(VariableType.LocalParameter));
  165.                             compiler.PopScope();
  166.                             continue;
  167.                         }
  168.                         else {
  169.                             return;
  170.                         }
  171.                         break;
  172.                     case XPathNodeType.Text:
  173.                         return;
  174.                     case XPathNodeType.SignificantWhitespace:
  175.                         this.AddEvent(compiler.CreateTextEvent());
  176.                         continue;
  177.                     default:
  178.                         continue;
  179.                 }
  180.             }
  181.             while (input.Advance());
  182.         }
  183.        
  184.         //
  185.         // Priority calculation plus template splitting
  186.         //
  187.        
  188.         private TemplateAction CloneWithoutName()
  189.         {
  190.             TemplateAction clone = new TemplateAction();
  191.             {
  192.                 clone.containedActions = this.containedActions;
  193.                 clone.mode = this.mode;
  194.                 clone.variableCount = this.variableCount;
  195.                 clone.replaceNSAliasesDone = true;
  196.                 // We shouldn't replace NS in clones.
  197.             }
  198.             return clone;
  199.         }
  200.        
  201.         internal override void ReplaceNamespaceAlias(Compiler compiler)
  202.         {
  203.             // if template has both name and match it will be twice caled by stylesheet to replace NS aliases.
  204.             if (!replaceNSAliasesDone) {
  205.                 base.ReplaceNamespaceAlias(compiler);
  206.                 replaceNSAliasesDone = true;
  207.             }
  208.         }
  209.         //
  210.         // Execution
  211.         //
  212.        
  213.         internal override void Execute(Processor processor, ActionFrame frame)
  214.         {
  215.             Debug.Assert(processor != null && frame != null);
  216.            
  217.             switch (frame.State) {
  218.                 case Initialized:
  219.                     if (this.variableCount > 0) {
  220.                         frame.AllocateVariables(this.variableCount);
  221.                     }
  222.                     if (this.containedActions != null && this.containedActions.Count > 0) {
  223.                         processor.PushActionFrame(frame);
  224.                         frame.State = ProcessingChildren;
  225.                     }
  226.                     else {
  227.                         frame.Finished();
  228.                     }
  229.                     break;
  230.                 case ProcessingChildren:
  231.                     // Allow children to run
  232.                     frame.Finished();
  233.                     break;
  234.                 default:
  235.                     Debug.Fail("Invalid Container action execution state");
  236.                     break;
  237.             }
  238.         }
  239.     }
  240. }

Developer Fusion