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

  1. //------------------------------------------------------------------------------
  2. // <copyright file="Processor.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.Globalization;
  19.     using System.Diagnostics;
  20.     using System.IO;
  21.     using System.Xml.XPath;
  22.     using MS.Internal.Xml.XPath;
  23.     using System.Text;
  24.     using System.Collections;
  25.     using System.Collections.Generic;
  26.     using System.Xml.Xsl.XsltOld.Debugger;
  27.     using System.Reflection;
  28.     using System.Security;
  29.    
  30.     internal sealed class Processor : IXsltProcessor
  31.     {
  32.         //
  33.         // Static constants
  34.         //
  35.        
  36.         const int StackIncrement = 10;
  37.        
  38.         //
  39.         // Execution result
  40.         //
  41.        
  42.         internal enum ExecResult
  43.         {
  44.             Continue,
  45.             // Continues next iteration immediately
  46.             Interrupt,
  47.             // Returns to caller, was processed enough
  48.             Done
  49.             // Execution finished
  50.         }
  51.        
  52.         internal enum OutputResult
  53.         {
  54.             Continue,
  55.             Interrupt,
  56.             Overflow,
  57.             Error,
  58.             Ignore
  59.         }
  60.        
  61.         private ExecResult execResult;
  62.        
  63.         //
  64.         // Compiled stylesheet
  65.         //
  66.        
  67.         private Stylesheet stylesheet;
  68.         // Root of import tree of template managers
  69.         private RootAction rootAction;
  70.         private Key[] keyList;
  71.         private List<TheQuery> queryStore;
  72.         public PermissionSet permissions;
  73.         // used by XsltCompiledContext in document and extension functions
  74.         //
  75.         // Document Being transformed
  76.         //
  77.        
  78.         private XPathNavigator document;
  79.        
  80.         //
  81.         // Execution action stack
  82.         //
  83.        
  84.         private HWStack actionStack;
  85.         private HWStack debuggerStack;
  86.        
  87.         //
  88.         // Register for returning value from calling nested action
  89.         //
  90.        
  91.         private StringBuilder sharedStringBuilder;
  92.        
  93.         //
  94.         // Output related member variables
  95.         //
  96.         int ignoreLevel;
  97.         StateMachine xsm;
  98.         RecordBuilder builder;
  99.        
  100.         XsltOutput output;
  101.        
  102.         XmlNameTable nameTable = new NameTable();
  103.        
  104.         XmlResolver resolver;
  105.        
  106.         #pragma warning disable 618
  107.         XsltArgumentList args;
  108.         #pragma warning restore 618
  109.         Hashtable scriptExtensions;
  110.        
  111.         ArrayList numberList;
  112.         //
  113.         // Template lookup action
  114.         //
  115.        
  116.         TemplateLookupAction templateLookup = new TemplateLookupAction();
  117.        
  118.         private IXsltDebugger debugger;
  119.         Query[] queryList;
  120.        
  121.         private ArrayList sortArray;
  122.        
  123.         private Hashtable documentCache;
  124.        
  125.         // NOTE: ValueOf() can call Matches() through XsltCompileContext.PreserveWhitespace(),
  126.         // that's why we use two different contexts here, valueOfContext and matchesContext
  127.         private XsltCompileContext valueOfContext;
  128.         private XsltCompileContext matchesContext;
  129.        
  130.         internal XPathNavigator Current {
  131.             get {
  132.                 ActionFrame frame = (ActionFrame)this.actionStack.Peek();
  133.                 return frame != null ? frame.Node : null;
  134.             }
  135.         }
  136.        
  137.         internal ExecResult ExecutionResult {
  138.             get { return this.execResult; }
  139.            
  140.             set {
  141.                 Debug.Assert(this.execResult == ExecResult.Continue);
  142.                 this.execResult = value;
  143.             }
  144.         }
  145.        
  146.         internal Stylesheet Stylesheet {
  147.             get { return this.stylesheet; }
  148.         }
  149.        
  150.         internal XmlResolver Resolver {
  151.             get {
  152.                 Debug.Assert(this.resolver != null, "Constructor should create it if null passed");
  153.                 return this.resolver;
  154.             }
  155.         }
  156.        
  157.         internal ArrayList SortArray {
  158.             get {
  159.                 Debug.Assert(this.sortArray != null, "InitSortArray() wasn't called");
  160.                 return this.sortArray;
  161.             }
  162.         }
  163.        
  164.         internal Key[] KeyList {
  165.             get { return this.keyList; }
  166.         }
  167.        
  168.         internal XPathNavigator GetNavigator(Uri ruri)
  169.         {
  170.             XPathNavigator result = null;
  171.             if (documentCache != null) {
  172.                 result = documentCache[ruri] as XPathNavigator;
  173.                 if (result != null) {
  174.                     return result.Clone();
  175.                 }
  176.             }
  177.             else {
  178.                 documentCache = new Hashtable();
  179.             }
  180.            
  181.             object input = resolver.GetEntity(ruri, null, null);
  182.             if (input is Stream) {
  183.                 XmlTextReaderImpl tr = new XmlTextReaderImpl(ruri.ToString(), (Stream)input);
  184.                 {
  185.                     tr.XmlResolver = this.resolver;
  186.                 }
  187.                 // reader is closed by Compiler.LoadDocument()
  188.                 result = ((IXPathNavigable)Compiler.LoadDocument(tr)).CreateNavigator();
  189.             }
  190.             else if (input is XPathNavigator) {
  191.                 result = (XPathNavigator)input;
  192.             }
  193.             else {
  194.                 throw XsltException.Create(Res.Xslt_CantResolve, ruri.ToString());
  195.             }
  196.             documentCache[ruri] = result.Clone();
  197.             return result;
  198.         }
  199.        
  200.         internal void AddSort(Sort sortinfo)
  201.         {
  202.             Debug.Assert(this.sortArray != null, "InitSortArray() wasn't called");
  203.             this.sortArray.Add(sortinfo);
  204.         }
  205.        
  206.         internal void InitSortArray()
  207.         {
  208.             if (this.sortArray == null) {
  209.                 this.sortArray = new ArrayList();
  210.             }
  211.             else {
  212.                 this.sortArray.Clear();
  213.             }
  214.         }
  215.        
  216.         internal object GetGlobalParameter(XmlQualifiedName qname)
  217.         {
  218.             object parameter = args.GetParam(qname.Name, qname.Namespace);
  219.             if (parameter == null) {
  220.                 return null;
  221.             }
  222.             if (parameter is XPathNodeIterator || parameter is XPathNavigator || parameter is bool || parameter is double || parameter is string) {
  223.                 // doing nothing
  224.             }
  225.             else if (parameter is Int16 || parameter is UInt16 || parameter is Int32 || parameter is UInt32 || parameter is Int64 || parameter is UInt64 || parameter is float || parameter is decimal) {
  226.                 parameter = XmlConvert.ToXPathDouble(parameter);
  227.             }
  228.             else {
  229.                 parameter = parameter.ToString();
  230.             }
  231.             return parameter;
  232.         }
  233.        
  234.         internal object GetExtensionObject(string nsUri)
  235.         {
  236.             return args.GetExtensionObject(nsUri);
  237.         }
  238.        
  239.         internal object GetScriptObject(string nsUri)
  240.         {
  241.             return scriptExtensions[nsUri];
  242.         }
  243.        
  244.         internal RootAction RootAction {
  245.             get { return this.rootAction; }
  246.         }
  247.        
  248.         internal XPathNavigator Document {
  249.             get { return this.document; }
  250.         }
  251.        
  252.         #if DEBUG
  253.         private bool stringBuilderLocked = false;
  254.         #endif
  255.        
  256.         internal StringBuilder GetSharedStringBuilder()
  257.         {
  258.             #if DEBUG
  259.             Debug.Assert(!stringBuilderLocked);
  260.             #endif
  261.             if (sharedStringBuilder == null) {
  262.                 sharedStringBuilder = new StringBuilder();
  263.             }
  264.             else {
  265.                 sharedStringBuilder.Length = 0;
  266.             }
  267.             #if DEBUG
  268.             stringBuilderLocked = true;
  269.             #endif
  270.             return sharedStringBuilder;
  271.         }
  272.        
  273.         internal void ReleaseSharedStringBuilder()
  274.         {
  275.             // don't clean stringBuilderLocked here. ToString() will happen after this call
  276.             #if DEBUG
  277.             stringBuilderLocked = false;
  278.             #endif
  279.         }
  280.        
  281.         internal ArrayList NumberList {
  282.             get {
  283.                 if (this.numberList == null) {
  284.                     this.numberList = new ArrayList();
  285.                 }
  286.                 return this.numberList;
  287.             }
  288.         }
  289.        
  290.         internal IXsltDebugger Debugger {
  291.             get { return this.debugger; }
  292.         }
  293.        
  294.         internal HWStack ActionStack {
  295.             get { return this.actionStack; }
  296.         }
  297.        
  298.         internal RecordBuilder Builder {
  299.             get { return this.builder; }
  300.         }
  301.        
  302.         internal XsltOutput Output {
  303.             get { return this.output; }
  304.         }
  305.        
  306.         //
  307.         // Construction
  308.         //
  309.         public Processor(XPathNavigator doc, XsltArgumentList args, XmlResolver resolver, Stylesheet stylesheet, List<TheQuery> queryStore, RootAction rootAction, IXsltDebugger debugger)
  310.         {
  311.             this.stylesheet = stylesheet;
  312.             this.queryStore = queryStore;
  313.             this.rootAction = rootAction;
  314.             this.queryList = new Query[queryStore.Count];
  315.             {
  316.                 for (int i = 0; i < queryStore.Count; i++) {
  317.                     queryList[i] = Query.Clone(queryStore[i].CompiledQuery.QueryTree);
  318.                 }
  319.             }
  320.            
  321.             this.xsm = new StateMachine();
  322.             this.document = doc;
  323.             this.builder = null;
  324.             this.actionStack = new HWStack(StackIncrement);
  325.             this.output = this.rootAction.Output;
  326.             this.permissions = this.rootAction.permissions;
  327.             this.resolver = resolver != null ? resolver : new XmlNullResolver();
  328.             this.args = args != null ? args : new XsltArgumentList();
  329.             this.debugger = debugger;
  330.             if (this.debugger != null) {
  331.                     /*limit:*/                this.debuggerStack = new HWStack(StackIncrement, 1000);
  332.                 templateLookup = new TemplateLookupActionDbg();
  333.             }
  334.            
  335.             // Clone the compile-time KeyList
  336.             if (this.rootAction.KeyList != null) {
  337.                 this.keyList = new Key[this.rootAction.KeyList.Count];
  338.                 for (int i = 0; i < this.keyList.Length; i++) {
  339.                     this.keyList[i] = this.rootAction.KeyList[i].Clone();
  340.                 }
  341.             }
  342.            
  343.             this.scriptExtensions = new Hashtable(this.stylesheet.ScriptObjectTypes.Count);
  344.             {
  345.                 foreach (DictionaryEntry entry in this.stylesheet.ScriptObjectTypes) {
  346.                     string namespaceUri = (string)entry.Key;
  347.                     if (GetExtensionObject(namespaceUri) != null) {
  348.                         throw XsltException.Create(Res.Xslt_ScriptDub, namespaceUri);
  349.                     }
  350.                     scriptExtensions.Add(namespaceUri, Activator.CreateInstance((Type)entry.Value, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.CreateInstance, null, null, null));
  351.                 }
  352.             }
  353.            
  354.                 /*nodeSet:*/            this.PushActionFrame(this.rootAction, null);
  355.         }
  356.        
  357.         public ReaderOutput StartReader()
  358.         {
  359.             ReaderOutput output = new ReaderOutput(this);
  360.             this.builder = new RecordBuilder(output, this.nameTable);
  361.             return output;
  362.         }
  363.        
  364.         public void Execute(Stream stream)
  365.         {
  366.             RecordOutput recOutput = null;
  367.            
  368.             switch (this.output.Method) {
  369.                 case XsltOutput.OutputMethod.Text:
  370.                     recOutput = new TextOnlyOutput(this, stream);
  371.                     break;
  372.                 case XsltOutput.OutputMethod.Xml:
  373.                 case XsltOutput.OutputMethod.Html:
  374.                 case XsltOutput.OutputMethod.Other:
  375.                 case XsltOutput.OutputMethod.Unknown:
  376.                     recOutput = new TextOutput(this, stream);
  377.                     break;
  378.             }
  379.             this.builder = new RecordBuilder(recOutput, this.nameTable);
  380.             Execute();
  381.         }
  382.        
  383.         public void Execute(TextWriter writer)
  384.         {
  385.             RecordOutput recOutput = null;
  386.            
  387.             switch (this.output.Method) {
  388.                 case XsltOutput.OutputMethod.Text:
  389.                     recOutput = new TextOnlyOutput(this, writer);
  390.                     break;
  391.                 case XsltOutput.OutputMethod.Xml:
  392.                 case XsltOutput.OutputMethod.Html:
  393.                 case XsltOutput.OutputMethod.Other:
  394.                 case XsltOutput.OutputMethod.Unknown:
  395.                     recOutput = new TextOutput(this, writer);
  396.                     break;
  397.             }
  398.             this.builder = new RecordBuilder(recOutput, this.nameTable);
  399.             Execute();
  400.         }
  401.        
  402.         public void Execute(XmlWriter writer)
  403.         {
  404.             this.builder = new RecordBuilder(new WriterOutput(this, writer), this.nameTable);
  405.             Execute();
  406.         }
  407.        
  408.         //
  409.         // Execution part of processor
  410.         //
  411.         internal void Execute()
  412.         {
  413.             Debug.Assert(this.actionStack != null);
  414.            
  415.             while (this.execResult == ExecResult.Continue) {
  416.                 ActionFrame frame = (ActionFrame)this.actionStack.Peek();
  417.                
  418.                 if (frame == null) {
  419.                     Debug.Assert(this.builder != null);
  420.                     this.builder.TheEnd();
  421.                     ExecutionResult = ExecResult.Done;
  422.                     break;
  423.                 }
  424.                
  425.                 // Execute the action which was on the top of the stack
  426.                 if (frame.Execute(this)) {
  427.                     this.actionStack.Pop();
  428.                 }
  429.             }
  430.            
  431.             if (this.execResult == ExecResult.Interrupt) {
  432.                 this.execResult = ExecResult.Continue;
  433.             }
  434.         }
  435.        
  436.         //
  437.         // Action frame support
  438.         //
  439.        
  440.         internal ActionFrame PushNewFrame()
  441.         {
  442.             ActionFrame prent = (ActionFrame)this.actionStack.Peek();
  443.             ActionFrame frame = (ActionFrame)this.actionStack.Push();
  444.             if (frame == null) {
  445.                 frame = new ActionFrame();
  446.                 this.actionStack.AddToTop(frame);
  447.             }
  448.             Debug.Assert(frame != null);
  449.            
  450.             if (prent != null) {
  451.                 frame.Inherit(prent);
  452.             }
  453.            
  454.             return frame;
  455.         }
  456.        
  457.         internal void PushActionFrame(Action action, XPathNodeIterator nodeSet)
  458.         {
  459.             ActionFrame frame = PushNewFrame();
  460.             frame.Init(action, nodeSet);
  461.         }
  462.        
  463.         internal void PushActionFrame(ActionFrame container)
  464.         {
  465.             this.PushActionFrame(container, container.NodeSet);
  466.         }
  467.        
  468.         internal void PushActionFrame(ActionFrame container, XPathNodeIterator nodeSet)
  469.         {
  470.             ActionFrame frame = PushNewFrame();
  471.             frame.Init(container, nodeSet);
  472.         }
  473.        
  474.         internal void PushTemplateLookup(XPathNodeIterator nodeSet, XmlQualifiedName mode, Stylesheet importsOf)
  475.         {
  476.             Debug.Assert(this.templateLookup != null);
  477.             this.templateLookup.Initialize(mode, importsOf);
  478.             PushActionFrame(this.templateLookup, nodeSet);
  479.         }
  480.        
  481.         internal string GetQueryExpression(int key)
  482.         {
  483.             Debug.Assert(key != Compiler.InvalidQueryKey);
  484.             return this.queryStore[key].CompiledQuery.Expression;
  485.         }
  486.        
  487.         internal Query GetCompiledQuery(int key)
  488.         {
  489.             Debug.Assert(key != Compiler.InvalidQueryKey);
  490.             TheQuery theQuery = this.queryStore[key];
  491.             theQuery.CompiledQuery.CheckErrors();
  492.             Query expr = Query.Clone(this.queryList[key]);
  493.             expr.SetXsltContext(new XsltCompileContext(theQuery._ScopeManager, this));
  494.             return expr;
  495.         }
  496.        
  497.         internal Query GetValueQuery(int key)
  498.         {
  499.             return GetValueQuery(key, null);
  500.         }
  501.        
  502.         internal Query GetValueQuery(int key, XsltCompileContext context)
  503.         {
  504.             Debug.Assert(key != Compiler.InvalidQueryKey);
  505.             TheQuery theQuery = this.queryStore[key];
  506.             theQuery.CompiledQuery.CheckErrors();
  507.             Query expr = this.queryList[key];
  508.            
  509.             if (context == null) {
  510.                 context = new XsltCompileContext(theQuery._ScopeManager, this);
  511.             }
  512.             else {
  513.                 context.Reinitialize(theQuery._ScopeManager, this);
  514.             }
  515.            
  516.             expr.SetXsltContext(context);
  517.             return expr;
  518.         }
  519.        
  520.         private XsltCompileContext GetValueOfContext()
  521.         {
  522.             if (this.valueOfContext == null) {
  523.                 this.valueOfContext = new XsltCompileContext();
  524.             }
  525.             return this.valueOfContext;
  526.         }
  527.        
  528.         [Conditional("DEBUG")]
  529.         private void RecycleValueOfContext()
  530.         {
  531.             if (this.valueOfContext != null) {
  532.                 this.valueOfContext.Recycle();
  533.             }
  534.         }
  535.        
  536.         private XsltCompileContext GetMatchesContext()
  537.         {
  538.             if (this.matchesContext == null) {
  539.                 this.matchesContext = new XsltCompileContext();
  540.             }
  541.             return this.matchesContext;
  542.         }
  543.        
  544.         [Conditional("DEBUG")]
  545.         private void RecycleMatchesContext()
  546.         {
  547.             if (this.matchesContext != null) {
  548.                 this.matchesContext.Recycle();
  549.             }
  550.         }
  551.        
  552.         internal string ValueOf(ActionFrame context, int key)
  553.         {
  554.             string result;
  555.            
  556.             Query query = this.GetValueQuery(key, GetValueOfContext());
  557.             object value = query.Evaluate(context.NodeSet);
  558.             if (value is XPathNodeIterator) {
  559.                 XPathNavigator n = query.Advance();
  560.                 result = n != null ? ValueOf(n) : string.Empty;
  561.             }
  562.             else {
  563.                 result = XmlConvert.ToXPathString(value);
  564.             }
  565.            
  566.             RecycleValueOfContext();
  567.             return result;
  568.         }
  569.        
  570.         internal string ValueOf(XPathNavigator n)
  571.         {
  572.             if (this.stylesheet.Whitespace && n.NodeType == XPathNodeType.Element) {
  573.                 StringBuilder builder = this.GetSharedStringBuilder();
  574.                 ElementValueWithoutWS(n, builder);
  575.                 this.ReleaseSharedStringBuilder();
  576.                 return builder.ToString();
  577.             }
  578.             return n.Value;
  579.         }
  580.        
  581.         private void ElementValueWithoutWS(XPathNavigator nav, StringBuilder builder)
  582.         {
  583.             Debug.Assert(nav.NodeType == XPathNodeType.Element);
  584.             bool preserve = this.Stylesheet.PreserveWhiteSpace(this, nav);
  585.             if (nav.MoveToFirstChild()) {
  586.                 do {
  587.                     switch (nav.NodeType) {
  588.                         case XPathNodeType.Text:
  589.                         case XPathNodeType.SignificantWhitespace:
  590.                             builder.Append(nav.Value);
  591.                             break;
  592.                         case XPathNodeType.Whitespace:
  593.                             if (preserve) {
  594.                                 builder.Append(nav.Value);
  595.                             }
  596.                             break;
  597.                         case XPathNodeType.Element:
  598.                             ElementValueWithoutWS(nav, builder);
  599.                             break;
  600.                     }
  601.                 }
  602.                 while (nav.MoveToNext());
  603.                 nav.MoveToParent();
  604.             }
  605.         }
  606.        
  607.         internal XPathNodeIterator StartQuery(XPathNodeIterator context, int key)
  608.         {
  609.             Query query = GetCompiledQuery(key);
  610.             object result = query.Evaluate(context);
  611.             if (result is XPathNodeIterator) {
  612.                 return new XPathSelectionIterator(context.Current, query);
  613.             }
  614.             throw XsltException.Create(Res.XPath_NodeSetExpected);
  615.         }
  616.        
  617.         internal object Evaluate(ActionFrame context, int key)
  618.         {
  619.             return GetValueQuery(key).Evaluate(context.NodeSet);
  620.         }
  621.        
  622.         internal object RunQuery(ActionFrame context, int key)
  623.         {
  624.             Query query = GetCompiledQuery(key);
  625.             object value = query.Evaluate(context.NodeSet);
  626.             XPathNodeIterator it = value as XPathNodeIterator;
  627.             if (it != null) {
  628.                 return new XPathArrayIterator(it);
  629.             }
  630.            
  631.             return value;
  632.         }
  633.        
  634.         internal string EvaluateString(ActionFrame context, int key)
  635.         {
  636.             object objValue = Evaluate(context, key);
  637.             string value = null;
  638.             if (objValue != null)
  639.                 value = XmlConvert.ToXPathString(objValue);
  640.             if (value == null)
  641.                 value = string.Empty;
  642.             return value;
  643.         }
  644.        
  645.         internal bool EvaluateBoolean(ActionFrame context, int key)
  646.         {
  647.             object objValue = Evaluate(context, key);
  648.            
  649.             if (objValue != null) {
  650.                 XPathNavigator nav = objValue as XPathNavigator;
  651.                 return nav != null ? Convert.ToBoolean(nav.Value, CultureInfo.InvariantCulture) : Convert.ToBoolean(objValue, CultureInfo.InvariantCulture);
  652.             }
  653.             else {
  654.                 return false;
  655.             }
  656.         }
  657.        
  658.         internal bool Matches(XPathNavigator context, int key)
  659.         {
  660.             // We don't use XPathNavigator.Matches() to avoid cloning of Query on each call
  661.             Query query = this.GetValueQuery(key, GetMatchesContext());
  662.            
  663.             try {
  664.                 bool result = query.MatchNode(context) != null;
  665.                
  666.                 RecycleMatchesContext();
  667.                 return result;
  668.             }
  669.             catch (XPathException) {
  670.                 throw XsltException.Create(Res.Xslt_InvalidPattern, this.GetQueryExpression(key));
  671.             }
  672.         }
  673.        
  674.         //
  675.         // Outputting part of processor
  676.         //
  677.        
  678.         internal XmlNameTable NameTable {
  679.             get { return this.nameTable; }
  680.         }
  681.        
  682.         internal bool CanContinue {
  683.             get { return this.execResult == ExecResult.Continue; }
  684.         }
  685.        
  686.         internal bool ExecutionDone {
  687.             get { return this.execResult == ExecResult.Done; }
  688.         }
  689.        
  690.         internal void ResetOutput()
  691.         {
  692.             Debug.Assert(this.builder != null);
  693.             this.builder.Reset();
  694.         }
  695.         internal bool BeginEvent(XPathNodeType nodeType, string prefix, string name, string nspace, bool empty)
  696.         {
  697.             return BeginEvent(nodeType, prefix, name, nspace, empty, null, true);
  698.         }
  699.        
  700.         internal bool BeginEvent(XPathNodeType nodeType, string prefix, string name, string nspace, bool empty, object htmlProps, bool search)
  701.         {
  702.             Debug.Assert(this.xsm != null);
  703.            
  704.             int stateOutlook = this.xsm.BeginOutlook(nodeType);
  705.            
  706.             if (this.ignoreLevel > 0 || stateOutlook == StateMachine.Error) {
  707.                 this.ignoreLevel++;
  708.                 return true;
  709.                 // We consumed the event, so pretend it was output.
  710.             }
  711.            
  712.             switch (this.builder.BeginEvent(stateOutlook, nodeType, prefix, name, nspace, empty, htmlProps, search)) {
  713.                 case OutputResult.Continue:
  714.                     this.xsm.Begin(nodeType);
  715.                     Debug.Assert(StateMachine.StateOnly(stateOutlook) == this.xsm.State);
  716.                     Debug.Assert(ExecutionResult == ExecResult.Continue);
  717.                     return true;
  718.                 case OutputResult.Interrupt:
  719.                     this.xsm.Begin(nodeType);
  720.                     Debug.Assert(StateMachine.StateOnly(stateOutlook) == this.xsm.State);
  721.                     ExecutionResult = ExecResult.Interrupt;
  722.                     return true;
  723.                 case OutputResult.Overflow:
  724.                     ExecutionResult = ExecResult.Interrupt;
  725.                     return false;
  726.                 case OutputResult.Error:
  727.                     this.ignoreLevel++;
  728.                     return true;
  729.                 case OutputResult.Ignore:
  730.                     return true;
  731.                 default:
  732.                     Debug.Fail("Unexpected result of RecordBuilder.BeginEvent()");
  733.                     return true;
  734.             }
  735.         }
  736.        
  737.         internal bool TextEvent(string text)
  738.         {
  739.             return this.TextEvent(text, false);
  740.         }
  741.        
  742.         internal bool TextEvent(string text, bool disableOutputEscaping)
  743.         {
  744.             Debug.Assert(this.xsm != null);
  745.            
  746.             if (this.ignoreLevel > 0) {
  747.                 return true;
  748.             }
  749.            
  750.             int stateOutlook = this.xsm.BeginOutlook(XPathNodeType.Text);
  751.            
  752.             switch (this.builder.TextEvent(stateOutlook, text, disableOutputEscaping)) {
  753.                 case OutputResult.Continue:
  754.                     this.xsm.Begin(XPathNodeType.Text);
  755.                     Debug.Assert(StateMachine.StateOnly(stateOutlook) == this.xsm.State);
  756.                     Debug.Assert(ExecutionResult == ExecResult.Continue);
  757.                     return true;
  758.                 case OutputResult.Interrupt:
  759.                     this.xsm.Begin(XPathNodeType.Text);
  760.                     Debug.Assert(StateMachine.StateOnly(stateOutlook) == this.xsm.State);
  761.                     ExecutionResult = ExecResult.Interrupt;
  762.                     return true;
  763.                 case OutputResult.Overflow:
  764.                     ExecutionResult = ExecResult.Interrupt;
  765.                     return false;
  766.                 case OutputResult.Error:
  767.                 case OutputResult.Ignore:
  768.                     return true;
  769.                 default:
  770.                     Debug.Fail("Unexpected result of RecordBuilder.TextEvent()");
  771.                     return true;
  772.             }
  773.         }
  774.        
  775.         internal bool EndEvent(XPathNodeType nodeType)
  776.         {
  777.             Debug.Assert(this.xsm != null);
  778.            
  779.             if (this.ignoreLevel > 0) {
  780.                 this.ignoreLevel--;
  781.                 return true;
  782.             }
  783.            
  784.             int stateOutlook = this.xsm.EndOutlook(nodeType);
  785.            
  786.             switch (this.builder.EndEvent(stateOutlook, nodeType)) {
  787.                 case OutputResult.Continue:
  788.                     this.xsm.End(nodeType);
  789.                     Debug.Assert(StateMachine.StateOnly(stateOutlook) == this.xsm.State);
  790.                     return true;
  791.                 case OutputResult.Interrupt:
  792.                     this.xsm.End(nodeType);
  793.                     Debug.Assert(StateMachine.StateOnly(stateOutlook) == this.xsm.State, "StateMachine.StateOnly(stateOutlook) == this.xsm.State");
  794.                     ExecutionResult = ExecResult.Interrupt;
  795.                     return true;
  796.                 case OutputResult.Overflow:
  797.                     ExecutionResult = ExecResult.Interrupt;
  798.                     return false;
  799.                 case OutputResult.Error:
  800.                 case OutputResult.Ignore:
  801.                 default:
  802.                     Debug.Fail("Unexpected result of RecordBuilder.TextEvent()");
  803.                     return true;
  804.             }
  805.         }
  806.        
  807.         internal bool CopyBeginEvent(XPathNavigator node, bool emptyflag)
  808.         {
  809.             switch (node.NodeType) {
  810.                 case XPathNodeType.Element:
  811.                 case XPathNodeType.Attribute:
  812.                 case XPathNodeType.ProcessingInstruction:
  813.                 case XPathNodeType.Comment:
  814.                     return BeginEvent(node.NodeType, node.Prefix, node.LocalName, node.NamespaceURI, emptyflag);
  815.                 case XPathNodeType.Namespace:
  816.                     // value instead of namespace here!
  817.                     return BeginEvent(XPathNodeType.Namespace, null, node.LocalName, node.Value, false);
  818.                 case XPathNodeType.Text:
  819.                     // Text will be copied in CopyContents();
  820.                     break;
  821.                 case XPathNodeType.Root:
  822.                 case XPathNodeType.Whitespace:
  823.                 case XPathNodeType.SignificantWhitespace:
  824.                 case XPathNodeType.All:
  825.                    
  826.                     break;
  827.                 default:
  828.                    
  829.                     Debug.Fail("Invalid XPathNodeType in CopyBeginEvent");
  830.                     break;
  831.             }
  832.            
  833.             return true;
  834.         }
  835.        
  836.         internal bool CopyTextEvent(XPathNavigator node)
  837.         {
  838.             switch (node.NodeType) {
  839.                 case XPathNodeType.Element:
  840.                 case XPathNodeType.Namespace:
  841.                     break;
  842.                 case XPathNodeType.Attribute:
  843.                 case XPathNodeType.ProcessingInstruction:
  844.                 case XPathNodeType.Comment:
  845.                 case XPathNodeType.Text:
  846.                 case XPathNodeType.Whitespace:
  847.                 case XPathNodeType.SignificantWhitespace:
  848.                    
  849.                     string text = node.Value;
  850.                     return TextEvent(text);
  851.                 case XPathNodeType.Root:
  852.                 case XPathNodeType.All:
  853.                    
  854.                     break;
  855.                 default:
  856.                    
  857.                     Debug.Fail("Invalid XPathNodeType in CopyTextEvent");
  858.                     break;
  859.             }
  860.            
  861.             return true;
  862.         }
  863.        
  864.         internal bool CopyEndEvent(XPathNavigator node)
  865.         {
  866.             switch (node.NodeType) {
  867.                 case XPathNodeType.Element:
  868.                 case XPathNodeType.Attribute:
  869.                 case XPathNodeType.ProcessingInstruction:
  870.                 case XPathNodeType.Comment:
  871.                 case XPathNodeType.Namespace:
  872.                     return EndEvent(node.NodeType);
  873.                 case XPathNodeType.Text:
  874.                    
  875.                     // Text was copied in CopyContents();
  876.                     break;
  877.                 case XPathNodeType.Root:
  878.                 case XPathNodeType.Whitespace:
  879.                 case XPathNodeType.SignificantWhitespace:
  880.                 case XPathNodeType.All:
  881.                    
  882.                    
  883.                     break;
  884.                 default:
  885.                    
  886.                     Debug.Fail("Invalid XPathNodeType in CopyEndEvent");
  887.                     break;
  888.             }
  889.            
  890.             return true;
  891.         }
  892.        
  893.         static internal bool IsRoot(XPathNavigator navigator)
  894.         {
  895.             Debug.Assert(navigator != null);
  896.            
  897.             if (navigator.NodeType == XPathNodeType.Root) {
  898.                 return true;
  899.             }
  900.             else if (navigator.NodeType == XPathNodeType.Element) {
  901.                 XPathNavigator clone = navigator.Clone();
  902.                 clone.MoveToRoot();
  903.                 return clone.IsSamePosition(navigator);
  904.             }
  905.             else {
  906.                 return false;
  907.             }
  908.         }
  909.        
  910.         //
  911.         // Builder stack
  912.         //
  913.         internal void PushOutput(RecordOutput output)
  914.         {
  915.             Debug.Assert(output != null);
  916.             this.builder.OutputState = this.xsm.State;
  917.             RecordBuilder lastBuilder = this.builder;
  918.             this.builder = new RecordBuilder(output, this.nameTable);
  919.             this.builder.Next = lastBuilder;
  920.            
  921.             this.xsm.Reset();
  922.         }
  923.        
  924.         internal RecordOutput PopOutput()
  925.         {
  926.             Debug.Assert(this.builder != null);
  927.            
  928.             RecordBuilder topBuilder = this.builder;
  929.             this.builder = topBuilder.Next;
  930.             this.xsm.State = this.builder.OutputState;
  931.            
  932.             topBuilder.TheEnd();
  933.            
  934.             return topBuilder.Output;
  935.         }
  936.        
  937.         internal bool SetDefaultOutput(XsltOutput.OutputMethod method)
  938.         {
  939.             if (Output.Method != method) {
  940.                 this.output = this.output.CreateDerivedOutput(method);
  941.                 return true;
  942.             }
  943.             return false;
  944.         }
  945.        
  946.         internal object GetVariableValue(VariableAction variable)
  947.         {
  948.             int variablekey = variable.VarKey;
  949.             if (variable.IsGlobal) {
  950.                 ActionFrame rootFrame = (ActionFrame)this.actionStack[0];
  951.                 object result = rootFrame.GetVariable(variablekey);
  952.                 if (result != null) {
  953.                     return result;
  954.                 }
  955.                 // Variable wasn't evaluated yet
  956.                 if (variable.Stylesheetid == -1) {
  957.                     throw XsltException.Create(Res.Xslt_CircularReference, variable.NameStr);
  958.                 }
  959.                 int saveStackSize = this.actionStack.Length;
  960.                 ActionFrame varFrame = PushNewFrame();
  961.                 varFrame.Inherit(rootFrame);
  962.                 varFrame.Init(variable, rootFrame.NodeSet);
  963.                 do {
  964.                     bool endOfFrame = ((ActionFrame)this.actionStack.Peek()).Execute(this);
  965.                     if (endOfFrame) {
  966.                         this.actionStack.Pop();
  967.                     }
  968.                 }
  969.                 while (saveStackSize < this.actionStack.Length);
  970.                 Debug.Assert(saveStackSize == this.actionStack.Length);
  971.                 result = rootFrame.GetVariable(variablekey);
  972.                 Debug.Assert(result != null, "Variable was just calculated and result can't be null");
  973.                 return result;
  974.             }
  975.             else {
  976.                 return ((ActionFrame)this.actionStack.Peek()).GetVariable(variablekey);
  977.             }
  978.         }
  979.        
  980.         internal void SetParameter(XmlQualifiedName name, object value)
  981.         {
  982.             Debug.Assert(1 < actionStack.Length);
  983.             ActionFrame parentFrame = (ActionFrame)this.actionStack[actionStack.Length - 2];
  984.             parentFrame.SetParameter(name, value);
  985.         }
  986.        
  987.         internal void ResetParams()
  988.         {
  989.             ActionFrame frame = (ActionFrame)this.actionStack[actionStack.Length - 1];
  990.             frame.ResetParams();
  991.         }
  992.        
  993.         internal object GetParameter(XmlQualifiedName name)
  994.         {
  995.             Debug.Assert(2 < actionStack.Length);
  996.             ActionFrame parentFrame = (ActionFrame)this.actionStack[actionStack.Length - 3];
  997.             return parentFrame.GetParameter(name);
  998.         }
  999.        
  1000.         // ---------------------- Debugger stack -----------------------
  1001.        
  1002.         internal class DebuggerFrame
  1003.         {
  1004.             internal ActionFrame actionFrame;
  1005.             internal XmlQualifiedName currentMode;
  1006.         }
  1007.        
  1008.         internal void PushDebuggerStack()
  1009.         {
  1010.             Debug.Assert(this.Debugger != null, "We don't generate calls this function if ! debugger");
  1011.             DebuggerFrame dbgFrame = (DebuggerFrame)this.debuggerStack.Push();
  1012.             if (dbgFrame == null) {
  1013.                 dbgFrame = new DebuggerFrame();
  1014.                 this.debuggerStack.AddToTop(dbgFrame);
  1015.             }
  1016.             dbgFrame.actionFrame = (ActionFrame)this.actionStack.Peek();
  1017.             // In a case of next builtIn action.
  1018.         }
  1019.        
  1020.         internal void PopDebuggerStack()
  1021.         {
  1022.             Debug.Assert(this.Debugger != null, "We don't generate calls this function if ! debugger");
  1023.             this.debuggerStack.Pop();
  1024.         }
  1025.        
  1026.         internal void OnInstructionExecute()
  1027.         {
  1028.             Debug.Assert(this.Debugger != null, "We don't generate calls this function if ! debugger");
  1029.             DebuggerFrame dbgFrame = (DebuggerFrame)this.debuggerStack.Peek();
  1030.             Debug.Assert(dbgFrame != null, "PushDebuggerStack() wasn't ever called");
  1031.             dbgFrame.actionFrame = (ActionFrame)this.actionStack.Peek();
  1032.             this.Debugger.OnInstructionExecute((IXsltProcessor)this);
  1033.         }
  1034.        
  1035.         internal XmlQualifiedName GetPrevioseMode()
  1036.         {
  1037.             Debug.Assert(this.Debugger != null, "We don't generate calls this function if ! debugger");
  1038.             Debug.Assert(2 <= this.debuggerStack.Length);
  1039.             return ((DebuggerFrame)this.debuggerStack[this.debuggerStack.Length - 2]).currentMode;
  1040.         }
  1041.        
  1042.         internal void SetCurrentMode(XmlQualifiedName mode)
  1043.         {
  1044.             Debug.Assert(this.Debugger != null, "We don't generate calls this function if ! debugger");
  1045.             ((DebuggerFrame)this.debuggerStack[this.debuggerStack.Length - 1]).currentMode = mode;
  1046.         }
  1047.        
  1048.         // ----------------------- IXsltProcessor : --------------------
  1049.         int IXsltProcessor.StackDepth {
  1050.             get { return this.debuggerStack.Length; }
  1051.         }
  1052.        
  1053.         IStackFrame IXsltProcessor.GetStackFrame(int depth)
  1054.         {
  1055.             return ((DebuggerFrame)this.debuggerStack[depth]).actionFrame;
  1056.         }
  1057.     }
  1058. }

Developer Fusion