JQuery HtmlAgilityPack 中的“.closest()”等价物?
JQuery ".closest()" equivalent in HtmlAgilityPack?
我正在使用 HtmlAgilityPack
。有没有类似jQuery
closest
的功能? (与 CSS 选择器匹配的最近父级)。我尝试了 google 和网站 http://html-agility-pack.net - 两者似乎都没有答案。
我需要同样的东西,但找不到,所以我写了自己的 Closest
函数:
public static HtmlNode Closest(this HtmlNode node, string search)
{
search = search.ToLower();
while (node.ParentNode != null)
{
if (node.ParentNode.Name.ToLower() == search) return node.ParentNode;
node = node.ParentNode;
}
return null;
}
这个仅适用于标签名称(正如我所需要的),您可以将其扩展到 类、属性和...
目前没有内置方法,可以自己写一个Extension method
来实现
我写了一个简单的扩展方法,可用于查找名称为 tagName
、ID
和 class
的元素。
无论如何,它可以很容易地进一步扩展以匹配其他选择器。
public static class HtmlAgilityPackExtensions
{
public static HtmlNode Closest(this HtmlNode node, string jQuerySelector)
{
if (node == null) return null;
string tagName = "", id = "";
var classes = new List<string>();
if (jQuerySelector.Contains("."))
{
var parts = jQuerySelector.Split('.');
if (!string.IsNullOrWhiteSpace(parts[0]))
{
tagName = parts[0];
}
for (int i = 1; i < parts.Length; i++)
{
classes.Add(parts[i]);
}
}
if (jQuerySelector.Contains("#"))
{
var parts = jQuerySelector.Split('#');
if (!string.IsNullOrWhiteSpace(parts[0]))
{
tagName = parts[0];
}
id = parts[1];
}
if (string.IsNullOrWhiteSpace(tagName) && string.IsNullOrWhiteSpace(id) && classes.Count == 0)
{
tagName = jQuerySelector;
}
HtmlNode closestParent = null;
while (node.ParentNode != null && closestParent == null)
{
var isClosest = true;
node = node.ParentNode;
if (!string.IsNullOrWhiteSpace(tagName))
{
isClosest = node.Name == tagName;
}
if (isClosest && !string.IsNullOrWhiteSpace(id))
{
isClosest = node.Id == id;
}
if (isClosest && classes.Count > 0)
{
var classNames = node.GetAttributeValue("class", "");
if (!string.IsNullOrWhiteSpace(classNames))
{
foreach (string c in classes)
{
isClosest = classNames.Contains(c);
if (!isClosest) break;
}
}
}
if (isClosest)
{
closestParent = node;
}
}
return closestParent;
}
}
测试代码
var html = "<div><div id='parent1' class='parent'><span id='parent2' class='parent'><div id='parent3' class='parent'><div id='TestNode' class='child'>Test node</div></div></span></div></div>";
var htmlDoc = new HtmlDocument();
htmlDoc.LoadHtml(html);
var testNode1 = htmlDoc.DocumentNode.SelectSingleNode("//div[@id='TestNode']");
if (testNode1 != null)
{
var parent1 = testNode1.Closest(".parent");
var parent2 = testNode1.Closest("#parent1");
var parent3 = testNode1.Closest("span.parent");
var nonExistingParent = testNode1.Closest("span.parent1");
}
我正在使用 HtmlAgilityPack
。有没有类似jQuery
closest
的功能? (与 CSS 选择器匹配的最近父级)。我尝试了 google 和网站 http://html-agility-pack.net - 两者似乎都没有答案。
我需要同样的东西,但找不到,所以我写了自己的 Closest
函数:
public static HtmlNode Closest(this HtmlNode node, string search)
{
search = search.ToLower();
while (node.ParentNode != null)
{
if (node.ParentNode.Name.ToLower() == search) return node.ParentNode;
node = node.ParentNode;
}
return null;
}
这个仅适用于标签名称(正如我所需要的),您可以将其扩展到 类、属性和...
目前没有内置方法,可以自己写一个Extension method
来实现
我写了一个简单的扩展方法,可用于查找名称为 tagName
、ID
和 class
的元素。
无论如何,它可以很容易地进一步扩展以匹配其他选择器。
public static class HtmlAgilityPackExtensions
{
public static HtmlNode Closest(this HtmlNode node, string jQuerySelector)
{
if (node == null) return null;
string tagName = "", id = "";
var classes = new List<string>();
if (jQuerySelector.Contains("."))
{
var parts = jQuerySelector.Split('.');
if (!string.IsNullOrWhiteSpace(parts[0]))
{
tagName = parts[0];
}
for (int i = 1; i < parts.Length; i++)
{
classes.Add(parts[i]);
}
}
if (jQuerySelector.Contains("#"))
{
var parts = jQuerySelector.Split('#');
if (!string.IsNullOrWhiteSpace(parts[0]))
{
tagName = parts[0];
}
id = parts[1];
}
if (string.IsNullOrWhiteSpace(tagName) && string.IsNullOrWhiteSpace(id) && classes.Count == 0)
{
tagName = jQuerySelector;
}
HtmlNode closestParent = null;
while (node.ParentNode != null && closestParent == null)
{
var isClosest = true;
node = node.ParentNode;
if (!string.IsNullOrWhiteSpace(tagName))
{
isClosest = node.Name == tagName;
}
if (isClosest && !string.IsNullOrWhiteSpace(id))
{
isClosest = node.Id == id;
}
if (isClosest && classes.Count > 0)
{
var classNames = node.GetAttributeValue("class", "");
if (!string.IsNullOrWhiteSpace(classNames))
{
foreach (string c in classes)
{
isClosest = classNames.Contains(c);
if (!isClosest) break;
}
}
}
if (isClosest)
{
closestParent = node;
}
}
return closestParent;
}
}
测试代码
var html = "<div><div id='parent1' class='parent'><span id='parent2' class='parent'><div id='parent3' class='parent'><div id='TestNode' class='child'>Test node</div></div></span></div></div>";
var htmlDoc = new HtmlDocument();
htmlDoc.LoadHtml(html);
var testNode1 = htmlDoc.DocumentNode.SelectSingleNode("//div[@id='TestNode']");
if (testNode1 != null)
{
var parent1 = testNode1.Closest(".parent");
var parent2 = testNode1.Closest("#parent1");
var parent3 = testNode1.Closest("span.parent");
var nonExistingParent = testNode1.Closest("span.parent1");
}