AngleSharp by Florian Rappl

<PackageReference Include="AngleSharp" Version="0.8.1" />

 StringMap

sealed class StringMap : IStringMap, IEnumerable<KeyValuePair<string, string>>, IEnumerable
Represents a list of DOMTokens.
using AngleSharp.Extensions; using AngleSharp.Html; using System; using System.Collections; using System.Collections.Generic; namespace AngleSharp.Dom.Collections { internal sealed class StringMap : IStringMap, IEnumerable<KeyValuePair<string, string>>, IEnumerable { private readonly string _prefix; private readonly Element _parent; public string this[string name] { get { return _parent.GetAttribute(_prefix + Check(name)); } set { _parent.SetAttribute(_prefix + Check(name), value); } } internal StringMap(string prefix, Element parent) { _prefix = prefix; _parent = parent; } public void Remove(string name) { if (Contains(name)) this[name] = null; } public bool Contains(string name) { return _parent.HasAttribute(_prefix + Check(name)); } private string Check(string name) { if (name.StartsWith(Tags.Xml, StringComparison.OrdinalIgnoreCase)) throw new DomException(ErrorCode.Syntax); if (name.IndexOf(';') >= 0) throw new DomException(ErrorCode.Syntax); for (int i = 0; i < name.Length; i++) { if (name[i].IsUppercaseAscii()) throw new DomException(ErrorCode.Syntax); } return name; } public IEnumerator<KeyValuePair<string, string>> GetEnumerator() { List<IAttr>.Enumerator enumerator = _parent.Attributes.GetEnumerator(); try { while (enumerator.MoveNext()) { IAttr current = enumerator.Current; if (current.Name.StartsWith(_prefix, StringComparison.OrdinalIgnoreCase)) yield return new KeyValuePair<string, string>(current.Name.Remove(0, _prefix.Length), current.Value); } } finally { ((IDisposable)enumerator).Dispose(); } enumerator = default(List<IAttr>.Enumerator); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } }