We need you! We're working hard on the next version of Developer Fusion - Let us know what you think we should be up to!

The Labs \ Source Viewer \ SSCLI \ System.Runtime.Serialization.Formatters.Soap \ AttributeValueEntry

  1. // ==++==
  2. //
  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. //
  14. // ==--==
  15. //============================================================
  16. //
  17. // Class: SoapParser
  18. // Purpose: XML Handlers for System.XML parser
  19. //
  20. // Date: June 10, 1999
  21. //
  22. //============================================================
  23. namespace System.Runtime.Serialization.Formatters.Soap
  24. {
  25.     using System;
  26.     using System.Runtime.Serialization.Formatters;
  27.     using System.Xml;
  28.     using System.IO;
  29.     using System.Globalization;
  30.     using System.Collections;
  31.     using System.Reflection;
  32.     using System.Runtime.Serialization;
  33.     using System.Text;
  34.     using System.Runtime.Remoting;
  35.     using System.Runtime.Remoting.Messaging;
  36.     using System.Runtime.Remoting.Metadata;
  37.    
  38.    
  39.     internal sealed class SoapParser : ISerParser
  40.     {
  41.         internal XmlTextReader xmlReader;
  42.         internal SoapHandler soapHandler;
  43.         internal ObjectReader objectReader;
  44.         internal bool bStop = false;
  45.         int depth = 0;
  46.         bool bDebug = false;
  47.         TextReader textReader = null;
  48.        
  49.         internal SoapParser(Stream stream)
  50.         {
  51.             InternalST.Soap(this, "Constructor");
  52.             TraceStream(stream);
  53.             if (bDebug)
  54.                 xmlReader = new XmlTextReader(textReader);
  55.             else
  56.                 xmlReader = new XmlTextReader(stream);
  57.             xmlReader.XmlResolver = null;
  58.             xmlReader.ProhibitDtd = true;
  59.             soapHandler = new SoapHandler(this);
  60.         }
  61.        
  62.        
  63.         // Trace when checked builds
  64.         [System.Diagnostics.Conditional("_LOGGING")]
  65.         private void TraceStream(Stream stream)
  66.         {
  67.             bDebug = true;
  68.             TextReader tempReader = new StreamReader(stream);
  69.             string strbuffer = tempReader.ReadToEnd();
  70.             InternalST.InfoSoap("******************** Begin Deserialized Stream Buffer *******************");
  71.             InternalST.InfoSoap(strbuffer);
  72.             InternalST.InfoSoap("******************** End Deserialized Stream Buffer *******************");
  73.             textReader = new StringReader(strbuffer);
  74.         }
  75.        
  76.        
  77.         internal void Init(ObjectReader objectReader)
  78.         {
  79.             InternalST.Soap(this, "Init");
  80.             this.objectReader = objectReader;
  81.             soapHandler.Init(objectReader);
  82.             bStop = false;
  83.             depth = 0;
  84.             xmlReader.ResetState();
  85.         }
  86.        
  87.         // Start parsing the input
  88.         public void Run()
  89.         {
  90.             InternalST.Soap(this, "Run");
  91.             try {
  92.                 soapHandler.Start(xmlReader);
  93.                 ParseXml();
  94.             }
  95.             catch (EndOfStreamException) {
  96.             }
  97.         }
  98.        
  99.         internal void Stop()
  100.         {
  101.             InternalST.Soap(this, "Stop");
  102.             bStop = true;
  103.         }
  104.        
  105.        
  106.         private void ParseXml()
  107.         {
  108.             InternalST.Soap(this, "ParseXml");
  109.             while (!bStop && xmlReader.Read()) {
  110.                 if (depth < xmlReader.Depth) {
  111.                     soapHandler.StartChildren();
  112.                     depth = xmlReader.Depth;
  113.                 }
  114.                 else if (depth > xmlReader.Depth) {
  115.                     soapHandler.FinishChildren(xmlReader.Prefix, xmlReader.LocalName, xmlReader.NamespaceURI);
  116.                     depth = xmlReader.Depth;
  117.                 }
  118.                
  119.                 switch (xmlReader.NodeType) {
  120.                     case (XmlNodeType.None):
  121.                         break;
  122.                     case (XmlNodeType.Element):
  123.                         Dump("Node Element", xmlReader);
  124.                         soapHandler.StartElement(xmlReader.Prefix, xmlReader.LocalName, xmlReader.NamespaceURI);
  125.                         int attributeCount = xmlReader.AttributeCount;
  126.                         while (xmlReader.MoveToNextAttribute()) {
  127.                             soapHandler.Attribute(xmlReader.Prefix, xmlReader.LocalName, xmlReader.NamespaceURI, xmlReader.Value);
  128.                         }
  129.                         xmlReader.MoveToElement();
  130.                         if (xmlReader.IsEmptyElement)
  131.                             soapHandler.EndElement(xmlReader.Prefix, xmlReader.LocalName, xmlReader.NamespaceURI);
  132.                         break;
  133.                     case XmlNodeType.EndElement:
  134.                         Dump("Node EndElement", xmlReader);
  135.                         soapHandler.EndElement(xmlReader.Prefix, xmlReader.LocalName, xmlReader.NamespaceURI);
  136.                         break;
  137.                     case (XmlNodeType.Text):
  138.                         Dump("Node Text", xmlReader);
  139.                         soapHandler.Text(xmlReader.Value);
  140.                         break;
  141.                     case (XmlNodeType.SignificantWhitespace):
  142.                         Dump("Node SignificantWhitespace", xmlReader);
  143.                         soapHandler.Text(xmlReader.Value);
  144.                         break;
  145.                     case (XmlNodeType.Whitespace):
  146.                         Dump("Node Whitespace", xmlReader);
  147.                         soapHandler.Text(xmlReader.Value);
  148.                         break;
  149.                     case (XmlNodeType.Entity):
  150.                         Dump("Node Entity", xmlReader);
  151.                         break;
  152.                     case (XmlNodeType.CDATA):
  153.                         Dump("Node CDATA", xmlReader);
  154.                         soapHandler.Text(xmlReader.Value);
  155.                         break;
  156.                     case (XmlNodeType.Comment):
  157.                         Dump("Node Comment", xmlReader);
  158.                         soapHandler.Comment(xmlReader.Value);
  159.                         break;
  160.                     case (XmlNodeType.EntityReference):
  161.                         Dump("Node EntityReference", xmlReader);
  162.                         break;
  163.                     case (XmlNodeType.ProcessingInstruction):
  164.                         Dump("Node ProcessingInstruction", xmlReader);
  165.                         break;
  166.                     case (XmlNodeType.Document):
  167.                         Dump("Node Document", xmlReader);
  168.                         break;
  169.                     case (XmlNodeType.DocumentType):
  170.                         Dump("Node DocumentType", xmlReader);
  171.                         break;
  172.                     case (XmlNodeType.DocumentFragment):
  173.                         Dump("Node DocumentFragment", xmlReader);
  174.                         break;
  175.                     case (XmlNodeType.Notation):
  176.                         Dump("Node Notation", xmlReader);
  177.                         break;
  178.                     case (XmlNodeType.EndEntity):
  179.                         Dump("Node EndEntity", xmlReader);
  180.                         break;
  181.                     default:
  182.                         Dump("Node Default", xmlReader);
  183.                         break;
  184.                 }
  185.                
  186.             }
  187.         }
  188.        
  189.         [System.Diagnostics.Conditional("SER_LOGGING")]
  190.         private static void Dump(string name, XmlReader xmlReader)
  191.         {
  192.             InternalST.Soap("========== " + name + " ============");
  193.             InternalST.Soap("Prefix : " + xmlReader.Prefix);
  194.             InternalST.Soap("Name : " + xmlReader.Name);
  195.             InternalST.Soap("LocalName : " + xmlReader.LocalName);
  196.             InternalST.Soap("Namespace : " + xmlReader.NamespaceURI);
  197.             InternalST.Soap("Depth : " + xmlReader.Depth);
  198.             InternalST.Soap("Value : [" + xmlReader.Value + "]");
  199.             InternalST.Soap("IsDefault : " + xmlReader.IsDefault);
  200.             InternalST.Soap("XmlSpace : " + xmlReader.XmlSpace);
  201.             InternalST.Soap("XmlLang : " + xmlReader.XmlLang);
  202.             InternalST.Soap("QuoteChar : " + xmlReader.QuoteChar);
  203.             InternalST.Soap("================================\n");
  204.         }
  205.        
  206.     }
  207.    
  208.     // Sets the handler which contains the callbacks for the parser
  209.     internal sealed class SoapHandler
  210.     {
  211.         SerStack stack = new SerStack("SoapParser Stack");
  212.        
  213.         XmlTextReader xmlTextReader = null;
  214.         SoapParser soapParser = null;
  215.        
  216.        
  217.         // Current text
  218.         string textValue = "";
  219.        
  220.         // XML Formatter
  221.         ObjectReader objectReader;
  222.         internal Hashtable keyToNamespaceTable;
  223.         //needed for xsd QName type
  224.         // Current state
  225.         InternalParseStateE currentState;
  226.         bool isEnvelope = false;
  227.         bool isBody = false;
  228.         bool isTopFound = false;
  229.         HeaderStateEnum headerState = HeaderStateEnum.None;
  230.        
  231.         // Attribute holder
  232.         SerStack attributeValues = new SerStack("AttributePrefix");
  233.        
  234.         SerStack prPool = new SerStack("prPool");
  235.        
  236.         // XML Key to AssemblyId table
  237.         // Key of SOAP has an AssemblyId of -1
  238.         // Key of urt has an AssemblyId of -2
  239.         Hashtable assemKeyToAssemblyTable = null;
  240.         Hashtable assemKeyToNameSpaceTable = null;
  241.         Hashtable assemKeyToInteropAssemblyTable = null;
  242.         Hashtable nameSpaceToKey = null;
  243.         // Used to assign a key to default xml namespaces
  244.         string soapKey = "SOAP-ENC";
  245.         //xml key for soap, should be SOAP
  246.         string urtKey = "urt";
  247.         //xml key for urt, should be urt
  248.         string soapEnvKey = "SOAP-ENV";
  249.         //xml key for SOAPRENV, initial value, might change
  250.         string xsiKey = "xsi";
  251.         //xml key for xsi, initial value, might change
  252.         string xsdKey = "xsd";
  253.         //xml key for xsd, initial value, might change
  254.         int nextPrefix = 0;
  255.         // Used to generate a prefix if necessary
  256.         internal SoapHandler(SoapParser soapParser)
  257.         {
  258.             this.soapParser = soapParser;
  259.         }
  260.        
  261.         internal void Init(ObjectReader objectReader)
  262.         {
  263.             this.objectReader = objectReader;
  264.             objectReader.soapHandler = this;
  265.             isEnvelope = false;
  266.             isBody = false;
  267.             isTopFound = false;
  268.             attributeValues.Clear();
  269.             assemKeyToAssemblyTable = new Hashtable(10);
  270.             assemKeyToAssemblyTable[urtKey] = new SoapAssemblyInfo(SoapUtil.urtAssemblyString, SoapUtil.urtAssembly);
  271.             assemKeyToNameSpaceTable = new Hashtable(10);
  272.             assemKeyToInteropAssemblyTable = new Hashtable(10);
  273.             nameSpaceToKey = new Hashtable(5);
  274.             keyToNamespaceTable = new Hashtable(10);
  275.            
  276.         }
  277.        
  278.         private string NextPrefix()
  279.         {
  280.             nextPrefix++;
  281.             return "_P" + nextPrefix;
  282.            
  283.         }
  284.        
  285.         internal class AttributeValueEntry
  286.         {
  287.             internal string prefix;
  288.             internal string key;
  289.             internal string value;
  290.             internal string urn;
  291.            
  292.             internal AttributeValueEntry(string prefix, string key, string value, string urn)
  293.             {
  294.                 this.prefix = prefix;
  295.                 this.key = key;
  296.                 this.value = value;
  297.                 this.urn = urn;
  298.             }
  299.         }
  300.        
  301.         private ParseRecord GetPr()
  302.         {
  303.             ParseRecord pr = null;
  304.            
  305.             if (!prPool.IsEmpty()) {
  306.                 pr = (ParseRecord)prPool.Pop();
  307.                 pr.Init();
  308.             }
  309.             else
  310.                 pr = new ParseRecord();
  311.            
  312.             return pr;
  313.         }
  314.        
  315.         private void PutPr(ParseRecord pr)
  316.         {
  317.             prPool.Push(pr);
  318.         }
  319.        
  320.         // Creates a trace string
  321.         private static string SerTraceString(string handler, ParseRecord pr, string value, InternalParseStateE currentState, HeaderStateEnum headerState)
  322.         {
  323.             string valueString = "";
  324.             if (value != null)
  325.                 valueString = value;
  326.            
  327.             string prString = "";
  328.             if (pr != null)
  329.                 prString = ((Enum)pr.PRparseStateEnum).ToString();
  330.            
  331.             return handler + " - " + valueString + ", State " + ((Enum)currentState).ToString() + ", PushState " + prString;
  332.         }
  333.        
  334.         #if _DEBUG
  335.         private static string SerTraceString(string handler, ParseRecord pr, string value, string prefix, string urn, InternalParseStateE currentState, HeaderStateEnum headerState)
  336.         {
  337.             string valueString = "";
  338.             if (value != null)
  339.                 valueString = value;
  340.            
  341.             string prString = "";
  342.             if (pr != null)
  343.                 prString = ((Enum)pr.PRparseStateEnum).ToString();
  344.            
  345.             return handler + " - name " + valueString + ", prefix " + prefix + ", urn " + urn + ", CuurentState " + ((Enum)currentState).ToString() + ", HeaderState " + ((Enum)headerState).ToString() + ", PushState " + prString;
  346.         }
  347.         #endif
  348.        
  349.        
  350.         // Formats the error message and throws a SerializationException
  351.         private void MarshalError(string handler, ParseRecord pr, string value, InternalParseStateE currentState)
  352.         {
  353.             string traceString = SerTraceString(handler, pr, value, currentState, headerState);
  354.             #if _DEBUG
  355.             InternalST.Soap(this, "MarshalError,", traceString);
  356.             #endif
  357.             throw new SerializationException(String.Format(CultureInfo.CurrentCulture, SoapUtil.GetResourceString("Serialization_Syntax"), traceString));
  358.         }
  359.        
  360.         // Called at the beginning of parsing
  361.         internal void Start(XmlTextReader p)
  362.         {
  363.             InternalST.Soap(this, "Start ");
  364.             currentState = InternalParseStateE.Object;
  365.             xmlTextReader = p;
  366.         }
  367.        
  368.         // Called at the begining of an element
  369.         internal void StartElement(string prefix, string name, string urn)
  370.         {
  371.             #if _DEBUG
  372.             InternalST.Soap(this, SerTraceString("StartElement Begin ", (ParseRecord)stack.Peek(), name, prefix, urn, currentState, headerState));
  373.             #endif
  374.             string actualName = NameFilter(name);
  375.             string actualPrefix = prefix;
  376.            
  377.             ParseRecord pr = null;
  378.            
  379.             if (!((urn == null) || (urn.Length == 0)) && ((prefix == null) || (prefix.Length == 0))) {
  380.                 // Need to assign a prefix to the urn
  381.                 if (nameSpaceToKey.ContainsKey(urn))
  382.                     actualPrefix = (string)nameSpaceToKey[urn];
  383.                 else {
  384.                     actualPrefix = NextPrefix();
  385.                     nameSpaceToKey[urn] = actualPrefix;
  386.                 }
  387.                 InternalST.Soap(this, "StartElement Begin null urn assigned prefix ", actualPrefix);
  388.             }
  389.            
  390.            
  391.             switch (currentState) {
  392.                 case InternalParseStateE.Object:
  393.                     pr = GetPr();
  394.                     pr.PRname = actualName;
  395.                     pr.PRnameXmlKey = actualPrefix;
  396.                     pr.PRxmlNameSpace = urn;
  397.                     pr.PRparseStateEnum = InternalParseStateE.Object;
  398.                    
  399.                     if ((String.Compare(name, "Array", StringComparison.OrdinalIgnoreCase) == 0) && actualPrefix.Equals(soapKey))
  400.                         pr.PRparseTypeEnum = InternalParseTypeE.Object;
  401.                     else if (((String.Compare(name, "anyType", StringComparison.OrdinalIgnoreCase) == 0) || (String.Compare(name, "ur-type", StringComparison.OrdinalIgnoreCase) == 0)) && actualPrefix.Equals(xsdKey)) {
  402.                         pr.PRname = "System.Object";
  403.                         pr.PRnameXmlKey = urtKey;
  404.                         pr.PRxmlNameSpace = urn;
  405.                         pr.PRparseTypeEnum = InternalParseTypeE.Object;
  406.                     }
  407.                     else if (String.Compare(urn, "http://schemas.xmlsoap.org/soap/envelope/", StringComparison.OrdinalIgnoreCase) == 0) {
  408.                         if (String.Compare(name, "Envelope", StringComparison.OrdinalIgnoreCase) == 0) {
  409.                             if (isEnvelope)
  410.                                 throw new SerializationException(String.Format(CultureInfo.CurrentCulture, SoapUtil.GetResourceString("Serialization_Parser_Envelope"), prefix + ":" + name));
  411.                            
  412.                             isEnvelope = true;
  413.                             pr.PRparseTypeEnum = InternalParseTypeE.Envelope;
  414.                         }
  415.                         else if (String.Compare(name, "Body", StringComparison.OrdinalIgnoreCase) == 0) {
  416.                             if (!isEnvelope)
  417.                                 throw new SerializationException(SoapUtil.GetResourceString("Serialization_Parser_BodyChild"));
  418.                            
  419.                             if (isBody)
  420.                                 throw new SerializationException(SoapUtil.GetResourceString("Serialization_Parser_BodyOnce"));
  421.                            
  422.                             isBody = true;
  423.                             headerState = HeaderStateEnum.None;
  424.                             isTopFound = false;
  425.                             pr.PRparseTypeEnum = InternalParseTypeE.Body;
  426.                         }
  427.                         else if (String.Compare(name, "Header", StringComparison.OrdinalIgnoreCase) == 0) {
  428.                             if (!isEnvelope)
  429.                                 throw new SerializationException(SoapUtil.GetResourceString("Serialization_Parser_Header"));
  430.                            
  431.                             pr.PRparseTypeEnum = InternalParseTypeE.Headers;
  432.                             headerState = HeaderStateEnum.FirstHeaderRecord;
  433.                         }
  434.                         else
  435.                             pr.PRparseTypeEnum = InternalParseTypeE.Object;
  436.                         //SoapFault has an envelope key
  437.                     }
  438.                     else {
  439.                         pr.PRparseTypeEnum = InternalParseTypeE.Object;
  440.                     }
  441.                    
  442.                     stack.Push(pr);
  443.                     break;
  444.                 case InternalParseStateE.Member:
  445.                    
  446.                     pr = GetPr();
  447.                    
  448.                     // Members of Top object records cannot be reused because of the need to resolving fake element
  449.                     ParseRecord objectPr = (ParseRecord)stack.Peek();
  450.                     pr.PRname = actualName;
  451.                     pr.PRnameXmlKey = actualPrefix;
  452.                     pr.PRxmlNameSpace = urn;
  453.                     pr.PRparseTypeEnum = InternalParseTypeE.Member;
  454.                     pr.PRparseStateEnum = InternalParseStateE.Member;
  455.                     stack.Push(pr);
  456.                     break;
  457.                 case InternalParseStateE.MemberChild:
  458.                    
  459.                     objectPr = (ParseRecord)stack.PeekPeek();
  460.                     pr = (ParseRecord)stack.Peek();
  461.                     pr.PRmemberValueEnum = InternalMemberValueE.Nested;
  462.                     ProcessAttributes(pr, objectPr);
  463.                     switch (headerState) {
  464.                         case HeaderStateEnum.None:
  465.                         case HeaderStateEnum.TopLevelObject:
  466.                             InternalST.Soap(this, "ObjectReader.Parse 1");
  467.                             objectReader.Parse(pr);
  468.                             pr.PRisParsed = true;
  469.                             break;
  470.                         case HeaderStateEnum.HeaderRecord:
  471.                         case HeaderStateEnum.NestedObject:
  472.                             ProcessHeaderMember(pr);
  473.                             break;
  474.                     }
  475.                    
  476.                     ParseRecord nestPr = GetPr();
  477.                     nestPr.PRparseTypeEnum = InternalParseTypeE.Member;
  478.                     nestPr.PRparseStateEnum = InternalParseStateE.Member;
  479.                     nestPr.PRname = actualName;
  480.                     nestPr.PRnameXmlKey = actualPrefix;
  481.                     pr.PRxmlNameSpace = urn;
  482.                     currentState = InternalParseStateE.Member;
  483.                     stack.Push(nestPr);
  484.                     break;
  485.                 default:
  486.                    
  487.                     MarshalError("StartElement", (ParseRecord)stack.Peek(), actualName, currentState);
  488.                     break;
  489.             }
  490.            
  491.             #if _DEBUG
  492.             InternalST.Soap(this, SerTraceString("StartElement End ", (ParseRecord)stack.Peek(), name, currentState, headerState));
  493.             #endif
  494.         }
  495.        
  496.        
  497.         // Called at the end of an element
  498.         internal void EndElement(string prefix, string name, string urn)
  499.         {
  500.             #if _DEBUG
  501.             InternalST.Soap(this, SerTraceString("EndElement Begin ", (ParseRecord)stack.Peek(), name, prefix, urn, currentState, headerState));
  502.             #endif
  503.            
  504.             string actualName = NameFilter(name);
  505.            
  506.             ParseRecord objectPr = null;
  507.             ParseRecord pr = null;
  508.            
  509.             switch (currentState) {
  510.                 case InternalParseStateE.Object:
  511.                     pr = (ParseRecord)stack.Pop();
  512.                     if (pr.PRparseTypeEnum == InternalParseTypeE.Envelope)
  513.                         pr.PRparseTypeEnum = InternalParseTypeE.EnvelopeEnd;
  514.                     else if (pr.PRparseTypeEnum == InternalParseTypeE.Body)
  515.                         pr.PRparseTypeEnum = InternalParseTypeE.BodyEnd;
  516.                     else if (pr.PRparseTypeEnum == InternalParseTypeE.Headers) {
  517.                         pr.PRparseTypeEnum = InternalParseTypeE.HeadersEnd;
  518.                         headerState = HeaderStateEnum.HeaderRecord;
  519.                     }
  520.                     else if (pr.PRarrayTypeEnum != InternalArrayTypeE.Base64) {
  521.                         // A Base64 array object treated special by ObjectReader. It is completely processed when
  522.                         // pr.PRparseTypeEnum == InternalParseTypeE.Object, an ObjectEnd is not needed to complete parsing
  523.                        
  524.                         // For an element like <element />, the check was not made for top
  525.                         objectPr = (ParseRecord)stack.Peek();
  526.                         InternalST.Soap(this, "SoapParser.EndElement TopFound " + isTopFound + " objectPr.parseTypeEnum " + (objectPr == null ? "null" : ((Enum)objectPr.PRparseTypeEnum).ToString()));
  527.                         if (!isTopFound && (objectPr != null) && (objectPr.PRparseTypeEnum == InternalParseTypeE.Body)) {
  528.                             pr.PRobjectPositionEnum = InternalObjectPositionE.Top;
  529.                             isTopFound = true;
  530.                             InternalST.Soap(this, "SoapParser.EndElement change position to top");
  531.                         }
  532.                        
  533.                         if (!pr.PRisParsed) {
  534.                             InternalST.Soap(this, "SoapParser.EndElement Object hasn't been parsed");
  535.                             if (!pr.PRisProcessAttributes && !(pr.PRobjectPositionEnum == InternalObjectPositionE.Top && objectReader.IsFakeTopObject))
  536.                                 ProcessAttributes(pr, objectPr);
  537.                             objectReader.Parse(pr);
  538.                             pr.PRisParsed = true;
  539.                         }
  540.                         pr.PRparseTypeEnum = InternalParseTypeE.ObjectEnd;
  541.                     }
  542.                    
  543.                     switch (headerState) {
  544.                         case HeaderStateEnum.None:
  545.                         case HeaderStateEnum.TopLevelObject:
  546.                             InternalST.Soap(this, "SoapParser.EndElement Parse EndObject");
  547.                             objectReader.Parse(pr);
  548.                             break;
  549.                         case HeaderStateEnum.HeaderRecord:
  550.                         case HeaderStateEnum.NestedObject:
  551.                             InternalST.Soap(this, "SoapParser.EndElement ProcessHeaderEnd");
  552.                             ProcessHeaderEnd(pr);
  553.                             break;
  554.                     }
  555.                    
  556.                     if (pr.PRparseTypeEnum == InternalParseTypeE.EnvelopeEnd) {
  557.                         // End of document
  558.                         soapParser.Stop();
  559.                     }
  560.                    
  561.                     PutPr(pr);
  562.                     break;
  563.                 case InternalParseStateE.Member:
  564.                    
  565.                     pr = (ParseRecord)stack.Peek();
  566.                     objectPr = (ParseRecord)stack.PeekPeek();
  567.                     ProcessAttributes(pr, objectPr);
  568.                    
  569.                     // Check if there are any XmlAttribute records, if there are, process them
  570.                     if (xmlAttributeList != null)
  571.                         InternalST.Soap(this, "XmlAttribute check count ", xmlAttributeList.Count);
  572.                     else
  573.                         InternalST.Soap(this, "XmlAttribute null");
  574.                    
  575.                     if ((xmlAttributeList != null) && (xmlAttributeList.Count > 0)) {
  576.                         InternalST.Soap(this, "xmlAttribute list count ", xmlAttributeList.Count);
  577.                         for (int i = 0; i < xmlAttributeList.Count; i++) {
  578.                             InternalST.Soap(this, "ObjectReader.Parse 7");
  579.                             objectReader.Parse((ParseRecord)xmlAttributeList[i]);
  580.                         }
  581.                         xmlAttributeList.Clear();
  582.                     }
  583.                    
  584.                     pr = (ParseRecord)stack.Pop();
  585.                     if ((headerState == HeaderStateEnum.TopLevelObject) && (pr.PRarrayTypeEnum == InternalArrayTypeE.Base64)) {
  586.                         // A Base64 array object treated specially by ObjectReader. It is completely processed when
  587.                         // pr.PRparseTypeEnum == InternalParseTypeE.Object, an ObjectEnd is not needed to complete parsing
  588.                         InternalST.Soap(this, "ObjectReader.Parse 3");
  589.                         objectReader.Parse(pr);
  590.                         pr.PRisParsed = true;
  591.                     }
  592.                     else if (pr.PRmemberValueEnum != InternalMemberValueE.Nested) {
  593.                         if ((pr.PRobjectTypeEnum == InternalObjectTypeE.Array) && (pr.PRmemberValueEnum != InternalMemberValueE.Null)) {
  594.                             // Empty array
  595.                             pr.PRmemberValueEnum = InternalMemberValueE.Nested;
  596.                             InternalST.Soap(this, "ObjectReader.Parse 4");
  597.                             objectReader.Parse(pr);
  598.                             pr.PRisParsed = true;
  599.                            
  600.                             pr.PRparseTypeEnum = InternalParseTypeE.MemberEnd;
  601.                         }
  602.                         else if (pr.PRidRef > 0)
  603.                             pr.PRmemberValueEnum = InternalMemberValueE.Reference;
  604.                         else if (pr.PRmemberValueEnum != InternalMemberValueE.Null)
  605.                             pr.PRmemberValueEnum = InternalMemberValueE.InlineValue;
  606.                        
  607.                         switch (headerState) {
  608.                             case HeaderStateEnum.None:
  609.                             case HeaderStateEnum.TopLevelObject:
  610.                                 InternalST.Soap(this, "ObjectReader.Parse 5");
  611.                                 if (pr.PRparseTypeEnum == InternalParseTypeE.Object) {
  612.                                     // Empty object in header case
  613.                                     if (!pr.PRisParsed)
  614.                                         objectReader.Parse(pr);
  615.                                     pr.PRparseTypeEnum = InternalParseTypeE.ObjectEnd;
  616.                                 }
  617.                                 objectReader.Parse(pr);
  618.                                 pr.PRisParsed = true;
  619.                                 break;
  620.                             case HeaderStateEnum.HeaderRecord:
  621.                             case HeaderStateEnum.NestedObject:
  622.                                 ProcessHeaderMember(pr);
  623.                                 break;
  624.                         }
  625.                     }
  626.                     else {
  627.                         // Nested member already parsed, need end to finish nested object
  628.                         pr.PRparseTypeEnum = InternalParseTypeE.MemberEnd;
  629.                         switch (headerState) {
  630.                             case HeaderStateEnum.None:
  631.                             case HeaderStateEnum.TopLevelObject:
  632.                                 InternalST.Soap(this, "ObjectReader.Parse 6");
  633.                                 objectReader.Parse(pr);
  634.                                 pr.PRisParsed = true;
  635.                                 break;
  636.                             case HeaderStateEnum.HeaderRecord:
  637.                             case HeaderStateEnum.NestedObject:
  638.                                 ProcessHeaderMemberEnd(pr);
  639.                                 break;
  640.                         }
  641.                     }
  642.                     PutPr(pr);
  643.                     break;
  644.                 case InternalParseStateE.MemberChild:
  645.                    
  646.                     pr = (ParseRecord)stack.Peek();
  647.                     if (pr.PRmemberValueEnum != InternalMemberValueE.Null)
  648.                         MarshalError("EndElement", (ParseRecord)stack.Peek(), actualName, currentState);
  649.                     break;
  650.                 default:
  651.                    
  652.                     MarshalError("EndElement", (ParseRecord)stack.Peek(), actualName, currentState);
  653.                     break;
  654.             }
  655.             #if _DEBUG
  656.             InternalST.Soap(this, SerTraceString("EndElement End ", (ParseRecord)stack.Peek(), name, currentState, headerState));
  657.             #endif
  658.         }
  659.        
  660.         // Called at the start of processing child nodes for an element
  661.         internal void StartChildren()
  662.         {
  663.             #if _DEBUG
  664.             InternalST.Soap(this, SerTraceString("StartChildren Begin ", (ParseRecord)stack.Peek(), null, currentState, headerState));
  665.             #endif
  666.             ParseRecord pr = null;
  667.            
  668.             switch (currentState) {
  669.                 case InternalParseStateE.Object:
  670.                     InternalST.Soap(this, "StartChildren Object");
  671.                     pr = (ParseRecord)stack.Peek();
  672.                     ParseRecord objectPr = (ParseRecord)stack.PeekPeek();
  673.                     ProcessAttributes(pr, objectPr);
  674.                     if (pr.PRarrayTypeEnum != InternalArrayTypeE.Base64) {
  675.                         if (!((pr.PRparseTypeEnum == InternalParseTypeE.Envelope) || (pr.PRparseTypeEnum == InternalParseTypeE.Body))) {
  676.                             currentState = InternalParseStateE.Member;
  677.                            
  678.                         }
  679.                        
  680.                         switch (headerState) {
  681.                             case HeaderStateEnum.None:
  682.                             case HeaderStateEnum.TopLevelObject:
  683.                                 InternalST.Soap(this, "ObjectReader.Parse 8");
  684.                                 InternalST.Soap(this, "SoapParser.StartChildren TopFound " + isTopFound + " objectPr.parseTypeEnum " + (objectPr == null ? "null" : ((Enum)objectPr.PRparseTypeEnum).ToString()));
  685.                                 if (!isTopFound && (objectPr != null) && (objectPr.PRparseTypeEnum == InternalParseTypeE.Body)) {
  686.                                     pr.PRobjectPositionEnum = InternalObjectPositionE.Top;
  687.                                     isTopFound = true;
  688.                                     InternalST.Soap(this, "SoapParser.StartChildren change position to top");
  689.                                 }
  690.                                 objectReader.Parse(pr);
  691.                                 pr.PRisParsed = true;
  692.                                 break;
  693.                             case HeaderStateEnum.HeaderRecord:
  694.                             case HeaderStateEnum.NestedObject:
  695.                             case HeaderStateEnum.FirstHeaderRecord:
  696.                                 ProcessHeader(pr);
  697.                                 break;
  698.                         }
  699.                     }
  700.                     break;
  701.                 case InternalParseStateE.Member:
  702.                    
  703.                     InternalST.Soap(this, "StartChildren Member");
  704.                     pr = (ParseRecord)stack.Peek();
  705.                     currentState = InternalParseStateE.MemberChild;
  706.                     break;
  707.                 case InternalParseStateE.MemberChild:
  708.                 default:
  709.                    
  710.                     MarshalError("StartChildren", (ParseRecord)stack.Peek(), null, currentState);
  711.                     break;
  712.             }
  713.            
  714.             #if _DEBUG
  715.             InternalST.Soap(this, "StartChildren 10");
  716.             InternalST.Soap(this, SerTraceString("StartChildren End ", (ParseRecord)stack.Peek(), null, currentState, headerState));
  717.             #endif
  718.         }
  719.        
  720.         // Called at the end of process the child nodes for an element
  721.         internal void FinishChildren(string prefix, string name, string urn)
  722.         {
  723.             #if _DEBUG
  724.             InternalST.Soap(this, SerTraceString("FinishChildren Begin ", (ParseRecord)stack.Peek(), name, prefix, urn, currentState, headerState));
  725.             #endif
  726.             ParseRecord pr = null;
  727.            
  728.             switch (currentState) {
  729.                 case InternalParseStateE.Member:
  730.                     pr = (ParseRecord)stack.Peek();
  731.                     currentState = pr.PRparseStateEnum;
  732.                     // For an object which has a value such as top level System.String
  733.                     pr.PRvalue = textValue;
  734.                     textValue = "";
  735.                     break;
  736.                 case InternalParseStateE.MemberChild:
  737.                    
  738.                     pr = (ParseRecord)stack.Peek();
  739.                     currentState = pr.PRparseStateEnum;
  740.                    
  741.                     ParseRecord objectPr = (ParseRecord)stack.PeekPeek();
  742.                     pr.PRvalue = textValue;
  743.                     // Non-primitive type need to filter
  744.                     textValue = "";
  745.                    
  746.                     break;
  747.                 case InternalParseStateE.Object:
  748.                    
  749.                     pr = (ParseRecord)stack.Peek();
  750.                     if (pr.PRarrayTypeEnum == InternalArrayTypeE.Base64) {
  751.                         pr.PRvalue = textValue;
  752.                         textValue = "";
  753.                     }
  754.                     // Only occur for top obj