AngleSharp by AngleSharp

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

 TreeWalker

sealed class TreeWalker : ITreeWalker
The treewalker for walking through the DOM tree.
using AngleSharp.Extensions; namespace AngleSharp.Dom.Collections { internal sealed class TreeWalker : ITreeWalker { private readonly INode _root; private readonly FilterSettings _settings; private readonly NodeFilter _filter; private INode _current; public INode Root => _root; public FilterSettings Settings => _settings; public NodeFilter Filter => _filter; public INode Current { get { return _current; } set { _current = value; } } public TreeWalker(INode root, FilterSettings settings, NodeFilter filter) { _root = root; _settings = settings; _filter = (filter ?? ((NodeFilter)((INode m) => FilterResult.Accept))); _current = _root; } public INode ToNext() { INode node = _current; FilterResult filterResult = FilterResult.Accept; while (node != null) { while (filterResult != FilterResult.Reject && node.HasChildNodes) { node = node.FirstChild; filterResult = Check(node); if (filterResult == FilterResult.Accept) { _current = node; return node; } } while (node != _root) { INode nextSibling = node.NextSibling; if (nextSibling != null) { node = nextSibling; break; } node = node.Parent; } if (node == _root) break; filterResult = Check(node); if (filterResult == FilterResult.Accept) { _current = node; return node; } } return null; } public INode ToPrevious() { INode node = _current; while (node != null && node != _root) { INode previousSibling = node.PreviousSibling; while (previousSibling != null) { node = previousSibling; FilterResult filterResult = Check(node); while (filterResult != FilterResult.Reject && node.HasChildNodes) { node = node.LastChild; filterResult = Check(node); if (filterResult == FilterResult.Accept) { _current = node; return node; } } } if (node == _root || node.Parent == null) break; if (Check(node) == FilterResult.Accept) { _current = node; return node; } } return null; } public INode ToParent() { INode node = _current; while (node != null && node != _root) { node = node.Parent; if (node != null && Check(node) == FilterResult.Accept) { _current = node; return node; } } return null; } public INode ToFirst() { INode node = (_current != null) ? _current.FirstChild : null; while (node != null) { switch (Check(node)) { case FilterResult.Accept: _current = node; return node; case FilterResult.Skip: { INode firstChild = node.FirstChild; if (firstChild != null) { node = firstChild; break; } goto default; } default: while (node != null) { INode nextSibling = node.NextSibling; if (nextSibling != null) { node = nextSibling; break; } INode parent = node.Parent; if (parent == null || parent == _root || parent == _current) { node = null; break; } node = parent; } break; } } return null; } public INode ToLast() { INode node = (_current != null) ? _current.LastChild : null; while (node != null) { switch (Check(node)) { case FilterResult.Accept: _current = node; return node; case FilterResult.Skip: { INode lastChild = node.LastChild; if (lastChild != null) { node = lastChild; break; } goto default; } default: while (node != null) { INode previousSibling = node.PreviousSibling; if (previousSibling != null) { node = previousSibling; break; } INode parent = node.Parent; if (parent == null || parent == _root || parent == _current) { node = null; break; } node = parent; } break; } } return null; } public INode ToPreviousSibling() { INode node = _current; if (node != _root) { while (node != null) { INode node2 = node.PreviousSibling; while (node2 != null) { node = node2; FilterResult filterResult = Check(node); if (filterResult == FilterResult.Accept) { _current = node; return node; } node2 = node.LastChild; if (filterResult == FilterResult.Reject || node2 == null) node2 = node.PreviousSibling; } node = node.Parent; if (node == null || node == _root || Check(node) == FilterResult.Accept) break; } } return null; } public INode ToNextSibling() { INode node = _current; if (node != _root) { while (node != null) { INode node2 = node.NextSibling; while (node2 != null) { node = node2; FilterResult filterResult = Check(node); if (filterResult == FilterResult.Accept) { _current = node; return node; } node2 = node.FirstChild; if (filterResult == FilterResult.Reject || node2 == null) node2 = node.NextSibling; } node = node.Parent; if (node == null || node == _root || Check(node) == FilterResult.Accept) break; } } return null; } private FilterResult Check(INode node) { if (!_settings.Accepts(node)) return FilterResult.Skip; return _filter(node); } } }