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

  1. //------------------------------------------------------------------------------
  2. // <copyright file="AttributeAction.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.Xml;
  21.     using System.Xml.XPath;
  22.    
  23.     internal class AttributeAction : ContainerAction
  24.     {
  25.         private const int NameDone = 2;
  26.        
  27.         private Avt nameAvt;
  28.         private Avt nsAvt;
  29.         private InputScopeManager manager;
  30.         // Compile time precalculated AVTs
  31.         private string name;
  32.         private string nsUri;
  33.         private PrefixQName qname;
  34.         // When we not have AVTs at all we can do this. null otherwise.
  35.         private static PrefixQName CreateAttributeQName(string name, string nsUri, InputScopeManager manager)
  36.         {
  37.             // if name == "xmlns" we don't need to generate this attribute.
  38.             // to avoid i'ts generation we can return false and not add AtributeCation to it's parent container action
  39.             // for now not creating this.qname will do the trick at execution time
  40.             if (name == Keywords.s_Xmlns)
  41.                 return null;
  42.             if (nsUri == Keywords.s_XmlnsNamespace) {
  43.                 throw XsltException.Create(Res.Xslt_ReservedNS, nsUri);
  44.             }
  45.            
  46.             PrefixQName qname = new PrefixQName();
  47.             qname.SetQName(name);
  48.            
  49.             qname.Namespace = nsUri != null ? nsUri : manager.ResolveXPathNamespace(qname.Prefix);
  50.            
  51.             if (qname.Prefix.StartsWith("xml", StringComparison.Ordinal)) {
  52.                 if (qname.Prefix.Length == 3) {
  53.                     // prefix == "xml"
  54.                     if (qname.Namespace == Keywords.s_XmlNamespace && (qname.Name == "lang" || qname.Name == "space")) {
  55.                         // preserve prefix for xml:lang and xml:space
  56.                     }
  57.                     else {
  58.                         qname.ClearPrefix();
  59.                     }
  60.                 }
  61.                 else if (qname.Prefix == Keywords.s_Xmlns) {
  62.                     if (qname.Namespace == Keywords.s_XmlnsNamespace) {
  63.                         // if NS wasn't specified we have to use prefix to find it and this is imposible for 'xmlns'
  64.                         throw XsltException.Create(Res.Xslt_InvalidPrefix, qname.Prefix);
  65.                     }
  66.                     else {
  67.                         qname.ClearPrefix();
  68.                     }
  69.                 }
  70.             }
  71.             return qname;
  72.         }
  73.        
  74.         internal override void Compile(Compiler compiler)
  75.         {
  76.             CompileAttributes(compiler);
  77.             CheckRequiredAttribute(compiler, this.nameAvt, Keywords.s_Name);
  78.            
  79.             this.name = PrecalculateAvt(ref this.nameAvt);
  80.             this.nsUri = PrecalculateAvt(ref this.nsAvt);
  81.            
  82.             // if both name and ns are not AVT we can calculate qname at compile time and will not need namespace manager anymore
  83.             if (this.nameAvt == null && this.nsAvt == null) {
  84.                 if (this.name != Keywords.s_Xmlns) {
  85.                     this.qname = CreateAttributeQName(this.name, this.nsUri, compiler.CloneScopeManager());
  86.                 }
  87.             }
  88.             else {
  89.                 this.manager = compiler.CloneScopeManager();
  90.             }
  91.            
  92.             if (compiler.Recurse()) {
  93.                 CompileTemplate(compiler);
  94.                 compiler.ToParent();
  95.             }
  96.         }
  97.        
  98.         internal override bool CompileAttribute(Compiler compiler)
  99.         {
  100.             string name = compiler.Input.LocalName;
  101.             string value = compiler.Input.Value;
  102.             if (Keywords.Equals(name, compiler.Atoms.Name)) {
  103.                 this.nameAvt = Avt.CompileAvt(compiler, value);
  104.             }
  105.             else if (Keywords.Equals(name, compiler.Atoms.Namespace)) {
  106.                 this.nsAvt = Avt.CompileAvt(compiler, value);
  107.             }
  108.             else {
  109.                 return false;
  110.             }
  111.            
  112.             return true;
  113.         }
  114.        
  115.         internal override void Execute(Processor processor, ActionFrame frame)
  116.         {
  117.             Debug.Assert(processor != null && frame != null);
  118.            
  119.             switch (frame.State) {
  120.                 case Initialized:
  121.                     if (this.qname != null) {
  122.                         frame.CalulatedName = this.qname;
  123.                     }
  124.                     else {
  125.                         frame.CalulatedName = CreateAttributeQName(this.nameAvt == null ? this.name : this.nameAvt.Evaluate(processor, frame), this.nsAvt == null ? this.nsUri : this.nsAvt.Evaluate(processor, frame), this.manager);
  126.                         if (frame.CalulatedName == null) {
  127.                             // name == "xmlns" case. Ignore xsl:attribute
  128.                             frame.Finished();
  129.                             break;
  130.                         }
  131.                     }
  132.                     goto case NameDone;
  133.                     break;
  134.                 case NameDone:
  135.                    
  136.                     {
  137.                         PrefixQName qname = frame.CalulatedName;
  138.                         if (processor.BeginEvent(XPathNodeType.Attribute, qname.Prefix, qname.Name, qname.Namespace, false) == false) {
  139.                             // Come back later
  140.                             frame.State = NameDone;
  141.                             break;
  142.                         }
  143.                        
  144.                         processor.PushActionFrame(frame);
  145.                         frame.State = ProcessingChildren;
  146.                         break;
  147.                         // Allow children to run
  148.                     }
  149.                     break;
  150.                 case ProcessingChildren:
  151.                     if (processor.EndEvent(XPathNodeType.Attribute) == false) {
  152.                         frame.State = ProcessingChildren;
  153.                         break;
  154.                     }
  155.                     frame.Finished();
  156.                     break;
  157.                 default:
  158.                     Debug.Fail("Invalid ElementAction execution state");
  159.                     break;
  160.             }
  161.         }
  162.     }
  163. }

Developer Fusion