loading...

Favicon and Linq

bugmagnet profile image Bruce Axtens ・2 min read

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

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

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.

Posted on by:

bugmagnet profile

Bruce Axtens

@bugmagnet

Programmed Canon Canola calculators in 1977. Assorted platforms and languages ever since. Assisting with HOPL.info. I am NOT looking for work -- I've got more than enough to do.

Discussion

markdown guide