private XmlNode LoadNode(bool skipOverWhitespace)
{
XmlReader r = _reader;
XmlNode parent = null;
XmlElement element;
IXmlSchemaInfo schemaInfo;
do
{
XmlNode node = null;
switch (r.NodeType)
{
case XmlNodeType.Element:
bool fEmptyElement = r.IsEmptyElement;
element = _doc.CreateElement(r.Prefix, r.LocalName, r.NamespaceURI);
element.IsEmpty = fEmptyElement;
if (r.MoveToFirstAttribute())
{
XmlAttributeCollection attributes = element.Attributes;
do
{
XmlAttribute attr = LoadAttributeNode();
attributes.Append(attr); // special case for load
}
while (r.MoveToNextAttribute());
r.MoveToElement();
}
// recursively load all children.
if (!fEmptyElement)
{
if (parent != null)
{
parent.AppendChildForLoad(element, _doc);
}
parent = element;
continue;
}
else
{
schemaInfo = r.SchemaInfo;
if (schemaInfo != null)
{
element.XmlName = _doc.AddXmlName(element.Prefix, element.LocalName, element.NamespaceURI, schemaInfo);
}
node = element;
break;
}
case XmlNodeType.EndElement:
if (parent == null)
{
return null;
}
Debug.Assert(parent.NodeType == XmlNodeType.Element);
schemaInfo = r.SchemaInfo;
if (schemaInfo != null)
{
element = parent as XmlElement;
if (element != null)
{
element.XmlName = _doc.AddXmlName(element.Prefix, element.LocalName, element.NamespaceURI, schemaInfo);
}
}
if (parent.ParentNode == null)
{
return parent;
}
parent = parent.ParentNode;
continue;
case XmlNodeType.EntityReference:
node = LoadEntityReferenceNode(false);
break;
case XmlNodeType.EndEntity:
Debug.Assert(parent == null);
return null;
case XmlNodeType.Attribute:
node = LoadAttributeNode();
break;
case XmlNodeType.Text:
node = _doc.CreateTextNode(r.Value);
break;
case XmlNodeType.SignificantWhitespace:
node = _doc.CreateSignificantWhitespace(r.Value);
break;
case XmlNodeType.Whitespace:
if (_preserveWhitespace)
{
node = _doc.CreateWhitespace(r.Value);
break;
}
else if (parent == null && !skipOverWhitespace)
{
// if called from LoadEntityReferenceNode, just return null
return null;
}
else
{
continue;
}
case XmlNodeType.CDATA:
node = _doc.CreateCDataSection(r.Value);
break;
case XmlNodeType.XmlDeclaration:
node = LoadDeclarationNode();
break;
case XmlNodeType.ProcessingInstruction:
node = _doc.CreateProcessingInstruction(r.Name, r.Value);
break;
case XmlNodeType.Comment:
node = _doc.CreateComment(r.Value);
break;
case XmlNodeType.DocumentType:
node = LoadDocumentTypeNode();
break;
default:
throw UnexpectedNodeType(r.NodeType);
}
Debug.Assert(node != null);
if (parent != null)
{
parent.AppendChildForLoad(node, _doc);
}
else
{
return node;
}
}
while (r.Read());
// when the reader ended before full subtree is read, return whatever we have created so far
if (parent != null)
{
while (parent.ParentNode != null)
{
parent = parent.ParentNode;
}
}
return parent;
}