public void ReadMetadata() { while (reader.Read()) { switch (reader.NodeType) { case XmlNodeType.Element: switch (state) { case ParserState.Start: // Assumption: // - skip the soap response tags if ((reader.LocalName == "QueryXmlResponse") || (reader.LocalName == "QueryXmlResult")) { continue; } if (string.CompareOrdinal(reader.LocalName, "queryResult") == 0) { state = ParserState.Root; } else { throw new InvalidOperationException( "Expecting <queryResult> element but found " + reader.LocalName); } break; case ParserState.Root: if (string.CompareOrdinal(reader.LocalName, "queryPlan") == 0) { QueryPlan = new XmlDocument(); QueryPlan.Load(reader.ReadSubtree()); } // obsolete since 2016.2 - the statistics was put after data else if (string.CompareOrdinal(reader.LocalName, "statistics") == 0) { QueryStats = new XmlDocument(); QueryStats.Load(reader.ReadSubtree()); } else if (string.CompareOrdinal(reader.LocalName, "template") == 0) { state = ParserState.Template; } else if (string.CompareOrdinal(reader.LocalName, "data") == 0) { state = ParserState.Data; hasRows = true; string totalRowsAttr = reader.GetAttribute("totalRows"); if (!string.IsNullOrEmpty(totalRowsAttr)) { TotalRows = Convert.ToInt64(totalRowsAttr, CultureInfo.InvariantCulture); } return; } else { throw new InvalidOperationException("Unexepected element " + reader.LocalName); } break; case ParserState.Template: if (string.CompareOrdinal(reader.LocalName, "resultset") == 0) { if (columns != null) { throw new InvalidOperationException("Only one resultset is supported"); } state = ParserState.ResultSet; } break; case ParserState.ResultSet: if (string.CompareOrdinal(reader.LocalName, "column") != 0) { throw new InvalidOperationException( "Only <column> elements are expected as children of a <resultset> element"); } if (columns == null) { columns = new List <ColumnInfo>(); } ColumnInfo columnInfo = new ColumnInfo(reader["name"], reader["type"], Int32.Parse(reader["ordinal"], CultureInfo.InvariantCulture)); // TODO: this should be define in column definition columnInfo.DateTimeMode = DateTimeMode; while (reader.MoveToNextAttribute()) { var name = reader.Name; if (!name.Equals("name", StringComparison.OrdinalIgnoreCase) && !name.Equals("type", StringComparison.OrdinalIgnoreCase) && !name.Equals("ordinal", StringComparison.OrdinalIgnoreCase)) { columnInfo.AddMetadata(name, reader.Value); } } reader.MoveToElement(); columns.Add(columnInfo); // Sometime empty elements come with an end element, adjust the statemachine state accordingly if (!reader.IsEmptyElement) { state = ParserState.PropertyTemplate; } break; default: throw new InvalidOperationException("Unexpected state " + state); } break; case XmlNodeType.EndElement: switch (state) { case ParserState.Root: if (string.CompareOrdinal(reader.LocalName, "queryResult") != 0) { throw new InvalidOperationException( string.Format("Not expecting element {0} while in state {1}", reader.LocalName, state)); } return; case ParserState.Template: ValidateEndElement(reader.LocalName, "template", ParserState.Root); break; case ParserState.ResultSet: ValidateEndElement(reader.LocalName, "resultset", ParserState.Template); break; case ParserState.PropertyTemplate: ValidateEndElement(reader.LocalName, "column", ParserState.ResultSet); break; default: throw new InvalidOperationException( string.Format("Not expecting element {0} while in state {1}", reader.LocalName, state)); } break; } } throw new InvalidOperationException("Malformed Xml result"); }