DEV Community

Bruce Axtens
Bruce Axtens

Posted on

Favicon and Linq

I'm getting very partial to Linq. The encapsulation of logic at a declarative level is getting quite addictive.

I'll start off with the declaration of the Favicon object before I get to the code.

    [Serializable()]
    public class Favicon
    {
        public string Rel { get; set; }
        public string Type { get; set; }
        public string Title { get; set; }
        public string Href { get; set; }
        public string Sizes { get; set; }
    }
Enter fullscreen mode Exit fullscreen mode

Next the code.

        private Favicon[] GetFavicons(HtmlNode document)
        {
            var favicons = new List<Favicon>();

            var rels = from link in 
            (from tag in document.Descendants("link") select tag) 
            where link.Attributes["rel"] != null && 
            link.Attributes["rel"].Value.Contains("icon") select link;

            foreach (var link in rels)
            {
                favicons.Add(new Favicon
                {
                    Href = link.Attributes["href"]?.Value,
                    Rel = link.Attributes["rel"]?.Value,
                    Title = link.Attributes["title"]?.Value,
                    Type = link.Attributes["type"]?.Value,
                    Sizes = link.Attributes["sizes"]?.Value
                });
            }

            return favicons.ToArray();
        }
Enter fullscreen mode Exit fullscreen mode

The HtmlNode in this case is provided by HtmlAgilityPack. I haven't tried but I expect XDocument could work as it also has a Descendants method.

First of all we get all the link tags in the document. Then we pass that iterator up to another that finds all the links that are rel links with a value containing "icon" (so that one catches things like "icon", "shortcut icon" and "apple-touch-icon"). Then we iterate through the result set, create a new Favicon object and assign values to its members and then add the finished article to the List. (The ?. notation is the null-conditional operator discussed at Microsoft Docs.)

Finally, we turn the List into an array and return. This data structure eventually ends up in a large XML file.

I could put the whole of the clause after the rels = into the head of the foreach, but it gets a bit hard to read at that point. In fact, I may go back to having the from tag in document.Descendants("link") select tag clause assigned to separate variable (as I had it earlier in the development cycle) again just for the sake of readability.

Top comments (0)