AngleSharp by Florian Rappl

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

.NET API 1,176,064 bytes

 Element

Represents an element node.
using AngleSharp.Dom.Collections; using AngleSharp.Dom.Css; using AngleSharp.Dom.Events; using AngleSharp.Extensions; using AngleSharp.Html; using AngleSharp.Parser.Css; using AngleSharp.Services.Styling; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; namespace AngleSharp.Dom { [DebuggerStepThrough] internal class Element : Node, IElement, INode, IEventTarget, IMarkupFormattable, IParentNode, IChildNode, INonDocumentTypeChildNode { protected sealed class BoundLocation : ILocation, IUrlUtilities { private readonly Element _parent; private readonly string _attributeName; private Location _location; private Url _baseUrl; private string _value; public Location Location { get { string text = _parent.GetOwnAttribute(_attributeName) ?? string.Empty; Url baseUrl = _parent.BaseUrl; if (_location == null || !baseUrl.Equals(_baseUrl) || !text.Equals(_value, StringComparison.Ordinal)) { Url url = new Url(baseUrl, text); _baseUrl = baseUrl; _value = text; _location = new Location(url); } return _location; } } public string Href { get { return Location.Href; } set { Assign(value); } } public string Protocol { get { return Location.Protocol; } set { Location.Protocol = value; Reload(); } } public string Host { get { return Location.Host; } set { Location.Host = value; Reload(); } } public string HostName { get { return Location.HostName; } set { Location.HostName = value; Reload(); } } public string Port { get { return Location.Port; } set { Location.Port = value; Reload(); } } public string PathName { get { return Location.PathName; } set { Location.PathName = value; Reload(); } } public string Search { get { return Location.Search; } set { Location.Search = value; Reload(); } } public string Hash { get { return Location.Hash; } set { Location.Hash = value; Reload(); } } public string UserName { get { return Location.UserName; } set { Location.UserName = value; Reload(); } } public string Password { get { return Location.Password; } set { Location.Password = value; Reload(); } } public string Origin => Location.Origin; public BoundLocation(Element parent, string attributeName) { _parent = parent; _attributeName = attributeName; } public void Assign(string url) { _parent.SetOwnAttribute(_attributeName, url); _location = Location; } public void Replace(string url) { Assign(url); } public void Reload() { Assign(Href); } } private readonly List<IAttr> _attributes; private readonly Dictionary<string, Action<string>> _attributeHandlers; private readonly string _namespace; private readonly string _prefix; private readonly string _localName; private HtmlElementCollection _elements; private TokenList _classList; public string Prefix => _prefix; public string LocalName => _localName; public string NamespaceUri => _namespace; public override string TextContent { get { StringBuilder stringBuilder = Pool.NewStringBuilder(); foreach (IText item in this.GetDescendants().OfType<IText>()) { stringBuilder.Append(item.Data); } return stringBuilder.ToPool(); } set { TextNode node = (!string.IsNullOrEmpty(value)) ? new TextNode(base.Owner, value) : null; ReplaceAll(node, false); } } public ITokenList ClassList { get { if (_classList == null) { _classList = new TokenList(GetOwnAttribute(AttributeNames.Class)); CreateBindings(_classList, AttributeNames.Class); } return _classList; } } public string ClassName { get { return GetOwnAttribute(AttributeNames.Class); } set { SetOwnAttribute(AttributeNames.Class, value); } } public string Id { get { return GetOwnAttribute(AttributeNames.Id); } set { SetOwnAttribute(AttributeNames.Id, value); } } public string TagName => base.NodeName; public IElement PreviousElementSibling { get { Node parent = base.Parent; if (parent != null) { bool flag = false; for (int num = parent.ChildNodes.Length - 1; num >= 0; num--) { if (parent.ChildNodes[num] == this) flag = true; else if (flag && parent.ChildNodes[num] is IElement) { return (IElement)parent.ChildNodes[num]; } } } return null; } } public IElement NextElementSibling { get { Node parent = base.Parent; if (parent != null) { int length = parent.ChildNodes.Length; bool flag = false; for (int i = 0; i < length; i++) { if (parent.ChildNodes[i] == this) flag = true; else if (flag && parent.ChildNodes[i] is IElement) { return (IElement)parent.ChildNodes[i]; } } } return null; } } public int ChildElementCount { get { NodeList childNodes = base.ChildNodes; int length = childNodes.Length; int num = 0; for (int i = 0; i < length; i++) { if (childNodes[i].NodeType == NodeType.Element) num++; } return num; } } public IHtmlCollection<IElement> Children => _elements ?? (_elements = new HtmlElementCollection(this, false, null)); public IElement FirstElementChild { get { NodeList childNodes = base.ChildNodes; int length = childNodes.Length; for (int i = 0; i < length; i++) { IElement element = childNodes[i] as IElement; if (element != null) return element; } return null; } } public IElement LastElementChild { get { NodeList childNodes = base.ChildNodes; for (int num = childNodes.Length - 1; num >= 0; num--) { IElement element = childNodes[num] as IElement; if (element != null) return element; } return null; } } public string InnerHtml { get { return base.ChildNodes.ToHtml(HtmlMarkupFormatter.Instance); } set { ReplaceAll(new DocumentFragment(this, value), false); } } public string OuterHtml { get { return ToHtml(HtmlMarkupFormatter.Instance); } set { Node parent = base.Parent; if (parent != null) { if (base.Owner != null && base.Owner.DocumentElement == this) throw new DomException(DomError.NoModificationAllowed); parent.InsertChild(parent.IndexOf(this), new DocumentFragment(this, value)); parent.RemoveChild(this); return; } throw new DomException(DomError.NotSupported); } } IEnumerable<IAttr> IElement.Attributes { get { return _attributes; } } internal List<IAttr> Attributes => _attributes; public bool IsFocused { get { Document owner = base.Owner; if (owner == null) return false; return owner.FocusElement == this; } protected set { Document owner = base.Owner; if (owner != null) { if (value) { owner.SetFocus(this); this.Fire(delegate(FocusEvent m) { m.Init(EventNames.Focus, false, false); }, null); } else { owner.SetFocus(null); this.Fire(delegate(FocusEvent m) { m.Init(EventNames.Blur, false, false); }, null); } } } } public Element(Document owner, string name, NodeFlags flags = NodeFlags.None) : this(owner, name, null, null, flags) { } public Element(Document owner, string localName, string prefix, string namespaceUri, NodeFlags flags = NodeFlags.None) : this(owner, (prefix != null) ? (prefix + ":" + localName) : localName, localName, prefix, namespaceUri, flags) { } public Element(Document owner, string name, string localName, string prefix, string namespaceUri, NodeFlags flags = NodeFlags.None) : base(owner, name, NodeType.Element, flags) { _localName = localName; _prefix = prefix; _namespace = namespaceUri; _attributes = new List<IAttr>(); _attributeHandlers = new Dictionary<string, Action<string>>(); } public IElement QuerySelector(string selectors) { return base.ChildNodes.QuerySelector(selectors); } public IHtmlCollection<IElement> QuerySelectorAll(string selectors) { return base.ChildNodes.QuerySelectorAll(selectors); } public IHtmlCollection<IElement> GetElementsByClassName(string classNames) { return base.ChildNodes.GetElementsByClassName(classNames); } public IHtmlCollection<IElement> GetElementsByTagName(string tagName) { return base.ChildNodes.GetElementsByTagName(tagName); } public IHtmlCollection<IElement> GetElementsByTagNameNS(string namespaceURI, string tagName) { return base.ChildNodes.GetElementsByTagName(namespaceURI, tagName); } public bool Matches(string selectors) { return CssParser.Default.ParseSelector(selectors).Match(this); } public override INode Clone(bool deep = true) { Element element = new Element(base.Owner, LocalName, _prefix, _namespace, base.Flags); Node.CopyProperties(this, element, deep); CopyAttributes(this, element); return element; } public IPseudoElement Pseudo(string pseudoElement) { return PseudoElement.Create(this, pseudoElement); } public bool HasAttribute(string name) { if (_namespace == Namespaces.HtmlUri) name = name.ToLowerInvariant(); return _attributes.Has(name); } public bool HasAttribute(string namespaceUri, string localName) { if (string.IsNullOrEmpty(namespaceUri)) namespaceUri = null; return _attributes.Has(namespaceUri, localName); } public string GetAttribute(string name) { if (_namespace == Namespaces.HtmlUri) name = name.ToLower(); return _attributes.Get(name)?.Value; } protected string GetOwnAttribute(string name) { return _attributes.Get(null, name)?.Value; } public string GetAttribute(string namespaceUri, string localName) { if (string.IsNullOrEmpty(namespaceUri)) namespaceUri = null; return _attributes.Get(namespaceUri, localName)?.Value; } public void SetAttribute(string name, string value) { if (value != null) { if (!name.IsXmlName()) throw new DomException(DomError.InvalidCharacter); if (_namespace == Namespaces.HtmlUri) name = name.ToLowerInvariant(); for (int i = 0; i < _attributes.Count; i++) { if (_attributes[i].Prefix == null && _attributes[i].LocalName == name) { _attributes[i].Value = value; return; } } _attributes.Add(new Attr(this, name, value)); AttributeChanged(name, null, null, false); } else RemoveAttribute(name); } protected void SetOwnAttribute(string name, string value) { for (int i = 0; i < _attributes.Count; i++) { if (_attributes[i].LocalName == name && _attributes[i].NamespaceUri == null) { _attributes[i].Value = value; return; } } _attributes.Add(new Attr(this, null, name, value, null)); AttributeChanged(name, null, null, false); } public void SetAttribute(string namespaceUri, string name, string value) { if (value != null) { if (string.IsNullOrEmpty(namespaceUri)) namespaceUri = null; if (!name.IsXmlName()) throw new DomException(DomError.InvalidCharacter); if (!name.IsQualifiedName()) throw new DomException(DomError.Namespace); int num = name.IndexOf(':'); string text = (num >= 0) ? name.Substring(0, num) : null; string text2 = (num >= 0) ? name.Substring(num + 1) : name; if (text != null && namespaceUri == null) throw new DomException(DomError.Namespace); if (text == Namespaces.XmlPrefix && namespaceUri != Namespaces.XmlUri) throw new DomException(DomError.Namespace); if ((name == Namespaces.XmlNsPrefix || text == Namespaces.XmlNsPrefix) && namespaceUri != Namespaces.XmlNsUri) throw new DomException(DomError.Namespace); if (namespaceUri == Namespaces.XmlNsUri && name != Namespaces.XmlNsPrefix && text != Namespaces.XmlNsPrefix) throw new DomException(DomError.Namespace); for (int i = 0; i < _attributes.Count; i++) { if (_attributes[i].LocalName == text2 && _attributes[i].NamespaceUri == namespaceUri) { _attributes[i].Value = value; return; } } _attributes.Add(new Attr(this, text, text2, value, namespaceUri)); AttributeChanged(text2, namespaceUri, null, false); } else RemoveAttribute(namespaceUri, name); } public void RemoveAttribute(string name) { if (_namespace == Namespaces.HtmlUri) name = name.ToLower(); int num = 0; while (true) { if (num >= _attributes.Count) return; if (_attributes[num].Prefix == null && _attributes[num].LocalName == name) break; num++; } IAttr attr = _attributes[num]; _attributes.RemoveAt(num); AttributeChanged(attr.LocalName, attr.NamespaceUri, attr.Value, false); } public void RemoveAttribute(string namespaceUri, string localName) { if (string.IsNullOrEmpty(namespaceUri)) namespaceUri = null; int num = 0; while (true) { if (num >= _attributes.Count) return; if (_attributes[num].LocalName == localName && _attributes[num].NamespaceUri == namespaceUri) break; num++; } IAttr attr = _attributes[num]; _attributes.RemoveAt(num); AttributeChanged(attr.LocalName, attr.NamespaceUri, attr.Value, false); } public void Prepend(params INode[] nodes) { this.PrependNodes(nodes); } public void Append(params INode[] nodes) { this.AppendNodes(nodes); } public override bool Equals(INode otherNode) { IElement element = otherNode as IElement; if (element != null) { if (NamespaceUri != element.NamespaceUri) return false; if (_attributes.Count != element.Attributes.Count()) return false; int i; for (i = 0; i < _attributes.Count; i++) { if (!element.Attributes.Any(delegate(IAttr m) { if (m.Name == _attributes[i].Name) return m.Value == _attributes[i].Value; return false; })) return false; } return base.Equals(otherNode); } return false; } public void Before(params INode[] nodes) { this.InsertBefore(nodes); } public void After(params INode[] nodes) { this.InsertAfter(nodes); } public void Replace(params INode[] nodes) { this.ReplaceWith(nodes); } public void Remove() { this.RemoveFromParent(); } public void Insert(AdjacentPosition position, string html) { Element context = (position == AdjacentPosition.BeforeBegin || position == AdjacentPosition.AfterEnd) ? this : (base.Parent as Element); DocumentFragment documentFragment = new DocumentFragment(context, html); switch (position) { case AdjacentPosition.BeforeBegin: base.Parent.InsertBefore(documentFragment, this); break; case AdjacentPosition.AfterEnd: base.Parent.InsertChild(base.Parent.IndexOf(this) + 1, documentFragment); break; case AdjacentPosition.AfterBegin: InsertChild(0, documentFragment); break; case AdjacentPosition.BeforeEnd: AppendChild(documentFragment); break; } } public override string ToHtml(IMarkupFormatter formatter) { bool flag = base.Flags.HasFlag(NodeFlags.SelfClosing); string str = formatter.OpenTag(this, flag); string str2 = string.Empty; if (!flag) { StringBuilder stringBuilder = Pool.NewStringBuilder(); if (base.Flags.HasFlag(NodeFlags.LineTolerance) && base.FirstChild is IText) { IText text = (IText)base.FirstChild; if (text.Data.Length > 0 && text.Data[0] == '\n') stringBuilder.Append('\n'); } foreach (INode childNode in base.ChildNodes) { stringBuilder.Append(childNode.ToHtml(formatter)); } str2 = stringBuilder.ToPool(); } string str3 = formatter.CloseTag(this, flag); return str + str2 + str3; } protected ICssStyleDeclaration CreateStyle() { IConfiguration options = base.Owner.Options; ICssStyleEngine cssStyleEngine = options.GetCssStyleEngine(); if (cssStyleEngine != null) { string ownAttribute = GetOwnAttribute(AttributeNames.Style); StyleOptions styleOptions = new StyleOptions(); styleOptions.Element = this; styleOptions.Configuration = options; StyleOptions options2 = styleOptions; ICssStyleDeclaration cssStyleDeclaration = cssStyleEngine.ParseInline(ownAttribute, options2); IBindable bindable = cssStyleDeclaration as IBindable; if (bindable != null) bindable.Changed += delegate(string value) { UpdateAttribute(AttributeNames.Style, value); }; return cssStyleDeclaration; } return null; } protected void CreateBindings(IBindable bindable, string attributeName) { bindable.Changed += delegate(string value) { UpdateAttribute(attributeName, value); }; RegisterAttributeObserver(attributeName, delegate(string value) { bindable.Update(value); }); } protected void UpdateAttribute(string name, string value) { Action<string> value2 = null; if (_attributeHandlers.TryGetValue(name, out value2)) _attributeHandlers.Remove(name); SetOwnAttribute(name, value); if (value2 != null) _attributeHandlers.Add(name, value2); } internal void AttributeChanged(string localName, string namespaceUri, string oldValue, bool suppressMutationObservers = false) { Action<string> value = null; if (namespaceUri == null && _attributeHandlers.TryGetValue(localName, out value)) { IAttr attr = _attributes.Get(null, localName); value(attr?.Value); } if (!suppressMutationObservers) base.Owner.QueueMutation(MutationRecord.Attributes(this, localName, namespaceUri, oldValue)); } protected sealed override string LocateNamespace(string prefix) { return ElementExtensions.LocateNamespace(this, prefix); } protected sealed override string LocatePrefix(string namespaceUri) { return ElementExtensions.LocatePrefix(this, namespaceUri); } protected static void CopyAttributes(Element source, Element target) { for (int i = 0; i < source._attributes.Count; i++) { target._attributes.Add(new Attr(target, source._attributes[i].Name, source._attributes[i].Value)); } } protected void RegisterAttributeObserver(string name, Action<string> callback) { Action<string> value = null; value = ((!_attributeHandlers.TryGetValue(name, out value)) ? callback : ((Action<string>)Delegate.Combine(value, callback))); _attributeHandlers[name] = value; } } }