JQuery“.closest()”等同于HtmlAgilityPack?

时间:2016-12-01 02:30:24

标签: c# html-agility-pack

我正在使用awk version -GNU Awk 4.0.1。它是否具有与HtmlAgilityPack jQuery类似的功能? (与CSS选择器匹配的最近父级)。我试过谷歌和网站http://html-agility-pack.net - 两者似乎都没有答案。

2 个答案:

答案 0 :(得分:1)

由于目前没有内置方法,您可以编写Extension method来实现此目的。

我编写了一个简单的扩展方法,可用于查找可以使用tagNameIDclass名称的元素。

无论如何,它可以进一步扩展以匹配其他选择器。

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");
        }

答案 1 :(得分:0)

我需要相同的东西,但找不到任何东西,所以我写了自己的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;
} 

这个只适用于标签名称(我需要)你可以将它扩展到类,属性和......