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

  1. //------------------------------------------------------------------------------
  2. // <copyright file="ReaderOutput.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.Globalization;
  20.     using System.Diagnostics;
  21.     using System.IO;
  22.     using System.Text;
  23.     using System.Xml;
  24.     using System.Xml.XPath;
  25.     using System.Collections;
  26.    
  27.     internal class ReaderOutput : XmlReader, RecordOutput
  28.     {
  29.         private Processor processor;
  30.         private XmlNameTable nameTable;
  31.        
  32.         // Main node + Fields Collection
  33.         private RecordBuilder builder;
  34.         private BuilderInfo mainNode;
  35.         private ArrayList attributeList;
  36.         private int attributeCount;
  37.         private BuilderInfo attributeValue;
  38.        
  39.         // OutputScopeManager
  40.         private OutputScopeManager manager;
  41.        
  42.         // Current position in the list
  43.         private int currentIndex;
  44.         private BuilderInfo currentInfo;
  45.        
  46.         // Reader state
  47.         private ReadState state = ReadState.Initial;
  48.         private bool haveRecord;
  49.        
  50.         // Static default record
  51.         static BuilderInfo s_DefaultInfo = new BuilderInfo();
  52.        
  53.         XmlEncoder encoder = new XmlEncoder();
  54.         XmlCharType xmlCharType = XmlCharType.Instance;
  55.        
  56.         internal ReaderOutput(Processor processor)
  57.         {
  58.             Debug.Assert(processor != null);
  59.             Debug.Assert(processor.NameTable != null);
  60.            
  61.             this.processor = processor;
  62.             this.nameTable = processor.NameTable;
  63.            
  64.             Reset();
  65.         }
  66.        
  67.         // XmlReader abstract methods implementation
  68.         public override XmlNodeType NodeType {
  69.             get {
  70.                 CheckCurrentInfo();
  71.                 return this.currentInfo.NodeType;
  72.             }
  73.         }
  74.        
  75.         public override string Name {
  76.             get {
  77.                 CheckCurrentInfo();
  78.                 string prefix = Prefix;
  79.                 string localName = LocalName;
  80.                
  81.                 if (prefix != null && prefix.Length > 0) {
  82.                     if (localName.Length > 0) {
  83.                         return prefix + ":" + localName;
  84.                     }
  85.                     else {
  86.                         return prefix;
  87.                     }
  88.                 }
  89.                 else {
  90.                     return localName;
  91.                 }
  92.             }
  93.         }
  94.        
  95.         public override string LocalName {
  96.             get {
  97.                 CheckCurrentInfo();
  98.                 return this.currentInfo.LocalName;
  99.             }
  100.         }
  101.        
  102.         public override string NamespaceURI {
  103.             get {
  104.                 CheckCurrentInfo();
  105.                 return this.currentInfo.NamespaceURI;
  106.             }
  107.         }
  108.        
  109.         public override string Prefix {
  110.             get {
  111.                 CheckCurrentInfo();
  112.                 return this.currentInfo.Prefix;
  113.             }
  114.         }
  115.        
  116.         public override bool HasValue {
  117.             get { return XmlReader.HasValueInternal(NodeType); }
  118.         }
  119.        
  120.         public override string Value {
  121.             get {
  122.                 CheckCurrentInfo();
  123.                 return this.currentInfo.Value;
  124.             }
  125.         }
  126.        
  127.         public override int Depth {
  128.             get {
  129.                 CheckCurrentInfo();
  130.                 return this.currentInfo.Depth;
  131.             }
  132.         }
  133.        
  134.         public override string BaseURI {
  135.             get { return string.Empty; }
  136.         }
  137.        
  138.         public override bool IsEmptyElement {
  139.             get {
  140.                 CheckCurrentInfo();
  141.                 return this.currentInfo.IsEmptyTag;
  142.             }
  143.         }
  144.        
  145.         public override char QuoteChar {
  146.             get { return encoder.QuoteChar; }
  147.         }
  148.        
  149.         public override bool IsDefault {
  150.             get { return false; }
  151.         }
  152.        
  153.         public override XmlSpace XmlSpace {
  154.             get { return this.manager != null ? this.manager.XmlSpace : XmlSpace.None; }
  155.         }
  156.        
  157.         public override string XmlLang {
  158.             get { return this.manager != null ? this.manager.XmlLang : string.Empty; }
  159.         }
  160.        
  161.         // Attribute Accessors
  162.        
  163.         public override int AttributeCount {
  164.             get { return this.attributeCount; }
  165.         }
  166.        
  167.         public override string GetAttribute(string name)
  168.         {
  169.             int ordinal;
  170.             if (FindAttribute(name, out ordinal)) {
  171.                 Debug.Assert(ordinal >= 0);
  172.                 return ((BuilderInfo)this.attributeList[ordinal]).Value;
  173.             }
  174.             else {
  175.                 Debug.Assert(ordinal == -1);
  176.                 return null;
  177.             }
  178.         }
  179.        
  180.         public override string GetAttribute(string localName, string namespaceURI)
  181.         {
  182.             int ordinal;
  183.             if (FindAttribute(localName, namespaceURI, out ordinal)) {
  184.                 Debug.Assert(ordinal >= 0);
  185.                 return ((BuilderInfo)this.attributeList[ordinal]).Value;
  186.             }
  187.             else {
  188.                 Debug.Assert(ordinal == -1);
  189.                 return null;
  190.             }
  191.         }
  192.        
  193.         public override string GetAttribute(int i)
  194.         {
  195.             BuilderInfo attribute = GetBuilderInfo(i);
  196.             return attribute.Value;
  197.         }
  198.        
  199.         public override string this[int i]
  200.         {
  201.             get { return GetAttribute(i); }
  202.         }
  203.        
  204.         public override string this[string name]
  205.         {
  206.             get { return GetAttribute(name); }
  207.         }
  208.        
  209.         public override string this[string name, string namespaceURI]
  210.         {
  211.             get { return GetAttribute(name, namespaceURI); }
  212.         }
  213.        
  214.         public override bool MoveToAttribute(string name)
  215.         {
  216.             int ordinal;
  217.             if (FindAttribute(name, out ordinal)) {
  218.                 Debug.Assert(ordinal >= 0);
  219.                 SetAttribute(ordinal);
  220.                 return true;
  221.             }
  222.             else {
  223.                 Debug.Assert(ordinal == -1);
  224.                 return false;
  225.             }
  226.         }
  227.        
  228.         public override bool MoveToAttribute(string localName, string namespaceURI)
  229.         {
  230.             int ordinal;
  231.             if (FindAttribute(localName, namespaceURI, out ordinal)) {
  232.                 Debug.Assert(ordinal >= 0);
  233.                 SetAttribute(ordinal);
  234.                 return true;
  235.             }
  236.             else {
  237.                 Debug.Assert(ordinal == -1);
  238.                 return false;
  239.             }
  240.         }
  241.        
  242.         public override void MoveToAttribute(int i)
  243.         {
  244.             if (i < 0 || this.attributeCount <= i) {
  245.                 throw new ArgumentOutOfRangeException("i");
  246.             }
  247.             SetAttribute(i);
  248.         }
  249.        
  250.         public override bool MoveToFirstAttribute()
  251.         {
  252.             if (this.attributeCount <= 0) {
  253.                 Debug.Assert(this.attributeCount == 0);
  254.                 return false;
  255.             }
  256.             else {
  257.                 SetAttribute(0);
  258.                 return true;
  259.             }
  260.         }
  261.        
  262.         public override bool MoveToNextAttribute()
  263.         {
  264.             if (this.currentIndex + 1 < this.attributeCount) {
  265.                 SetAttribute(this.currentIndex + 1);
  266.                 return true;
  267.             }
  268.             return false;
  269.         }
  270.        
  271.         public override bool MoveToElement()
  272.         {
  273.             if (NodeType == XmlNodeType.Attribute || this.currentInfo == this.attributeValue) {
  274.                 SetMainNode();
  275.                 return true;
  276.             }
  277.             return false;
  278.         }
  279.        
  280.         // Moving through the Stream
  281.        
  282.         public override bool Read()
  283.         {
  284.             Debug.Assert(this.processor != null || this.state == ReadState.Closed);
  285.            
  286.             if (this.state != ReadState.Interactive) {
  287.                 if (this.state == ReadState.Initial) {
  288.                     state = ReadState.Interactive;
  289.                 }
  290.                 else {
  291.                     return false;
  292.                 }
  293.             }
  294.            
  295.             while (true) {
  296.                 // while -- to ignor empty whitespace nodes.
  297.                 if (this.haveRecord) {
  298.                     this.processor.ResetOutput();
  299.                     this.haveRecord = false;
  300.                 }
  301.                
  302.                 this.processor.Execute();
  303.                
  304.                 if (this.haveRecord) {
  305.                     CheckCurrentInfo();
  306.                     // check text nodes on whitespaces;
  307.                     switch (this.NodeType) {
  308.                         case XmlNodeType.Text:
  309.                             if (xmlCharType.IsOnlyWhitespace(this.Value)) {
  310.                                 this.currentInfo.NodeType = XmlNodeType.Whitespace;
  311.                                 goto case XmlNodeType.Whitespace;
  312.                             }
  313.                             Debug.Assert(this.Value.Length != 0, "It whould be Whitespace in this case");
  314.                             break;
  315.                         case XmlNodeType.Whitespace:
  316.                             if (this.Value.Length == 0) {
  317.                                 continue;
  318.                                 // ignoring emty text nodes
  319.                             }
  320.                             if (this.XmlSpace == XmlSpace.Preserve) {
  321.                                 this.currentInfo.NodeType = XmlNodeType.SignificantWhitespace;
  322.                             }
  323.                             break;
  324.                     }
  325.                 }
  326.                 else {
  327.                     Debug.Assert(this.processor.ExecutionDone);
  328.                     this.state = ReadState.EndOfFile;
  329.                     Reset();
  330.                 }
  331.                
  332.                 return this.haveRecord;
  333.             }
  334.         }
  335.        
  336.         public override bool EOF {
  337.             get { return this.state == ReadState.EndOfFile; }
  338.         }
  339.        
  340.         public override void Close()
  341.         {
  342.             this.processor = null;
  343.             this.state = ReadState.Closed;
  344.             Reset();
  345.         }
  346.        
  347.         public override ReadState ReadState {
  348.             get { return this.state; }
  349.         }
  350.        
  351.         // Whole Content Read Methods
  352.         public override string ReadString()
  353.         {
  354.             string result = string.Empty;
  355.            
  356.             if (NodeType == XmlNodeType.Element || NodeType == XmlNodeType.Attribute || this.currentInfo == this.attributeValue) {
  357.                 if (this.mainNode.IsEmptyTag) {
  358.                     return result;
  359.                 }
  360.                 if (!Read()) {
  361.                     throw new InvalidOperationException(Res.GetString(Res.Xml_InvalidOperation));
  362.                 }
  363.             }
  364.            
  365.             StringBuilder sb = null;
  366.             bool first = true;
  367.            
  368.             while (true) {
  369.                 switch (NodeType) {
  370.                     case XmlNodeType.Text:
  371.                     case XmlNodeType.Whitespace:
  372.                     case XmlNodeType.SignificantWhitespace:
  373.                         // case XmlNodeType.CharacterEntity:
  374.                         if (first) {
  375.                             result = this.Value;
  376.                             first = false;
  377.                         }
  378.                         else {
  379.                             if (sb == null) {
  380.                                 sb = new StringBuilder(result);
  381.                             }
  382.                             sb.Append(this.Value);
  383.                         }
  384.                         if (!Read())
  385.                             throw new InvalidOperationException(Res.GetString(Res.Xml_InvalidOperation));
  386.                         break;
  387.                     default:
  388.                         return (sb == null) ? result : sb.ToString();
  389.                 }
  390.             }
  391.         }
  392.        
  393.         public override string ReadInnerXml()
  394.         {
  395.             if (ReadState == ReadState.Interactive) {
  396.                 if (NodeType == XmlNodeType.Element && !IsEmptyElement) {
  397.                     StringOutput output = new StringOutput(this.processor);
  398.                     output.OmitXmlDecl();
  399.                     int depth = Depth;
  400.                    
  401.                     Read();
  402.                     // skeep begin Element
  403.                     while (depth < Depth) {
  404.                         // process content
  405.                         Debug.Assert(this.builder != null);
  406.                         output.RecordDone(this.builder);
  407.                         Read();
  408.                     }
  409.                     Debug.Assert(NodeType == XmlNodeType.EndElement);
  410.                     Read();
  411.                     // skeep end element
  412.                     output.TheEnd();
  413.                     return output.Result;
  414.                 }
  415.                 else if (NodeType == XmlNodeType.Attribute) {
  416.                     return encoder.AtributeInnerXml(Value);
  417.                 }
  418.                 else {
  419.                     Read();
  420.                 }
  421.             }
  422.             return string.Empty;
  423.         }
  424.        
  425.         public override string ReadOuterXml()
  426.         {
  427.             if (ReadState == ReadState.Interactive) {
  428.                 if (NodeType == XmlNodeType.Element) {
  429.                     StringOutput output = new StringOutput(this.processor);
  430.                     output.OmitXmlDecl();
  431.                     bool emptyElement = IsEmptyElement;
  432.                     int depth = Depth;
  433.                     // process current record
  434.                     output.RecordDone(this.builder);
  435.                     Read();
  436.                     // process internal elements & text nodes
  437.                     while (depth < Depth) {
  438.                         Debug.Assert(this.builder != null);
  439.                         output.RecordDone(this.builder);
  440.                         Read();
  441.                     }
  442.                     // process end element
  443.                     if (!emptyElement) {
  444.                         output.RecordDone(this.builder);
  445.                         Read();
  446.                     }
  447.                    
  448.                     output.TheEnd();
  449.                     return output.Result;
  450.                 }
  451.                 else if (NodeType == XmlNodeType.Attribute) {
  452.                     return encoder.AtributeOuterXml(Name, Value);
  453.                 }
  454.                 else {
  455.                     Read();
  456.                 }
  457.             }
  458.             return string.Empty;
  459.         }
  460.        
  461.         //
  462.         // Nametable and Namespace Helpers
  463.         //
  464.        
  465.         public override XmlNameTable NameTable {
  466.             get {
  467.                 Debug.Assert(this.nameTable != null);
  468.                 return this.nameTable;
  469.             }
  470.         }
  471.        
  472.         public override string LookupNamespace(string prefix)
  473.         {
  474.             prefix = this.nameTable.Get(prefix);
  475.            
  476.             if (this.manager != null && prefix != null) {
  477.                 return this.manager.ResolveNamespace(prefix);
  478.             }
  479.             return null;
  480.         }
  481.        
  482.         public override void ResolveEntity()
  483.         {
  484.             Debug.Assert(NodeType != XmlNodeType.EntityReference);
  485.            
  486.             if (NodeType != XmlNodeType.EntityReference) {
  487.                 throw new InvalidOperationException(Res.GetString(Res.Xml_InvalidOperation));
  488.             }
  489.         }
  490.        
  491.         public override bool ReadAttributeValue()
  492.         {
  493.             if (ReadState != ReadState.Interactive || NodeType != XmlNodeType.Attribute) {
  494.                 return false;
  495.             }
  496.            
  497.             if (this.attributeValue == null) {
  498.                 this.attributeValue = new BuilderInfo();
  499.                 this.attributeValue.NodeType = XmlNodeType.Text;
  500.             }
  501.             if (this.currentInfo == this.attributeValue) {
  502.                 return false;
  503.             }
  504.            
  505.             this.attributeValue.Value = this.currentInfo.Value;
  506.             this.attributeValue.Depth = this.currentInfo.Depth + 1;
  507.             this.currentInfo = this.attributeValue;
  508.            
  509.             return true;
  510.         }
  511.        
  512.         //
  513.         // RecordOutput interface method implementation
  514.         //
  515.        
  516.         public Processor.OutputResult RecordDone(RecordBuilder record)
  517.         {
  518.             this.builder = record;
  519.             this.mainNode = record.MainNode;
  520.             this.attributeList = record.AttributeList;
  521.             this.attributeCount = record.AttributeCount;
  522.             this.manager = record.Manager;
  523.            
  524.             this.haveRecord = true;
  525.             SetMainNode();
  526.            
  527.             return Processor.OutputResult.Interrupt;
  528.         }
  529.        
  530.         public void TheEnd()
  531.         {
  532.             // nothing here, was taken care of by RecordBuilder
  533.         }
  534.        
  535.         //
  536.         // Implementation internals
  537.         //
  538.        
  539.         private void SetMainNode()
  540.         {
  541.             this.currentIndex = -1;
  542.             this.currentInfo = this.mainNode;
  543.         }
  544.        
  545.         private void SetAttribute(int attrib)
  546.         {
  547.             Debug.Assert(0 <= attrib && attrib < this.attributeCount);
  548.             Debug.Assert(0 <= attrib && attrib < this.attributeList.Count);
  549.             Debug.Assert(this.attributeList[attrib] is BuilderInfo);
  550.            
  551.             this.currentIndex = attrib;
  552.             this.currentInfo = (BuilderInfo)this.attributeList[attrib];
  553.         }
  554.        
  555.         private BuilderInfo GetBuilderInfo(int attrib)
  556.         {
  557.             if (attrib < 0 || this.attributeCount <= attrib) {
  558.                 throw new ArgumentOutOfRangeException("attrib");
  559.             }
  560.            
  561.             Debug.Assert(this.attributeList[attrib] is BuilderInfo);
  562.            
  563.             return (BuilderInfo)this.attributeList[attrib];
  564.         }
  565.        
  566.         private bool FindAttribute(string localName, string namespaceURI, out int attrIndex)
  567.         {
  568.             if (namespaceURI == null) {
  569.                 namespaceURI = string.Empty;
  570.             }
  571.             if (localName == null) {
  572.                 localName = string.Empty;
  573.             }
  574.            
  575.             for (int index = 0; index < this.attributeCount; index++) {
  576.                 Debug.Assert(this.attributeList[index] is BuilderInfo);
  577.                
  578.                 BuilderInfo attribute = (BuilderInfo)this.attributeList[index];
  579.                 if (attribute.NamespaceURI == namespaceURI && attribute.LocalName == localName) {
  580.                     attrIndex = index;
  581.                     return true;
  582.                 }
  583.             }
  584.            
  585.             attrIndex = -1;
  586.             return false;
  587.         }
  588.        
  589.         private bool FindAttribute(string name, out int attrIndex)
  590.         {
  591.             if (name == null) {
  592.                 name = string.Empty;
  593.             }
  594.            
  595.             for (int index = 0; index < this.attributeCount; index++) {
  596.                 Debug.Assert(this.attributeList[index] is BuilderInfo);
  597.                
  598.                 BuilderInfo attribute = (BuilderInfo)this.attributeList[index];
  599.                 if (attribute.Name == name) {
  600.                     attrIndex = index;
  601.                     return true;
  602.                 }
  603.             }
  604.            
  605.             attrIndex = -1;
  606.             return false;
  607.         }
  608.        
  609.         private void Reset()
  610.         {
  611.             this.currentIndex = -1;
  612.             this.currentInfo = s_DefaultInfo;
  613.             this.mainNode = s_DefaultInfo;
  614.             this.manager = null;
  615.         }
  616.        
  617.         [System.Diagnostics.Conditional("DEBUG")]
  618.         private void CheckCurrentInfo()
  619.         {
  620.             Debug.Assert(this.currentInfo != null);
  621.             Debug.Assert(this.attributeCount == 0 || this.attributeList != null);
  622.             Debug.Assert((this.currentIndex == -1) == (this.currentInfo == this.mainNode));
  623.             Debug.Assert((this.currentIndex == -1) || (this.currentInfo == this.attributeValue || this.attributeList[this.currentIndex] is BuilderInfo && this.attributeList[this.currentIndex] == this.currentInfo));
  624.         }
  625.        
  626.         private class XmlEncoder
  627.         {
  628.             private StringBuilder buffer = null;
  629.             private XmlTextEncoder encoder = null;
  630.            
  631.             private void Init()
  632.             {
  633.                 buffer = new StringBuilder();
  634.                 encoder = new XmlTextEncoder(new StringWriter(buffer, CultureInfo.InvariantCulture));
  635.             }
  636.            
  637.             public string AtributeInnerXml(string value)
  638.             {
  639.                 if (encoder == null)
  640.                     Init();
  641.                 buffer.Length = 0;
  642.                 // clean buffer
  643.                     /*save:*/                encoder.StartAttribute(false);
  644.                 encoder.Write(value);
  645.                 encoder.EndAttribute();
  646.                 return buffer.ToString();
  647.             }
  648.            
  649.             public string AtributeOuterXml(string name, string value)
  650.             {
  651.                 if (encoder == null)
  652.                     Init();
  653.                 buffer.Length = 0;
  654.                 // clean buffer
  655.                 buffer.Append(name);
  656.                 buffer.Append('=');
  657.                 buffer.Append(QuoteChar);
  658.                     /*save:*/                encoder.StartAttribute(false);
  659.                 encoder.Write(value);
  660.                 encoder.EndAttribute();
  661.                 buffer.Append(QuoteChar);
  662.                 return buffer.ToString();
  663.             }
  664.            
  665.             public char QuoteChar {
  666.                 get { return '"'; }
  667.             }
  668.         }
  669.     }
  670. }

Developer Fusion