Element
public abstract class Element : Node, IElement, INode, IEventTarget, IMarkupFormattable, IParentNode, IChildNode, INonDocumentTypeChildNode
Represents an element node.
using AngleSharp.Css.Dom;
using AngleSharp.Css.Parser;
using AngleSharp.Dom.Events;
using AngleSharp.Html.Dom;
using AngleSharp.Text;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
namespace AngleSharp.Dom
{
[System.Runtime.CompilerServices.NullableContext(1)]
[System.Runtime.CompilerServices.Nullable(0)]
public abstract class Element : Node, IElement, INode, IEventTarget, IMarkupFormattable, IParentNode, IChildNode, INonDocumentTypeChildNode
{
private readonly NamedNodeMap _attributes;
private readonly string _namespace;
[System.Runtime.CompilerServices.Nullable(2)]
private readonly string _prefix;
private readonly string _localName;
[System.Runtime.CompilerServices.Nullable(new byte[] {
2,
1
})]
private HtmlCollection<IElement> _elements;
[System.Runtime.CompilerServices.Nullable(2)]
private TokenList _classList;
[System.Runtime.CompilerServices.Nullable(2)]
private IShadowRoot _shadowRoot;
internal IBrowsingContext Context => base.Owner?.Context;
internal NamedNodeMap Attributes => _attributes;
[System.Runtime.CompilerServices.Nullable(2)]
public IElement AssignedSlot {
[System.Runtime.CompilerServices.NullableContext(2)]
get {
return base.ParentElement?.ShadowRoot?.GetAssignedSlot(Slot);
}
}
[System.Runtime.CompilerServices.Nullable(2)]
public string Slot {
[System.Runtime.CompilerServices.NullableContext(2)]
get {
return this.GetOwnAttribute(AttributeNames.Slot);
}
[System.Runtime.CompilerServices.NullableContext(2)]
set {
this.SetOwnAttribute(AttributeNames.Slot, value, false);
}
}
[System.Runtime.CompilerServices.Nullable(2)]
public IShadowRoot ShadowRoot {
[System.Runtime.CompilerServices.NullableContext(2)]
get {
return _shadowRoot;
}
}
[System.Runtime.CompilerServices.Nullable(2)]
public string Prefix {
[System.Runtime.CompilerServices.NullableContext(2)]
get {
return _prefix;
}
}
public string LocalName => _localName;
[System.Runtime.CompilerServices.Nullable(2)]
public string NamespaceUri {
[System.Runtime.CompilerServices.NullableContext(2)]
get {
return _namespace ?? this.GetNamespaceUri();
}
}
[System.Runtime.CompilerServices.Nullable(2)]
public string GivenNamespaceUri {
[System.Runtime.CompilerServices.NullableContext(2)]
get {
return _namespace;
}
}
public override string TextContent {
get {
StringBuilder stringBuilder = StringBuilderPool.Obtain();
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(this.GetOwnAttribute(AttributeNames.Class));
_classList.Changed += delegate(string value) {
UpdateAttribute(AttributeNames.Class, value);
};
}
return _classList;
}
}
[System.Runtime.CompilerServices.Nullable(2)]
public string ClassName {
[System.Runtime.CompilerServices.NullableContext(2)]
get {
return this.GetOwnAttribute(AttributeNames.Class);
}
[System.Runtime.CompilerServices.NullableContext(2)]
set {
this.SetOwnAttribute(AttributeNames.Class, value, false);
}
}
[System.Runtime.CompilerServices.Nullable(2)]
public string Id {
[System.Runtime.CompilerServices.NullableContext(2)]
get {
return this.GetOwnAttribute(AttributeNames.Id);
}
[System.Runtime.CompilerServices.NullableContext(2)]
set {
this.SetOwnAttribute(AttributeNames.Id, value, false);
}
}
public string TagName => base.NodeName;
[System.Runtime.CompilerServices.Nullable(2)]
[field: System.Runtime.CompilerServices.Nullable(2)]
public ISourceReference SourceReference {
[System.Runtime.CompilerServices.NullableContext(2)]
get;
[System.Runtime.CompilerServices.NullableContext(2)]
set;
}
[System.Runtime.CompilerServices.Nullable(2)]
public IElement PreviousElementSibling {
[System.Runtime.CompilerServices.NullableContext(2)]
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) {
IElement element = parent.ChildNodes[num] as IElement;
if (element != null)
return element;
}
}
}
return null;
}
}
[System.Runtime.CompilerServices.Nullable(2)]
public IElement NextElementSibling {
[System.Runtime.CompilerServices.NullableContext(2)]
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) {
IElement element = parent.ChildNodes[i] as IElement;
if (element != null)
return element;
}
}
}
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 HtmlCollection<IElement>(this, false, null));
[System.Runtime.CompilerServices.Nullable(2)]
public IElement FirstElementChild {
[System.Runtime.CompilerServices.NullableContext(2)]
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;
}
}
[System.Runtime.CompilerServices.Nullable(2)]
public IElement LastElementChild {
[System.Runtime.CompilerServices.NullableContext(2)]
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();
}
set {
ReplaceAll(new DocumentFragment(this, value), false);
}
}
public string OuterHtml {
get {
return this.ToHtml();
}
set {
Node node = base.Parent;
if (node != null) {
switch (node.NodeType) {
case NodeType.Document:
throw new DomException(DomError.NoModificationAllowed);
case NodeType.DocumentFragment:
node = new HtmlBodyElement(base.Owner, null);
break;
}
}
Element obj = node as Element;
if (obj == null)
throw new DomException(DomError.NotSupported);
Element element = obj;
element.InsertChild(element.IndexOf(this), new DocumentFragment(element, value));
element.RemoveChild(this);
}
}
INamedNodeMap IElement.Attributes {
get {
return _attributes;
}
}
public bool IsFocused {
get {
return base.Owner?.FocusElement == this;
}
protected set {
Document document = base.Owner;
document?.QueueTask(delegate {
if (value) {
document.SetFocus(this);
this.Fire(delegate(FocusEvent m) {
m.Init(EventNames.Focus, false, false);
}, null);
} else {
document.SetFocus(null);
this.Fire(delegate(FocusEvent m) {
m.Init(EventNames.Blur, false, false);
}, null);
}
});
}
}
public Element(Document owner, string localName, [System.Runtime.CompilerServices.Nullable(2)] string prefix, [System.Runtime.CompilerServices.Nullable(2)] 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, [System.Runtime.CompilerServices.Nullable(2)] string prefix, string namespaceUri, NodeFlags flags = NodeFlags.None)
: base(owner, name, NodeType.Element, flags)
{
_localName = localName;
_prefix = prefix;
_namespace = namespaceUri;
_attributes = new NamedNodeMap(this);
}
public abstract IElement ParseSubtree(string source);
public IShadowRoot AttachShadow(ShadowRootMode mode = ShadowRootMode.Open)
{
if (TagNames.AllNoShadowRoot.Contains(_localName))
throw new DomException(DomError.NotSupported);
if (ShadowRoot != null)
throw new DomException(DomError.InvalidState);
_shadowRoot = new ShadowRoot(this, mode);
return _shadowRoot;
}
[return: System.Runtime.CompilerServices.Nullable(2)]
public IElement QuerySelector(string selectors)
{
return base.ChildNodes.QuerySelector(selectors, this);
}
public IHtmlCollection<IElement> QuerySelectorAll(string selectors)
{
return base.ChildNodes.QuerySelectorAll(selectors, this);
}
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([System.Runtime.CompilerServices.Nullable(2)] string namespaceURI, string tagName)
{
return base.ChildNodes.GetElementsByTagName(namespaceURI, tagName);
}
public bool Matches(string selectorText)
{
ISelector selector = Context.GetService<ICssSelectorParser>().ParseSelector(selectorText);
if (selector == null)
throw new DomException(DomError.Syntax);
return selector.Match(this, this);
}
[return: System.Runtime.CompilerServices.Nullable(2)]
public IElement Closest(string selectorText)
{
ISelector selector = Context.GetService<ICssSelectorParser>().ParseSelector(selectorText);
if (selector == null)
throw new DomException(DomError.Syntax);
ISelector selector2 = selector;
for (IElement element = this; element != null; element = element.ParentElement) {
if (selector2.Match(element, element))
return element;
}
return null;
}
public bool HasAttribute(string name)
{
if (_namespace.Is(NamespaceNames.HtmlUri))
name = name.HtmlLower();
return _attributes.GetNamedItem(name) != null;
}
public bool HasAttribute([System.Runtime.CompilerServices.Nullable(2)] string namespaceUri, string localName)
{
if (string.IsNullOrEmpty(namespaceUri))
namespaceUri = null;
return _attributes.GetNamedItem(namespaceUri, localName) != null;
}
[return: System.Runtime.CompilerServices.Nullable(2)]
public string GetAttribute(string name)
{
if (_namespace.Is(NamespaceNames.HtmlUri))
name = name.HtmlLower();
return _attributes.GetNamedItem(name)?.Value;
}
[System.Runtime.CompilerServices.NullableContext(2)]
public string GetAttribute(string namespaceUri, [System.Runtime.CompilerServices.Nullable(1)] string localName)
{
if (string.IsNullOrEmpty(namespaceUri))
namespaceUri = null;
return _attributes.GetNamedItem(namespaceUri, localName)?.Value;
}
public void SetAttribute(string name, [System.Runtime.CompilerServices.Nullable(2)] string value)
{
if (value != null) {
if (!name.IsXmlName())
throw new DomException(DomError.InvalidCharacter);
if (_namespace.Is(NamespaceNames.HtmlUri))
name = name.HtmlLower();
this.SetOwnAttribute(name, value, false);
} else
RemoveAttribute(name);
}
[System.Runtime.CompilerServices.NullableContext(2)]
public void SetAttribute(string namespaceUri, [System.Runtime.CompilerServices.Nullable(1)] string name, string value)
{
if (value != null) {
Node.GetPrefixAndLocalName(name, ref namespaceUri, out string prefix, out string localName);
_attributes.SetNamedItem(new Attr(prefix, localName, value, namespaceUri));
} else
RemoveAttribute(namespaceUri, name);
}
public void AddAttribute(Attr attr)
{
attr.Container = _attributes;
_attributes.FastAddItem(attr);
}
public bool RemoveAttribute(string name)
{
if (_namespace.Is(NamespaceNames.HtmlUri))
name = name.HtmlLower();
return _attributes.RemoveNamedItemOrDefault(name) != null;
}
public bool RemoveAttribute([System.Runtime.CompilerServices.Nullable(2)] string namespaceUri, string localName)
{
if (string.IsNullOrEmpty(namespaceUri))
namespaceUri = null;
return _attributes.RemoveNamedItemOrDefault(namespaceUri, localName) != null;
}
public void Prepend(params INode[] nodes)
{
this.PrependNodes(nodes);
}
public void Append(params INode[] nodes)
{
this.AppendNodes(nodes);
}
[System.Runtime.CompilerServices.NullableContext(2)]
public override bool Equals(INode otherNode)
{
IElement element = otherNode as IElement;
if (element != null) {
if (NamespaceUri.Is(element.NamespaceUri) && _attributes.SameAs(element.Attributes))
return base.Equals(otherNode);
return false;
}
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)
{
object obj;
if (position != AdjacentPosition.AfterBegin && position != AdjacentPosition.BeforeEnd) {
obj = (base.Parent as Element);
if (obj == null)
throw new DomException("The element has no parent.");
} else
obj = this;
DocumentFragment documentFragment = new DocumentFragment((Element)obj, 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 Node Clone(Document owner, bool deep)
{
AnyElement anyElement = new AnyElement(owner, LocalName, _prefix, _namespace, base.Flags);
CloneElement(anyElement, owner, deep);
return anyElement;
}
internal virtual void SetupElement()
{
NamedNodeMap attributes = _attributes;
if (attributes.Length > 0) {
IEnumerable<IAttributeObserver> services = Context.GetServices<IAttributeObserver>();
foreach (IAttr item in attributes) {
string localName = item.LocalName;
string value = item.Value;
foreach (IAttributeObserver item2 in services) {
item2.NotifyChange(this, localName, value);
}
}
}
}
[System.Runtime.CompilerServices.NullableContext(2)]
internal void AttributeChanged([System.Runtime.CompilerServices.Nullable(1)] string localName, string namespaceUri, string oldValue, string newValue)
{
if (namespaceUri == null) {
foreach (IAttributeObserver service in Context.GetServices<IAttributeObserver>()) {
service.NotifyChange(this, localName, newValue);
}
}
base.Owner.QueueMutation(MutationRecord.Attributes(this, localName, namespaceUri, oldValue));
}
internal void UpdateClassList(string value)
{
_classList?.Update(value);
}
protected void UpdateAttribute(string name, string value)
{
this.SetOwnAttribute(name, value, true);
}
[return: System.Runtime.CompilerServices.Nullable(2)]
protected sealed override string LocateNamespace(string prefix)
{
return this.LocateNamespaceFor(prefix);
}
[return: System.Runtime.CompilerServices.Nullable(2)]
protected sealed override string LocatePrefix(string namespaceUri)
{
return this.LocatePrefixFor(namespaceUri);
}
protected void CloneElement(Element element, Document owner, bool deep)
{
CloneNode(element, owner, deep);
foreach (IAttr attribute in _attributes) {
Attr attr = new Attr(attribute.Prefix, attribute.LocalName, attribute.Value, attribute.NamespaceUri);
attr.Container = element._attributes;
element._attributes.FastAddItem(attr);
}
element.SetupElement();
}
}
}