AngleSharp by Florian Rappl

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

.NET API 1,172,480 bytes

 Node

Represents a node in the generated tree.
using AngleSharp.Dom.Collections; using AngleSharp.Extensions; using AngleSharp.Html; using AngleSharp.Linq; using System; using System.Diagnostics; using System.Text; namespace AngleSharp.Dom { [DebuggerStepThrough] internal class Node : EventTarget, INode, IEventTarget, IEquatable<INode> { private readonly NodeType _type; private readonly string _name; private readonly NodeFlags _flags; private Document _owner; private Url _baseUri; private Node _parent; private NodeList _children; private TextRange _range; public TextRange OriginalPosition { get { return _range; } internal set { _range = value; } } public bool HasChildNodes => _children.Length != 0; public string BaseUri { get { Url baseUrl = BaseUrl; if (baseUrl != null) return baseUrl.Href; return string.Empty; } } public Url BaseUrl { get { if (_baseUri != null) return _baseUri; if (_parent != null) return _parent.BaseUrl; if (_owner != null) return _owner._baseUri ?? _owner.DocumentUrl; if (_type == NodeType.Document) return ((Document)this).DocumentUrl; return null; } set { _baseUri = value; } } public NodeType NodeType => _type; public virtual string NodeValue { get { return null; } set { } } public virtual string TextContent { get { return null; } set { } } INode INode.PreviousSibling { get { return PreviousSibling; } } INode INode.NextSibling { get { return NextSibling; } } INode INode.FirstChild { get { return FirstChild; } } INode INode.LastChild { get { return LastChild; } } IDocument INode.Owner { get { return Owner; } } INode INode.Parent { get { return _parent; } } public IElement ParentElement => _parent as IElement; INodeList INode.ChildNodes { get { return _children; } } public string NodeName => _name; internal Node PreviousSibling { get { if (_parent == null) return null; int length = _parent._children.Length; for (int i = 1; i < length; i++) { if (_parent._children[i] == this) return _parent._children[i - 1]; } return null; } } internal Node NextSibling { get { if (_parent == null) return null; int num = _parent._children.Length - 1; for (int i = 0; i < num; i++) { if (_parent._children[i] == this) return _parent._children[i + 1]; } return null; } } internal Node FirstChild { get { if (_children.Length <= 0) return null; return _children[0]; } } internal Node LastChild { get { if (_children.Length <= 0) return null; return _children[_children.Length - 1]; } } internal NodeFlags Flags => _flags; internal NodeList ChildNodes { get { return _children; } set { _children = value; } } internal Node Parent { get { return _parent; } set { _parent = value; } } internal Document Owner { get { if (_type == NodeType.Document) return null; return _owner; } set { if (_owner != value) { Document owner = _owner; _owner = value; for (int i = 0; i < _children.Length; i++) { _children[i].Owner = value; } if (owner != null) NodeIsAdopted(owner); } } } internal Node(Document owner, string name, NodeType type = NodeType.Element, NodeFlags flags = NodeFlags.None) { _owner = owner; _name = (name ?? string.Empty); _type = type; _children = new NodeList(); _flags = flags; } internal void AppendText(string s) { TextNode textNode = LastChild as TextNode; if (textNode == null) AddNode(new TextNode(Owner, s)); else textNode.Append(s); } internal void InsertText(int index, string s) { if (index > 0 && index <= _children.Length && _children[index - 1].NodeType == NodeType.Text) ((IText)_children[index - 1]).Append(s); else if (index >= 0 && index < _children.Length && _children[index].NodeType == NodeType.Text) { ((IText)_children[index]).Insert(0, s); } else { InsertNode(index, new TextNode(Owner, s)); } } public INode AppendChild(INode child) { return this.PreInsert(child, null); } public INode InsertChild(int index, INode child) { return this.PreInsert(child, _children[index]); } public INode InsertBefore(INode newElement, INode referenceElement) { return this.PreInsert(newElement, referenceElement); } public INode ReplaceChild(INode newChild, INode oldChild) { return ReplaceChild(newChild as Node, oldChild as Node, false); } public INode RemoveChild(INode child) { return this.PreRemove(child); } public virtual INode Clone(bool deep = true) { Node node = new Node(_owner, _name, _type, _flags); CopyProperties(this, node, deep); return node; } public DocumentPositions CompareDocumentPosition(INode otherNode) { if (this == otherNode) return DocumentPositions.Same; if (_owner != otherNode.Owner) return (DocumentPositions)(33 | ((otherNode.GetHashCode() > GetHashCode()) ? 4 : 2)); if (otherNode.IsAncestorOf(this)) return DocumentPositions.Preceding | DocumentPositions.Contains; if (otherNode.IsDescendantOf(this)) return DocumentPositions.Following | DocumentPositions.ContainedBy; if (otherNode.IsPreceding(this)) return DocumentPositions.Preceding; return DocumentPositions.Following; } public bool Contains(INode otherNode) { return this.IsInclusiveAncestorOf(otherNode); } public void Normalize() { for (int i = 0; i < _children.Length; i++) { TextNode text = _children[i] as TextNode; if (text != null) { int length = text.Length; if (length == 0) { RemoveChild(text, false); i--; } else { StringBuilder stringBuilder = Pool.NewStringBuilder(); TextNode sibling = text; int end = i; <>c__DisplayClass2 <>c__DisplayClass; while ((sibling = (sibling.NextSibling as TextNode)) != null) { stringBuilder.Append(sibling.Data); end++; Document owner = _owner; Predicate<AngleSharp.Dom.Collections.Range> condition = (AngleSharp.Dom.Collections.Range m) => m.Head == sibling; object action = <>c__DisplayClass.CS$<>9__CachedAnonymousMethodDelegate5; if (action == null) { Action<AngleSharp.Dom.Collections.Range> action2; action = (action2 = delegate(AngleSharp.Dom.Collections.Range m) { m.StartWith(text, length); }); } owner.ForEachRange(condition, (Action<AngleSharp.Dom.Collections.Range>)action); Document owner2 = _owner; Predicate<AngleSharp.Dom.Collections.Range> condition2 = (AngleSharp.Dom.Collections.Range m) => m.Tail == sibling; object action3 = <>c__DisplayClass.CS$<>9__CachedAnonymousMethodDelegate8; if (action3 == null) { Action<AngleSharp.Dom.Collections.Range> action4; action3 = (action4 = delegate(AngleSharp.Dom.Collections.Range m) { m.EndWith(text, length); }); } owner2.ForEachRange(condition2, (Action<AngleSharp.Dom.Collections.Range>)action3); Document owner3 = _owner; Predicate<AngleSharp.Dom.Collections.Range> condition3 = delegate(AngleSharp.Dom.Collections.Range m) { if (m.Head == sibling.Parent) return m.Start == end; return false; }; object action5 = <>c__DisplayClass.CS$<>9__CachedAnonymousMethodDelegate11; if (action5 == null) { Action<AngleSharp.Dom.Collections.Range> action6; action5 = (action6 = delegate(AngleSharp.Dom.Collections.Range m) { m.StartWith(text, length); }); } owner3.ForEachRange(condition3, (Action<AngleSharp.Dom.Collections.Range>)action5); Document owner4 = _owner; Predicate<AngleSharp.Dom.Collections.Range> condition4 = delegate(AngleSharp.Dom.Collections.Range m) { if (m.Tail == sibling.Parent) return m.End == end; return false; }; object action7 = <>c__DisplayClass.CS$<>9__CachedAnonymousMethodDelegate14; if (action7 == null) { Action<AngleSharp.Dom.Collections.Range> action8; action7 = (action8 = delegate(AngleSharp.Dom.Collections.Range m) { m.EndWith(text, length); }); } owner4.ForEachRange(condition4, (Action<AngleSharp.Dom.Collections.Range>)action7); length += sibling.Length; } text.Replace(text.Length, 0, stringBuilder.ToPool()); for (int num = end; num > i; num--) { RemoveChild(_children[num], false); } } } else if (_children[i].HasChildNodes) { _children[i].Normalize(); } } } public string LookupNamespaceUri(string prefix) { if (string.IsNullOrEmpty(prefix)) prefix = null; return LocateNamespace(prefix); } public string LookupPrefix(string namespaceUri) { if (string.IsNullOrEmpty(namespaceUri)) return null; return LocatePrefix(namespaceUri); } public bool IsDefaultNamespace(string namespaceUri) { if (string.IsNullOrEmpty(namespaceUri)) namespaceUri = null; return LocateNamespace(null) == namespaceUri; } public virtual bool Equals(INode otherNode) { if (BaseUri != otherNode.BaseUri || NodeName != otherNode.NodeName || ChildNodes.Length != otherNode.ChildNodes.Length) return false; for (int i = 0; i < _children.Length; i++) { if (!_children[i].Equals(otherNode.ChildNodes[i])) return false; } return true; } protected virtual string LocateNamespace(string prefix) { if (_parent != null) return _parent.LocateNamespace(prefix); return null; } protected virtual string LocatePrefix(string namespaceUri) { if (_parent != null) return _parent.LocatePrefix(namespaceUri); return null; } internal void ChangeOwner(Document document) { Document owner = _owner; if (_parent != null) _parent.RemoveChild(this, false); Owner = document; NodeIsAdopted(owner); } internal void InsertNode(int index, Node node) { node.Parent = this; _children.Insert(index, node); } internal void AddNode(Node node) { node.Parent = this; _children.Add(node); } internal void RemoveNode(int index, Node node) { node.Parent = null; _children.RemoveAt(index); } internal void ReplaceAll(Node node, bool suppressObservers) { if (node != null) _owner.AdoptNode(node); NodeList nodeList = new NodeList(_children); NodeList nodeList2 = new NodeList(); if (node != null) { if (node.NodeType == NodeType.DocumentFragment) nodeList2.AddRange(node._children); else nodeList2.Add(node); } for (int i = 0; i < nodeList.Length; i++) { RemoveChild(nodeList[i], true); } for (int j = 0; j < nodeList2.Length; j++) { InsertBefore(nodeList2[j], null, true); } if (!suppressObservers) _owner.QueueMutation(MutationRecord.ChildList(this, nodeList2, nodeList, null, null)); } internal INode InsertBefore(Node newElement, Node referenceElement, bool suppressObservers) { int count = (newElement.NodeType != NodeType.DocumentFragment) ? 1 : newElement.ChildNodes.Length; if (referenceElement != null) { int childIndex = referenceElement.Index(); _owner.ForEachRange(delegate(AngleSharp.Dom.Collections.Range m) { if (m.Head == this) return m.Start > childIndex; return false; }, delegate(AngleSharp.Dom.Collections.Range m) { m.StartWith(this, m.Start + count); }); _owner.ForEachRange(delegate(AngleSharp.Dom.Collections.Range m) { if (m.Tail == this) return m.End > childIndex; return false; }, delegate(AngleSharp.Dom.Collections.Range m) { m.EndWith(this, m.End + count); }); } if (newElement.NodeType == NodeType.Document || newElement.Contains(this)) throw new DomException(ErrorCode.HierarchyRequest); NodeList nodeList = new NodeList(); int num = _children.Index(referenceElement); if (num == -1) num = _children.Length; if (newElement._type == NodeType.DocumentFragment) { int num2 = num; int i = num; while (newElement.HasChildNodes) { Node node = newElement.ChildNodes[0]; newElement.RemoveChild(node, true); InsertNode(num2, node); AddNode(node); num2++; } for (; i < num2; i++) { Node node2 = _children[i]; nodeList.Add(node2); NodeIsInserted(node2); } } else { nodeList.Add(newElement); InsertNode(num, newElement); NodeIsInserted(newElement); } if (!suppressObservers) _owner.QueueMutation(MutationRecord.ChildList(this, nodeList, null, _children[num - 1], referenceElement)); return newElement; } internal void RemoveChild(Node node, bool suppressObservers) { int index = _children.Index(node); _owner.ForEachRange((AngleSharp.Dom.Collections.Range m) => m.Head.IsInclusiveDescendantOf(node), delegate(AngleSharp.Dom.Collections.Range m) { m.StartWith(this, index); }); _owner.ForEachRange((AngleSharp.Dom.Collections.Range m) => m.Tail.IsInclusiveDescendantOf(node), delegate(AngleSharp.Dom.Collections.Range m) { m.EndWith(this, index); }); _owner.ForEachRange(delegate(AngleSharp.Dom.Collections.Range m) { if (m.Head == this) return m.Start > index; return false; }, delegate(AngleSharp.Dom.Collections.Range m) { m.StartWith(this, m.Start - 1); }); _owner.ForEachRange(delegate(AngleSharp.Dom.Collections.Range m) { if (m.Tail == this) return m.End > index; return false; }, delegate(AngleSharp.Dom.Collections.Range m) { m.EndWith(this, m.End - 1); }); Node node2 = (index > 0) ? _children[index - 1] : null; if (!suppressObservers) { NodeList nodeList = new NodeList(); nodeList.Add(node); _owner.QueueMutation(MutationRecord.ChildList(this, null, nodeList, node2, node.NextSibling)); _owner.AddTransientObserver(node); } RemoveNode(index, node); NodeIsRemoved(node, node2); } internal INode ReplaceChild(Node node, Node child, bool suppressObservers) { if (_type != NodeType.Document && _type != NodeType.DocumentFragment && _type != NodeType.Element) throw new DomException(ErrorCode.HierarchyRequest); if (node.IsHostIncludingInclusiveAncestor(this)) throw new DomException(ErrorCode.HierarchyRequest); if (child.Parent != this) throw new DomException(ErrorCode.NotFound); NodeType nodeType = node.NodeType; if (nodeType == NodeType.Element || nodeType == NodeType.Comment || nodeType == NodeType.Text || nodeType == NodeType.ProcessingInstruction || nodeType == NodeType.DocumentFragment || nodeType == NodeType.DocumentType) { IDocument document = _parent as IDocument; if (document != null) { bool flag = false; switch (node._type) { case NodeType.DocumentType: flag = (document.Doctype != child || child.IsPrecededByElement()); break; case NodeType.Element: flag = (document.DocumentElement != child || child.IsFollowedByDoctype()); break; case NodeType.DocumentFragment: { int elementCount = node.GetElementCount(); flag = (elementCount > 1 || node.HasTextNodes() || (elementCount == 1 && (document.DocumentElement != child || child.IsFollowedByDoctype()))); break; } } if (flag) throw new DomException(ErrorCode.HierarchyRequest); } Node nextSibling = child.NextSibling; if (nextSibling == node) nextSibling = node.NextSibling; _owner.AdoptNode(node); RemoveChild(child, true); InsertBefore(node, nextSibling, true); NodeList nodeList = new NodeList(); NodeList nodeList2 = new NodeList(); nodeList2.Add(child); if (node._type == NodeType.DocumentFragment) nodeList.AddRange(node._children); else nodeList.Add(node); if (!suppressObservers) _owner.QueueMutation(MutationRecord.ChildList(this, nodeList, nodeList2, child.PreviousSibling, nextSibling)); return child; } throw new DomException(ErrorCode.HierarchyRequest); } internal virtual void NodeIsAdopted(Document oldDocument) { } internal virtual void NodeIsInserted(Node newNode) { } internal virtual void NodeIsRemoved(Node removedNode, Node oldPreviousSibling) { } protected static void CopyProperties(Node source, Node target, bool deep) { target._baseUri = source._baseUri; if (deep) { foreach (INode child in source._children) { target.AddNode((Node)child.Clone(true)); } } } public virtual string ToHtml() { return TextContent; } } }