internal void LoadFromReader(XmlReader reader, XmlSpace space) {
XPathDocumentBuilder builder;
IXmlLineInfo lineInfo;
string xmlnsUri;
bool topLevelReader;
int initialDepth;
if (reader == null)
throw new ArgumentNullException("reader");
// Determine line number provider
lineInfo = reader as IXmlLineInfo;
if (lineInfo == null || !lineInfo.HasLineInfo())
lineInfo = null;
this.hasLineInfo = (lineInfo != null);
this.nameTable = reader.NameTable;
builder = new XPathDocumentBuilder(this, lineInfo, reader.BaseURI, LoadFlags.None);
try {
// Determine whether reader is in initial state
topLevelReader = (reader.ReadState == ReadState.Initial);
initialDepth = reader.Depth;
// Get atomized xmlns uri
Debug.Assert((object) this.nameTable.Get(string.Empty) == (object) string.Empty, "NameTable must contain atomized string.Empty");
xmlnsUri = this.nameTable.Get("http://www.w3.org/2000/xmlns/");
// Read past Initial state; if there are no more events then load is complete
if (topLevelReader && !reader.Read())
return;
// Read all events
do {
// If reader began in intermediate state, return when all siblings have been read
if (!topLevelReader && reader.Depth < initialDepth)
return;
switch (reader.NodeType) {
case XmlNodeType.Element: {
bool isEmptyElement = reader.IsEmptyElement;
builder.WriteStartElement(reader.Prefix, reader.LocalName, reader.NamespaceURI, reader.BaseURI);
// Add attribute and namespace nodes to element
while (reader.MoveToNextAttribute()) {
string namespaceUri = reader.NamespaceURI;
if ((object) namespaceUri == (object) xmlnsUri) {
if (reader.Prefix.Length == 0) {
// Default namespace declaration "xmlns"
Debug.Assert(reader.LocalName == "xmlns");
builder.WriteNamespaceDeclaration(string.Empty, reader.Value);
}
else {
Debug.Assert(reader.Prefix == "xmlns");
builder.WriteNamespaceDeclaration(reader.LocalName, reader.Value);
}
}
else {
builder.WriteStartAttribute(reader.Prefix, reader.LocalName, namespaceUri);
builder.WriteString(reader.Value, TextBlockType.Text);
builder.WriteEndAttribute();
}
}
if (isEmptyElement)
builder.WriteEndElement(true);
break;
}
case XmlNodeType.EndElement:
builder.WriteEndElement(false);
break;
case XmlNodeType.Text:
case XmlNodeType.CDATA:
builder.WriteString(reader.Value, TextBlockType.Text);
break;
case XmlNodeType.SignificantWhitespace:
if (reader.XmlSpace == XmlSpace.Preserve)
builder.WriteString(reader.Value, TextBlockType.SignificantWhitespace);
else
// Significant whitespace without xml:space="preserve" is not significant in XPath/XQuery data model
goto case XmlNodeType.Whitespace;
break;
case XmlNodeType.Whitespace:
Debug.Assert(reader.XmlSpace != XmlSpace.Preserve);
// Always filter top-level whitespace
if (space == XmlSpace.Preserve && (!topLevelReader || reader.Depth != 0))
builder.WriteString(reader.Value, TextBlockType.Whitespace);
break;
case XmlNodeType.Comment:
builder.WriteComment(reader.Value);
break;
case XmlNodeType.ProcessingInstruction:
builder.WriteProcessingInstruction(reader.LocalName, reader.Value, reader.BaseURI);
break;
case XmlNodeType.EntityReference:
reader.ResolveEntity();
break;
case XmlNodeType.DocumentType:
// Create ID tables
SchemaInfo info = XmlReader.GetDtdSchemaInfo(reader);
if (info != null)
builder.CreateIdTables(info);
break;
case XmlNodeType.EndEntity:
case XmlNodeType.None:
case XmlNodeType.XmlDeclaration:
break;
}
}
while (reader.Read());
}
finally {
builder.Close();
}
}