HtmlAgilityPack: How to check if an element is visible?

c# html-agility-pack

Question

I am doing some HTML parsing and I am using HtmlAgilityPack and I am trying to check if a node element would be visible if the html was rendered in a browser.

By visible, I am probably content with checking the display and visibility style values. (unless there is something additional I should worry about?).

So, how can I do this? Is there a build in easy way? Can I use some XPath magic? (I don't have too much knowledge of XPath at the moment).

I have thought about manually parsing the style value, but would rather save this as a last resort. Or is this my only option?

Just for reference, the object I am working with is something like this:

HtmlAgilityPack.HtmlNode node = GetNode();

Accepted Answer

OK, so I have managed to do this, at least for my needs. Please be warned however, as other comments have spoke of, this doesn't allow you to check if an element will be visible (on screen) for the end user.

The approach I have taken simple checks some basic rules: An element is "not visible" if the style attribute for the element contains display:none or visibility:hidden, OR an ancestor element has the same style rules.

With that in mind, here is my code that does the job for me:

private static bool IsNodeVisible(HtmlAgilityPack.HtmlNode node)
{
    var attribute = node.Attributes["style"];

    bool thisVisible = false;

    if (attribute == null || CheckStyleVisibility(attribute.Value))
        thisVisible = true;

    if (thisVisible && node.ParentNode != null)
        return IsNodeVisible(node.ParentNode);

    return thisVisible;
}

private static bool CheckStyleVisibility(string style)
{
    if (string.IsNullOrWhiteSpace(style))
        return true;

    var keys = ParseHtmlStyleString(style);

    if (keys.Keys.Contains("display"))
    {
        string display = keys["display"];
        if (display != null && display == "none")
            return false;
    }

    if (keys.Keys.Contains("visibility"))
    {
        string visibility = keys["visibility"];
        if (visibility != null && visibility == "hidden")
            return false;
    }

    return true;
}

public static Dictionary<string, string> ParseHtmlStyleString(string style)
{
    Dictionary<string, string> result = new Dictionary<string, string>();

    style = style.Replace(" ", "").ToLowerInvariant();

    string[] settings = style.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);

    foreach (string s in settings)
    {
        if (!s.Contains(':'))
            continue;
        string[] data = s.Split(':');
        result.Add(data[0], data[1]);
    }

    return result;
}

The entry point for this is IsNodeVisible and will check the visibility of the HtmlNode passed to it.




Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why