using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
namespace ReadSharp.Ports.NReadability
{
public class MetaExtractor
{
///
/// Gets or sets a value indicating whether [has value].
///
///
/// true if [has value]; otherwise, false.
///
public bool HasValue { get; set; }
///
/// Gets or sets the tags.
///
///
/// The tags.
///
public IEnumerable Tags { get; private set; }
///
/// Initializes a new instance of the class.
///
/// The document.
public MetaExtractor(XDocument document)
{
var documentRoot = document.Root;
if (documentRoot == null || documentRoot.Name == null || !"html".Equals(documentRoot.Name.LocalName, StringComparison.OrdinalIgnoreCase))
{
HasValue = false;
return;
}
var headElement = documentRoot.GetChildrenByTagName("head").FirstOrDefault();
if (headElement == null)
{
HasValue = false;
return;
}
IEnumerable meta = headElement.GetChildrenByTagName("meta");
IEnumerable link = headElement.GetChildrenByTagName("link");
Tags = meta != null ? meta.Concat(link) : link;
HasValue = Tags != null && Tags.Count() > 0;
}
///
/// Gets the meta description.
///
///
public string GetMetaDescription()
{
return SearchCandidates(new Dictionary()
{
{ "property|og:description", "content" },
{ "name|description", "content" }
});
}
///
/// Gets the meta image.
///
///
public string GetMetaImage()
{
return SearchCandidates(new Dictionary()
{
{ "property|og:image", "content" },
{ "rel|apple-touch-icon", "href" },
{ "rel|apple-touch-icon-precomposed", "href"},
{ "name|msapplication-square310x310logo", "content" },
{ "name|msapplication-square150x150logo", "content" },
{ "name|msapplication-square70x70logo", "content" },
{ "name|msapplication-TileImage", "content" },
{ "rel|image_src", "href" }
});
}
///
/// Gets the meta favicon.
///
///
public string GetMetaFavicon()
{
return SearchCandidates(new Dictionary()
{
{ "rel|icon", "href" },
{ "rel|shortcut icon", "href" }
});
}
///
/// Gets the charset.
///
///
public string GetCharset()
{
// find:
string result = SearchCandidates(new Dictionary()
{
{ "charset", "charset" }
}, true);
if (String.IsNullOrEmpty(result))
{
// find:
result = SearchCandidates(new Dictionary()
{
{ "http-equiv|Content-Type", "content" }
});
if (!String.IsNullOrEmpty(result))
{
int charsetStart = result.IndexOf("charset=");
if (charsetStart > 0)
{
charsetStart += 8;
result = result.Substring(charsetStart, result.Length - charsetStart);
}
}
}
return String.IsNullOrEmpty(result) ? null : result.ToUpper();
}
///
/// Searches the candidates.
///
/// The candidates.
///
private string SearchCandidates(Dictionary candidates, bool simple = false)
{
string result = null;
foreach (var candidate in candidates)
{
XElement element;
string[] type = candidate.Key.Split('|');
if (simple)
{
element = Tags
.Where(item => item.GetAttributeValue(type[0], null) != null)
.FirstOrDefault();
}
else
{
element = Tags
.Where(item => String.Equals(item.GetAttributeValue(type[0], null), type[1], StringComparison.OrdinalIgnoreCase))
.FirstOrDefault();
}
if (element != null)
{
result = element.GetAttributeValue(candidate.Value, "");
}
if (result != null && result.Length > 1)
{
break;
}
}
return result;
}
}
}