internal static bool IsPseudoMatch(this HtmlAgilityPack.HtmlNode node, SimpleSelector selector, Stack<SimpleSelector> remainingStack) { //by default we fail out any rule using a pseudo selector return false; }
private void Add(SimpleSelector addSel) { if (addSel.Child != null) Add(addSel.Child); if (!string.IsNullOrEmpty(addSel.Class)) Class++; if (addSel.Attribute != null) Attribute++; if (addSel.Pseudo != null) Attribute++; if (!string.IsNullOrEmpty(addSel.ElementName)) Element++; if (!string.IsNullOrEmpty(addSel.ID)) Id++; }
internal static bool IsMatch(this HtmlAgilityPack.HtmlNode node, SimpleSelector selector, Stack<SimpleSelector> remainingStack) { if (!string.IsNullOrEmpty(selector.ElementName) && node.Name != selector.ElementName) return false; if (!string.IsNullOrEmpty(selector.ID) && node.Id != selector.ID) return false; if (!string.IsNullOrEmpty(selector.Class)) { var classString = node.Attributes.Contains("class") ? node.Attributes["class"].Value : ""; if (!classString.Split(' ').Contains(selector.Class)) return false; } if (!string.IsNullOrEmpty(selector.Pseudo)) { if (!node.IsPseudoMatch(selector, remainingStack)) return false; } if (selector.Combinator != null && remainingStack.Any()) { var nextSel = remainingStack.Pop(); switch (selector.Combinator.Value) { case Combinator.ChildOf: if (node.ParentNode == null)//has to be a child of something return false; if(!node.ParentNode.IsMatch(nextSel, remainingStack)) return false; break; case Combinator.Namespace: //we are not going to support this until I see a valid use case return false; case Combinator.PrecededBy: if(!node.PreviousSiblingsNotText().Any(x=>x.IsMatch(nextSel, remainingStack))) return false; break; case Combinator.PrecededImmediatelyBy: var sib = node.PreviousSiblingNotText(); if (sib == null)//has to be a child of something return false; if (!sib.IsMatch(nextSel, remainingStack)) return false; break; default: break; } } if (selector.Attribute != null) { if (!node.IsMatch(selector.Attribute)) return false; } if (selector.Child != null) { return node.IsMatch(selector.Child, remainingStack); } return true; }