internal void EndElement(String prefix, String name, String urn)
{
#if _DEBUG
InternalST.Soap( this,SerTraceString("EndElement Begin ", (ParseRecord)stack.Peek(), name, prefix, urn, currentState, headerState));
#endif
String actualName = NameFilter(name);
ParseRecord objectPr = null;
ParseRecord pr = null;
switch (currentState)
{
case InternalParseStateE.Object:
pr = (ParseRecord)stack.Pop();
if (pr.PRparseTypeEnum == InternalParseTypeE.Envelope)
pr.PRparseTypeEnum = InternalParseTypeE.EnvelopeEnd;
else if (pr.PRparseTypeEnum == InternalParseTypeE.Body)
pr.PRparseTypeEnum = InternalParseTypeE.BodyEnd;
else if (pr.PRparseTypeEnum == InternalParseTypeE.Headers)
{
pr.PRparseTypeEnum = InternalParseTypeE.HeadersEnd;
headerState = HeaderStateEnum.HeaderRecord;
}
else if (pr.PRarrayTypeEnum != InternalArrayTypeE.Base64)
{
// A Base64 array object treated special by ObjectReader. It is completely processed when
// pr.PRparseTypeEnum == InternalParseTypeE.Object, an ObjectEnd is not needed to complete parsing
// For an element like <element />, the check was not made for top
objectPr = (ParseRecord)stack.Peek();
InternalST.Soap( this,"SoapParser.EndElement TopFound "+isTopFound+" objectPr.parseTypeEnum "+(objectPr == null?"null":((Enum)objectPr.PRparseTypeEnum).ToString()));
if (!isTopFound && (objectPr != null ) && (objectPr.PRparseTypeEnum == InternalParseTypeE.Body))
{
pr.PRobjectPositionEnum = InternalObjectPositionE.Top;
isTopFound = true;
InternalST.Soap( this,"SoapParser.EndElement change position to top");
}
if (!pr.PRisParsed)
{
InternalST.Soap( this,"SoapParser.EndElement Object hasn't been parsed");
if (!pr.PRisProcessAttributes && !(pr.PRobjectPositionEnum == InternalObjectPositionE.Top && objectReader.IsFakeTopObject))
ProcessAttributes(pr, objectPr);
objectReader.Parse(pr);
pr.PRisParsed = true;
}
pr.PRparseTypeEnum = InternalParseTypeE.ObjectEnd;
}
switch (headerState)
{
case HeaderStateEnum.None:
case HeaderStateEnum.TopLevelObject:
InternalST.Soap( this,"SoapParser.EndElement Parse EndObject");
objectReader.Parse(pr);
break;
case HeaderStateEnum.HeaderRecord:
case HeaderStateEnum.NestedObject:
InternalST.Soap( this,"SoapParser.EndElement ProcessHeaderEnd");
ProcessHeaderEnd(pr);
break;
}
if (pr.PRparseTypeEnum == InternalParseTypeE.EnvelopeEnd)
{
// End of document
soapParser.Stop();
}
PutPr(pr);
break;
case InternalParseStateE.Member:
pr = (ParseRecord)stack.Peek();
objectPr = (ParseRecord)stack.PeekPeek();
ProcessAttributes(pr, objectPr);
// Check if there are any XmlAttribute records, if there are, process them
if (xmlAttributeList != null)
InternalST.Soap( this,"XmlAttribute check count ", xmlAttributeList.Count);
else
InternalST.Soap( this,"XmlAttribute null");
if ((xmlAttributeList != null) && (xmlAttributeList.Count > 0))
{
InternalST.Soap( this,"xmlAttribute list count ", xmlAttributeList.Count);
for (int i=0; i<xmlAttributeList.Count; i++)
{
InternalST.Soap( this,"ObjectReader.Parse 7");
objectReader.Parse((ParseRecord)xmlAttributeList[i]);
}
xmlAttributeList.Clear();
}
pr = (ParseRecord)stack.Pop();
if ((headerState == HeaderStateEnum.TopLevelObject) && (pr.PRarrayTypeEnum == InternalArrayTypeE.Base64))
{
// A Base64 array object treated specially by ObjectReader. It is completely processed when
// pr.PRparseTypeEnum == InternalParseTypeE.Object, an ObjectEnd is not needed to complete parsing
InternalST.Soap( this,"ObjectReader.Parse 3");
objectReader.Parse(pr);
pr.PRisParsed = true;
}
else if (pr.PRmemberValueEnum != InternalMemberValueE.Nested)
{
if ((pr.PRobjectTypeEnum == InternalObjectTypeE.Array) && (pr.PRmemberValueEnum != InternalMemberValueE.Null))
{
// Empty array
pr.PRmemberValueEnum = InternalMemberValueE.Nested;
InternalST.Soap( this,"ObjectReader.Parse 4");
objectReader.Parse(pr);
pr.PRisParsed = true;
pr.PRparseTypeEnum = InternalParseTypeE.MemberEnd;
}
else if (pr.PRidRef > 0)
pr.PRmemberValueEnum = InternalMemberValueE.Reference;
else if (pr.PRmemberValueEnum != InternalMemberValueE.Null)
pr.PRmemberValueEnum = InternalMemberValueE.InlineValue;
switch (headerState)
{
case HeaderStateEnum.None:
case HeaderStateEnum.TopLevelObject:
InternalST.Soap( this,"ObjectReader.Parse 5");
if (pr.PRparseTypeEnum == InternalParseTypeE.Object)
{
// Empty object in header case
if (!pr.PRisParsed)
objectReader.Parse(pr);
pr.PRparseTypeEnum = InternalParseTypeE.ObjectEnd;
}
objectReader.Parse(pr);
pr.PRisParsed = true;
break;
case HeaderStateEnum.HeaderRecord:
case HeaderStateEnum.NestedObject:
ProcessHeaderMember(pr);
break;
}
}
else
{
// Nested member already parsed, need end to finish nested object
pr.PRparseTypeEnum = InternalParseTypeE.MemberEnd;
switch (headerState)
{
case HeaderStateEnum.None:
case HeaderStateEnum.TopLevelObject:
InternalST.Soap( this,"ObjectReader.Parse 6");
objectReader.Parse(pr);
pr.PRisParsed = true;
break;
case HeaderStateEnum.HeaderRecord:
case HeaderStateEnum.NestedObject:
ProcessHeaderMemberEnd(pr);
break;
}
}
PutPr(pr);
break;
case InternalParseStateE.MemberChild:
pr = (ParseRecord)stack.Peek();
if (pr.PRmemberValueEnum != InternalMemberValueE.Null)
MarshalError("EndElement", (ParseRecord)stack.Peek(), actualName, currentState);
break;
default:
MarshalError("EndElement", (ParseRecord)stack.Peek(), actualName, currentState);
break;
}
#if _DEBUG
InternalST.Soap( this,SerTraceString("EndElement End ", (ParseRecord)stack.Peek(), name, currentState, headerState));
#endif
}