private void ExitContext() { _context.Pop(); _currentPath = ConfigurationPath.Combine(_context.Reverse()); }
/// <summary> /// Read a stream of INI values into a key/value dictionary. /// </summary> /// <param name="stream">The stream of INI data.</param> /// <returns></returns> public static IDictionary <string, string> Read(TextReader stream) { var data = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase); var readerSettings = new XmlReaderSettings() { CloseInput = false, // caller will close the stream DtdProcessing = DtdProcessing.Prohibit, IgnoreComments = true, IgnoreWhitespace = true }; using (var reader = XmlReader.Create(stream, readerSettings)) { var prefixStack = new Stack <string>(); SkipUntilRootElement(reader); // We process the root element individually since it doesn't contribute to prefix ProcessAttributes(reader, prefixStack, data, AddNamePrefix); ProcessAttributes(reader, prefixStack, data, AddAttributePair); var preNodeType = reader.NodeType; while (reader.Read()) { switch (reader.NodeType) { case XmlNodeType.Element: prefixStack.Push(reader.LocalName); ProcessAttributes(reader, prefixStack, data, AddNamePrefix); ProcessAttributes(reader, prefixStack, data, AddAttributePair); // If current element is self-closing if (reader.IsEmptyElement) { prefixStack.Pop(); } break; case XmlNodeType.EndElement: if (prefixStack.Any()) { // If this EndElement node comes right after an Element node, // it means there is no text/CDATA node in current element if (preNodeType == XmlNodeType.Element) { var key = ConfigurationPath.Combine(prefixStack.Reverse()); data[key] = string.Empty; } prefixStack.Pop(); } break; case XmlNodeType.CDATA: case XmlNodeType.Text: { var key = ConfigurationPath.Combine(prefixStack.Reverse()); if (data.ContainsKey(key)) { throw new FormatException($"A duplicate key '{key}' was found.{GetLineInfo(reader)}"); } data[key] = reader.Value; break; } case XmlNodeType.XmlDeclaration: case XmlNodeType.ProcessingInstruction: case XmlNodeType.Comment: case XmlNodeType.Whitespace: // Ignore certain types of nodes break; default: throw new FormatException($"Unsupported node type '{reader.NodeType}' was found.{GetLineInfo(reader)}"); } preNodeType = reader.NodeType; // If this element is a self-closing element, // we pretend that we just processed an EndElement node // because a self-closing element contains an end within itself if (preNodeType == XmlNodeType.Element && reader.IsEmptyElement) { preNodeType = XmlNodeType.EndElement; } } } return(data); }
private void EnterContext(string context) { _context.Push(context); _currentPath = ConfigurationPath.Combine(_context.Reverse()); }