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

  1. //------------------------------------------------------------------------------
  2. // <copyright file="RecordBuilder.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.Text;
  21.     using System.Xml;
  22.     using System.Xml.XPath;
  23.     using System.Collections;
  24.    
  25.     internal sealed class RecordBuilder
  26.     {
  27.         private int outputState;
  28.         private RecordBuilder next;
  29.        
  30.         RecordOutput output;
  31.        
  32.         // Atomization:
  33.         private XmlNameTable nameTable;
  34.         private OutKeywords atoms;
  35.        
  36.         // Namespace manager for output
  37.         private OutputScopeManager scopeManager;
  38.        
  39.         // Main node + Fields Collection
  40.         private BuilderInfo mainNode = new BuilderInfo();
  41.         private ArrayList attributeList = new ArrayList();
  42.         private int attributeCount;
  43.         private ArrayList namespaceList = new ArrayList();
  44.         private int namespaceCount;
  45.         private BuilderInfo dummy = new BuilderInfo();
  46.        
  47.         // Current position in the list
  48.         private BuilderInfo currentInfo;
  49.         // Builder state
  50.         private bool popScope;
  51.         private int recordState;
  52.         private int recordDepth;
  53.        
  54.         private const int NoRecord = 0;
  55.         // No part of a new record was generated (old record was cleared out)
  56.         private const int SomeRecord = 1;
  57.         // Record was generated partially (can be eventually record)
  58.         private const int HaveRecord = 2;
  59.         // Record was fully generated
  60.         private const char s_Minus = '-';
  61.         private const string s_Space = " ";
  62.         private const string s_SpaceMinus = " -";
  63.         private const char s_Question = '?';
  64.         private const char s_Greater = '>';
  65.         private const string s_SpaceGreater = " >";
  66.        
  67.         private const string PrefixFormat = "xp_{0}";
  68.         private const string s_SpaceDefault = "default";
  69.         private const string s_SpacePreserve = "preserve";
  70.        
  71.         internal RecordBuilder(RecordOutput output, XmlNameTable nameTable)
  72.         {
  73.             Debug.Assert(output != null);
  74.             this.output = output;
  75.             this.nameTable = nameTable != null ? nameTable : new NameTable();
  76.             this.atoms = new OutKeywords(this.nameTable);
  77.             this.scopeManager = new OutputScopeManager(this.nameTable, this.atoms);
  78.         }
  79.        
  80.         //
  81.         // Internal properties
  82.         //
  83.        
  84.         internal int OutputState {
  85.             get { return this.outputState; }
  86.             set { this.outputState = value; }
  87.         }
  88.        
  89.         internal RecordBuilder Next {
  90.             get { return this.next; }
  91.             set { this.next = value; }
  92.         }
  93.        
  94.         internal RecordOutput Output {
  95.             get { return this.output; }
  96.         }
  97.        
  98.         internal BuilderInfo MainNode {
  99.             get { return this.mainNode; }
  100.         }
  101.        
  102.         internal ArrayList AttributeList {
  103.             get { return this.attributeList; }
  104.         }
  105.        
  106.         internal int AttributeCount {
  107.             get { return this.attributeCount; }
  108.         }
  109.        
  110.         internal OutputScopeManager Manager {
  111.             get { return this.scopeManager; }
  112.         }
  113.        
  114.         private void ValueAppend(string s, bool disableOutputEscaping)
  115.         {
  116.             this.currentInfo.ValueAppend(s, disableOutputEscaping);
  117.         }
  118.        
  119.         private bool CanOutput(int state)
  120.         {
  121.             Debug.Assert(this.recordState != HaveRecord);
  122.            
  123.             // If we have no record cached or the next event doesn't start new record, we are OK
  124.            
  125.             if (this.recordState == NoRecord || (state & StateMachine.BeginRecord) == 0) {
  126.                 return true;
  127.             }
  128.             else {
  129.                 this.recordState = HaveRecord;
  130.                 FinalizeRecord();
  131.                 SetEmptyFlag(state);
  132.                 return this.output.RecordDone(this) == Processor.OutputResult.Continue;
  133.             }
  134.         }
  135.        
  136.         internal Processor.OutputResult BeginEvent(int state, XPathNodeType nodeType, string prefix, string name, string nspace, bool empty, object htmlProps, bool search)
  137.         {
  138.             if (!CanOutput(state)) {
  139.                 return Processor.OutputResult.Overflow;
  140.             }
  141.            
  142.             Debug.Assert(this.recordState == NoRecord || (state & StateMachine.BeginRecord) == 0);
  143.            
  144.             AdjustDepth(state);
  145.             ResetRecord(state);
  146.             PopElementScope();
  147.            
  148.             prefix = (prefix != null) ? this.nameTable.Add(prefix) : this.atoms.Empty;
  149.             name = (name != null) ? this.nameTable.Add(name) : this.atoms.Empty;
  150.             nspace = (nspace != null) ? this.nameTable.Add(nspace) : this.atoms.Empty;
  151.            
  152.             switch (nodeType) {
  153.                 case XPathNodeType.Element:
  154.                     this.mainNode.htmlProps = htmlProps as HtmlElementProps;
  155.                     this.mainNode.search = search;
  156.                     BeginElement(prefix, name, nspace, empty);
  157.                     break;
  158.                 case XPathNodeType.Attribute:
  159.                     BeginAttribute(prefix, name, nspace, htmlProps, search);
  160.                     break;
  161.                 case XPathNodeType.Namespace:
  162.                     BeginNamespace(name, nspace);
  163.                     break;
  164.                 case XPathNodeType.Text:
  165.                     break;
  166.                 case XPathNodeType.ProcessingInstruction:
  167.                     if (BeginProcessingInstruction(prefix, name, nspace) == false) {
  168.                         return Processor.OutputResult.Error;
  169.                     }
  170.                     break;
  171.                 case XPathNodeType.Comment:
  172.                     BeginComment();
  173.                     break;
  174.                 case XPathNodeType.Root:
  175.                     break;
  176.                 case XPathNodeType.Whitespace:
  177.                 case XPathNodeType.SignificantWhitespace:
  178.                 case XPathNodeType.All:
  179.                     break;
  180.             }
  181.            
  182.             return CheckRecordBegin(state);
  183.         }
  184.        
  185.         internal Processor.OutputResult TextEvent(int state, string text, bool disableOutputEscaping)
  186.         {
  187.             if (!CanOutput(state)) {
  188.                 return Processor.OutputResult.Overflow;
  189.             }
  190.            
  191.             Debug.Assert(this.recordState == NoRecord || (state & StateMachine.BeginRecord) == 0);
  192.            
  193.             AdjustDepth(state);
  194.             ResetRecord(state);
  195.             PopElementScope();
  196.            
  197.             if ((state & StateMachine.BeginRecord) != 0) {
  198.                 this.currentInfo.Depth = this.recordDepth;
  199.                 this.currentInfo.NodeType = XmlNodeType.Text;
  200.             }
  201.            
  202.             ValueAppend(text, disableOutputEscaping);
  203.            
  204.             return CheckRecordBegin(state);
  205.         }
  206.        
  207.         internal Processor.OutputResult EndEvent(int state, XPathNodeType nodeType)
  208.         {
  209.             if (!CanOutput(state)) {
  210.                 return Processor.OutputResult.Overflow;
  211.             }
  212.            
  213.             AdjustDepth(state);
  214.             PopElementScope();
  215.             this.popScope = (state & StateMachine.PopScope) != 0;
  216.            
  217.             if ((state & StateMachine.EmptyTag) != 0 && this.mainNode.IsEmptyTag == true) {
  218.                 return Processor.OutputResult.Continue;
  219.             }
  220.            
  221.             ResetRecord(state);
  222.            
  223.             if ((state & StateMachine.BeginRecord) != 0) {
  224.                 if (nodeType == XPathNodeType.Element) {
  225.                     EndElement();
  226.                 }
  227.             }
  228.            
  229.             return CheckRecordEnd(state);
  230.         }
  231.        
  232.         internal void Reset()
  233.         {
  234.             if (this.recordState == HaveRecord) {
  235.                 this.recordState = NoRecord;
  236.             }
  237.         }
  238.        
  239.         internal void TheEnd()
  240.         {
  241.             if (this.recordState == SomeRecord) {
  242.                 this.recordState = HaveRecord;
  243.                 FinalizeRecord();
  244.                 this.output.RecordDone(this);
  245.             }
  246.             this.output.TheEnd();
  247.         }
  248.        
  249.         //
  250.         // Utility implementation methods
  251.         //
  252.        
  253.         private int FindAttribute(string name, string nspace, ref string prefix)
  254.         {
  255.             Debug.Assert(this.attributeCount <= this.attributeList.Count);
  256.            
  257.             for (int attrib = 0; attrib < this.attributeCount; attrib++) {
  258.                 Debug.Assert(this.attributeList[attrib] != null && this.attributeList[attrib] is BuilderInfo);
  259.                
  260.                 BuilderInfo attribute = (BuilderInfo)this.attributeList[attrib];
  261.                
  262.                 if (Keywords.Equals(attribute.LocalName, name)) {
  263.                     if (Keywords.Equals(attribute.NamespaceURI, nspace)) {
  264.                         return attrib;
  265.                     }
  266.                     if (Keywords.Equals(attribute.Prefix, prefix)) {
  267.                         // prefix conflict. Should be renamed.
  268.                         prefix = string.Empty;
  269.                     }
  270.                 }
  271.                
  272.             }
  273.            
  274.             return -1;
  275.         }
  276.        
  277.         private void BeginElement(string prefix, string name, string nspace, bool empty)
  278.         {
  279.             Debug.Assert(this.attributeCount == 0);
  280.            
  281.             this.currentInfo.NodeType = XmlNodeType.Element;
  282.             this.currentInfo.Prefix = prefix;
  283.             this.currentInfo.LocalName = name;
  284.             this.currentInfo.NamespaceURI = nspace;
  285.             this.currentInfo.Depth = this.recordDepth;
  286.             this.currentInfo.IsEmptyTag = empty;
  287.            
  288.             this.scopeManager.PushScope(name, nspace, prefix);
  289.         }
  290.        
  291.         private void EndElement()
  292.         {
  293.             Debug.Assert(this.attributeCount == 0);
  294.             OutputScope elementScope = this.scopeManager.CurrentElementScope;
  295.            
  296.             this.currentInfo.NodeType = XmlNodeType.EndElement;
  297.             this.currentInfo.Prefix = elementScope.Prefix;
  298.             this.currentInfo.LocalName = elementScope.Name;
  299.             this.currentInfo.NamespaceURI = elementScope.Namespace;
  300.             this.currentInfo.Depth = this.recordDepth;
  301.         }
  302.        
  303.         private int NewAttribute()
  304.         {
  305.             if (this.attributeCount >= this.attributeList.Count) {
  306.                 Debug.Assert(this.attributeCount == this.attributeList.Count);
  307.                 this.attributeList.Add(new BuilderInfo());
  308.             }
  309.             return this.attributeCount++;
  310.         }
  311.        
  312.         private void BeginAttribute(string prefix, string name, string nspace, object htmlAttrProps, bool search)
  313.         {
  314.             int attrib = FindAttribute(name, nspace, ref prefix);
  315.            
  316.             if (attrib == -1) {
  317.                 attrib = NewAttribute();
  318.             }
  319.            
  320.             Debug.Assert(this.attributeList[attrib] != null && this.attributeList[attrib] is BuilderInfo);
  321.            
  322.             BuilderInfo attribute = (BuilderInfo)this.attributeList[attrib];
  323.             attribute.Initialize(prefix, name, nspace);
  324.             attribute.Depth = this.recordDepth;
  325.             attribute.NodeType = XmlNodeType.Attribute;
  326.             attribute.htmlAttrProps = htmlAttrProps as HtmlAttributeProps;
  327.             attribute.search = search;
  328.             this.currentInfo = attribute;
  329.         }
  330.        
  331.         private void BeginNamespace(string name, string nspace)
  332.         {
  333.             bool thisScope = false;
  334.             if (Keywords.Equals(name, this.atoms.Empty)) {
  335.                 if (Keywords.Equals(nspace, this.scopeManager.DefaultNamespace)) {
  336.                     // Main Node is OK
  337.                 }
  338.                 else if (Keywords.Equals(this.mainNode.NamespaceURI, this.atoms.Empty)) {
  339.                 }
  340.                 else {
  341.                     DeclareNamespace(nspace, name);
  342.                 }
  343.             }
  344.             else {
  345.                 string nspaceDeclared = this.scopeManager.ResolveNamespace(name, out thisScope);
  346.                 if (nspaceDeclared != null) {
  347.                     if (!Keywords.Equals(nspace, nspaceDeclared)) {
  348.                         if (!thisScope) {
  349.                             DeclareNamespace(nspace, name);
  350.                         }
  351.                     }
  352.                 }
  353.                 else {
  354.                     DeclareNamespace(nspace, name);
  355.                 }
  356.             }
  357.             this.currentInfo = dummy;
  358.             currentInfo.NodeType = XmlNodeType.Attribute;
  359.         }
  360.        
  361.         private bool BeginProcessingInstruction(string prefix, string name, string nspace)
  362.         {
  363.             this.currentInfo.NodeType = XmlNodeType.ProcessingInstruction;
  364.             this.currentInfo.Prefix = prefix;
  365.             this.currentInfo.LocalName = name;
  366.             this.currentInfo.NamespaceURI = nspace;
  367.             this.currentInfo.Depth = this.recordDepth;
  368.             return true;
  369.         }
  370.        
  371.         private void BeginComment()
  372.         {
  373.             this.currentInfo.NodeType = XmlNodeType.Comment;
  374.             this.currentInfo.Depth = this.recordDepth;
  375.         }
  376.        
  377.         private void AdjustDepth(int state)
  378.         {
  379.             switch (state & StateMachine.DepthMask) {
  380.                 case StateMachine.DepthUp:
  381.                     this.recordDepth++;
  382.                     break;
  383.                 case StateMachine.DepthDown:
  384.                     this.recordDepth--;
  385.                     break;
  386.                 default:
  387.                     break;
  388.             }
  389.         }
  390.        
  391.         private void ResetRecord(int state)
  392.         {
  393.             Debug.Assert(this.recordState == NoRecord || this.recordState == SomeRecord);
  394.            
  395.             if ((state & StateMachine.BeginRecord) != 0) {
  396.                 this.attributeCount = 0;
  397.                 this.namespaceCount = 0;
  398.                 this.currentInfo = this.mainNode;
  399.                
  400.                 this.currentInfo.Initialize(this.atoms.Empty, this.atoms.Empty, this.atoms.Empty);
  401.                 this.currentInfo.NodeType = XmlNodeType.None;
  402.                 this.currentInfo.IsEmptyTag = false;
  403.                 this.currentInfo.htmlProps = null;
  404.                 this.currentInfo.htmlAttrProps = null;
  405.             }
  406.         }
  407.        
  408.         private void PopElementScope()
  409.         {
  410.             if (this.popScope) {
  411.                 this.scopeManager.PopScope();
  412.                 this.popScope = false;
  413.             }
  414.         }
  415.        
  416.         private Processor.OutputResult CheckRecordBegin(int state)
  417.         {
  418.             Debug.Assert(this.recordState == NoRecord || this.recordState == SomeRecord);
  419.            
  420.             if ((state & StateMachine.EndRecord) != 0) {
  421.                 this.recordState = HaveRecord;
  422.                 FinalizeRecord();
  423.                 SetEmptyFlag(state);
  424.                 return this.output.RecordDone(this);
  425.             }
  426.             else {
  427.                 this.recordState = SomeRecord;
  428.                 return Processor.OutputResult.Continue;
  429.             }
  430.         }
  431.        
  432.         private Processor.OutputResult CheckRecordEnd(int state)
  433.         {
  434.             Debug.Assert(this.recordState == NoRecord || this.recordState == SomeRecord);
  435.            
  436.             if ((state & StateMachine.EndRecord) != 0) {
  437.                 this.recordState = HaveRecord;
  438.                 FinalizeRecord();
  439.                 SetEmptyFlag(state);
  440.                 return this.output.RecordDone(this);
  441.             }
  442.             else {
  443.                 // For end event, if there is no end token, don't force token
  444.                 return Processor.OutputResult.Continue;
  445.             }
  446.         }
  447.        
  448.         private void SetEmptyFlag(int state)
  449.         {
  450.             Debug.Assert(this.mainNode != null);
  451.            
  452.             if ((state & StateMachine.BeginChild) != 0) {
  453.                 this.mainNode.IsEmptyTag = false;
  454.             }
  455.         }
  456.        
  457.        
  458.         private void AnalyzeSpaceLang()
  459.         {
  460.             Debug.Assert(this.mainNode.NodeType == XmlNodeType.Element);
  461.            
  462.             for (int attr = 0; attr < this.attributeCount; attr++) {
  463.                 Debug.Assert(this.attributeList[attr] is BuilderInfo);
  464.                 BuilderInfo info = (BuilderInfo)this.attributeList[attr];
  465.                
  466.                 if (Keywords.Equals(info.Prefix, this.atoms.Xml)) {
  467.                     OutputScope scope = this.scopeManager.CurrentElementScope;
  468.                    
  469.                     if (Keywords.Equals(info.LocalName, this.atoms.Lang)) {
  470.                         scope.Lang = info.Value;
  471.                     }
  472.                     else if (Keywords.Equals(info.LocalName, this.atoms.Space)) {
  473.                         scope.Space = TranslateXmlSpace(info.Value);
  474.                     }
  475.                 }
  476.             }
  477.         }
  478.        
  479.         private void FixupElement()
  480.         {
  481.             Debug.Assert(this.mainNode.NodeType == XmlNodeType.Element);
  482.            
  483.             if (Keywords.Equals(this.mainNode.NamespaceURI, this.atoms.Empty)) {
  484.                 this.mainNode.Prefix = this.atoms.Empty;
  485.             }
  486.            
  487.             if (Keywords.Equals(this.mainNode.Prefix, this.atoms.Empty)) {
  488.                 if (Keywords.Equals(this.mainNode.NamespaceURI, this.scopeManager.DefaultNamespace)) {
  489.                     // Main Node is OK
  490.                 }
  491.                 else {
  492.                     DeclareNamespace(this.mainNode.NamespaceURI, this.mainNode.Prefix);
  493.                 }
  494.             }
  495.             else {
  496.                 bool thisScope = false;
  497.                 string nspace = this.scopeManager.ResolveNamespace(this.mainNode.Prefix, out thisScope);
  498.                 if (nspace != null) {
  499.                     if (!Keywords.Equals(this.mainNode.NamespaceURI, nspace)) {
  500.                         if (thisScope) {
  501.                             // Prefix conflict
  502.                             this.mainNode.Prefix = GetPrefixForNamespace(this.mainNode.NamespaceURI);
  503.                         }
  504.                         else {
  505.                             DeclareNamespace(this.mainNode.NamespaceURI, this.mainNode.Prefix);
  506.                         }
  507.                     }
  508.                 }
  509.                 else {
  510.                     DeclareNamespace(this.mainNode.NamespaceURI, this.mainNode.Prefix);
  511.                 }
  512.             }
  513.            
  514.             OutputScope elementScope = this.scopeManager.CurrentElementScope;
  515.             elementScope.Prefix = this.mainNode.Prefix;
  516.         }
  517.        
  518.         private void FixupAttributes(int attributeCount)
  519.         {
  520.             for (int attr = 0; attr < attributeCount; attr++) {
  521.                 Debug.Assert(this.attributeList[attr] is BuilderInfo);
  522.                 BuilderInfo info = (BuilderInfo)this.attributeList[attr];
  523.                
  524.                
  525.                 if (Keywords.Equals(info.NamespaceURI, this.atoms.Empty)) {
  526.                     info.Prefix = this.atoms.Empty;
  527.                 }
  528.                 else {
  529.                     if (Keywords.Equals(info.Prefix, this.atoms.Empty)) {
  530.                         info.Prefix = GetPrefixForNamespace(info.NamespaceURI);
  531.                     }
  532.                     else {
  533.                         bool thisScope = false;
  534.                         string nspace = this.scopeManager.ResolveNamespace(info.Prefix, out thisScope);
  535.                         if (nspace != null) {
  536.                             if (!Keywords.Equals(info.NamespaceURI, nspace)) {
  537.                                 if (thisScope) {
  538.                                     // prefix conflict
  539.                                     info.Prefix = GetPrefixForNamespace(info.NamespaceURI);
  540.                                 }
  541.                                 else {
  542.                                     DeclareNamespace(info.NamespaceURI, info.Prefix);
  543.                                 }
  544.                             }
  545.                         }
  546.                         else {
  547.                             DeclareNamespace(info.NamespaceURI, info.Prefix);
  548.                         }
  549.                     }
  550.                 }
  551.             }
  552.         }
  553.        
  554.         private void AppendNamespaces()
  555.         {
  556.             for (int i = this.namespaceCount - 1; i >= 0; i--) {
  557.                 BuilderInfo attribute = (BuilderInfo)this.attributeList[NewAttribute()];
  558.                 attribute.Initialize((BuilderInfo)this.namespaceList[i]);
  559.             }
  560.         }
  561.        
  562.         private void AnalyzeComment()
  563.         {
  564.             Debug.Assert(this.mainNode.NodeType == XmlNodeType.Comment);
  565.             Debug.Assert((object)this.currentInfo == (object)this.mainNode);
  566.            
  567.             StringBuilder newComment = null;
  568.             string comment = this.mainNode.Value;
  569.             bool minus = false;
  570.             int index = 0;
  571.             int begin = 0;
  572.            
  573.             for (; index < comment.Length; index++) {
  574.                 switch (comment[index]) {
  575.                     case s_Minus:
  576.                         if (minus) {
  577.                             if (newComment == null)
  578.                                 newComment = new StringBuilder(comment, begin, index, 2 * comment.Length);
  579.                             else
  580.                                 newComment.Append(comment, begin, index - begin);
  581.                            
  582.                             newComment.Append(s_SpaceMinus);
  583.                             begin = index + 1;
  584.                         }
  585.                         minus = true;
  586.                         break;
  587.                     default:
  588.                         minus = false;
  589.                         break;
  590.                 }
  591.             }
  592.            
  593.             if (newComment != null) {
  594.                 if (begin < comment.Length)
  595.                     newComment.Append(comment, begin, comment.Length - begin);
  596.                
  597.                 if (minus)
  598.                     newComment.Append(s_Space);
  599.                
  600.                 this.mainNode.Value = newComment.ToString();
  601.             }
  602.             else if (minus) {
  603.                 this.mainNode.ValueAppend(s_Space, false);
  604.             }
  605.         }
  606.        
  607.         private void AnalyzeProcessingInstruction()
  608.         {
  609.             Debug.Assert(this.mainNode.NodeType == XmlNodeType.ProcessingInstruction || this.mainNode.NodeType == XmlNodeType.XmlDeclaration);
  610.             //Debug.Assert((object) this.currentInfo == (object) this.mainNode);
  611.            
  612.             StringBuilder newPI = null;
  613.             string pi = this.mainNode.Value;
  614.             bool question = false;
  615.             int index = 0;
  616.             int begin = 0;
  617.            
  618.             for (; index < pi.Length; index++) {
  619.                 switch (pi[index]) {
  620.                     case s_Question:
  621.                         question = true;
  622.                         break;
  623.                     case s_Greater:
  624.                         if (question) {
  625.                             if (newPI == null) {
  626.                                 newPI = new StringBuilder(pi, begin, index, 2 * pi.Length);
  627.                             }
  628.                             else {
  629.                                 newPI.Append(pi, begin, index - begin);
  630.                             }
  631.                             newPI.Append(s_SpaceGreater);
  632.                             begin = index + 1;
  633.                         }
  634.                         question = false;
  635.                         break;
  636.                     default:
  637.                         question = false;
  638.                         break;
  639.                 }
  640.             }
  641.            
  642.             if (newPI != null) {
  643.                 if (begin < pi.Length) {
  644.                     newPI.Append(pi, begin, pi.Length - begin);
  645.                 }
  646.                 this.mainNode.Value = newPI.ToString();
  647.             }
  648.         }
  649.        
  650.         private void FinalizeRecord()
  651.         {
  652.             switch (this.mainNode.NodeType) {
  653.                 case XmlNodeType.Element:
  654.                     // Save count since FixupElement can add attribute...
  655.                     int attributeCount = this.attributeCount;
  656.                    
  657.                     FixupElement();
  658.                     FixupAttributes(attributeCount);
  659.                     AnalyzeSpaceLang();
  660.                     AppendNamespaces();
  661.                     break;
  662.                 case XmlNodeType.Comment:
  663.                     AnalyzeComment();
  664.                     break;
  665.                 case XmlNodeType.ProcessingInstruction:
  666.                     AnalyzeProcessingInstruction();
  667.                     break;
  668.             }
  669.         }
  670.        
  671.         private int NewNamespace()
  672.         {
  673.             if (this.namespaceCount >= this.namespaceList.Count) {
  674.                 Debug.Assert(this.namespaceCount == this.namespaceList.Count);
  675.                 this.namespaceList.Add(new BuilderInfo());
  676.             }
  677.             return this.namespaceCount++;
  678.         }
  679.        
  680.         private void DeclareNamespace(string nspace, string prefix)
  681.         {
  682.             int index = NewNamespace();
  683.            
  684.             Debug.Assert(this.namespaceList[index] != null && this.namespaceList[index] is BuilderInfo);
  685.            
  686.             BuilderInfo ns = (BuilderInfo)this.namespaceList[index];
  687.             if (prefix == this.atoms.Empty) {
  688.                 ns.Initialize(this.atoms.Empty, this.atoms.Xmlns, this.atoms.XmlnsNamespace);
  689.             }
  690.             else {
  691.                 ns.Initialize(this.atoms.Xmlns, prefix, this.atoms.XmlnsNamespace);
  692.             }
  693.             ns.Depth = this.recordDepth;
  694.             ns.NodeType = XmlNodeType.Attribute;
  695.             ns.Value = nspace;
  696.            
  697.             this.scopeManager.PushNamespace(prefix, nspace);
  698.         }
  699.        
  700.         private string DeclareNewNamespace(string nspace)
  701.         {
  702.             string prefix = this.scopeManager.GeneratePrefix(PrefixFormat);
  703.             DeclareNamespace(nspace, prefix);
  704.             return prefix;
  705.         }
  706.        
  707.         internal string GetPrefixForNamespace(string nspace)
  708.         {
  709.             string prefix = null;
  710.            
  711.             if (this.scopeManager.FindPrefix(nspace, out prefix)) {
  712.                 Debug.Assert(prefix != null && prefix.Length > 0);
  713.                 return prefix;
  714.             }
  715.             else {
  716.                 return DeclareNewNamespace(nspace);
  717.             }
  718.         }
  719.        
  720.         private static XmlSpace TranslateXmlSpace(string space)
  721.         {
  722.             if (Keywords.Compare(space, s_SpaceDefault)) {
  723.                 return XmlSpace.Default;
  724.             }
  725.             else if (Keywords.Compare(space, s_SpacePreserve)) {
  726.                 return XmlSpace.Preserve;
  727.             }
  728.             else {
  729.                 return XmlSpace.None;
  730.             }
  731.         }
  732.     }
  733. }

Developer Fusion