public static IList <HtmlNode> QuerySelectorAll(this IEnumerable <HtmlNode> nodes, string cssSelector) { if (cssSelector == null) { throw new ArgumentNullException(nameof(cssSelector)); } if (cssSelector.Contains(',')) { var combinedSelectors = cssSelector.Split(','); var rt = nodes.QuerySelectorAll(combinedSelectors[0]); foreach (var s in combinedSelectors.Skip(1)) { foreach (var n in nodes.QuerySelectorAll(s)) { if (!rt.Contains(n)) { rt.Add(n); } } } return(rt); } cssSelector = cssSelector.Trim(); var selectors = CssSelector.Parse(cssSelector); bool allowTraverse = true; for (int i = 0; i < selectors.Count; i++) { var selector = selectors[i]; if (allowTraverse && selector.AllowTraverse) { // If this is not the first selector then we must make filter against the child nodes of the current set of nodes // since any selector that follows another selector always scopes down the nodes to the descendants of the last scope. // Example: "span span" Should only resolve with span elements that are descendants of another span element. // Any span elements that are not descendant of another span element shoud not be included in the output. if (i > 0) { nodes = nodes.SelectMany(n => n.ChildNodes); } nodes = Traverse(nodes); } nodes = selector.Filter(nodes); allowTraverse = selector.AllowTraverse; } return(nodes.Distinct().ToList()); }
public static IList <HtmlNode> QuerySelectorAll(this IEnumerable <HtmlNode> nodes, string cssSelector) { if (cssSelector == null) { throw new ArgumentNullException(nameof(cssSelector)); } if (cssSelector.Contains(',')) { var combinedSelectors = cssSelector.Split(','); var rt = nodes.QuerySelectorAll(combinedSelectors[0]); foreach (var s in combinedSelectors.Skip(1)) { foreach (var n in nodes.QuerySelectorAll(s)) { if (!rt.Contains(n)) { rt.Add(n); } } } return(rt); } cssSelector = cssSelector.Trim(); var selectors = CssSelector.Parse(cssSelector); bool allowTraverse = true; foreach (var selector in selectors) { if (allowTraverse && selector.AllowTraverse) { nodes = Traverse(nodes); } nodes = selector.Filter(nodes); allowTraverse = selector.AllowTraverse; } return(nodes.Distinct().ToList()); }