public static int KeyMatchCount(KeyValueElementInfo kv, string elementName, IEnumerable<string> names)
 {
     var res = 0;
     if (kv.ElementName == "*" || kv.ElementName == elementName)
     {
         res = names == null || names.Count() == 0 ? -1 : names.Where(a => kv.KeyNames.Any(b => b == a)).Count();
         if (!string.IsNullOrWhiteSpace(kv.ValueName))
         {
             if (names != null && names.Any(a => a == kv.ValueName))
                 res++;
         }
     }
     return res;
 }
        public static int KeyMatchCount(KeyValueElementInfo kv, string elementName, IEnumerable <string> names)
        {
            var res = 0;

            if (kv.ElementName == "*" || kv.ElementName == elementName)
            {
                res = names == null || names.Count() == 0 ? -1 : names.Where(a => kv.KeyNames.Any(b => b == a)).Count();
                if (!string.IsNullOrWhiteSpace(kv.ValueName))
                {
                    if (names != null && names.Any(a => a == kv.ValueName))
                    {
                        res++;
                    }
                }
            }
            return(res);
        }
        internal static KeyValueElementInfo GetBestKeyValueInfo(this XElement element)
        {
            var res = default(KeyValueElementInfo);

            if (element != null)
            {
                var attribNames = element.GetAttributes().Select(a => a.Name.LocalName);
                res = Common.commonKeyValues
                      .Where(a => attribNames.Count() > 1 || string.IsNullOrWhiteSpace(a.ValueName))
                      .Select(a => new { MatchCount = KeyValueElementInfo.KeyMatchCount(a, element.Name.LocalName, attribNames), KeyValueInfo = a, })
                      .OrderByDescending(a => a.MatchCount)
                      .Where(a => a.MatchCount >= (attribNames.Count() == 1 ? 1 : 2))
                      .Select(a => a.KeyValueInfo)
                      .FirstOrDefault()
                ;
            }
            return(res);
        }
        public static string GetXPath(this XElement element, KeyValueElementInfo keyValueInfo)
        {
            if (element == null)
            {
                return(string.Empty);
            }

            if (element == element.Document.Root)
            {
                var s = "/" + element.FQN();
                return(s);
            }

            var kvParent = element.Parent.GetBestKeyValueInfo();

            var res = element.Parent.GetXPath(kvParent) + "/" + element.FQN();

            var attribs = element.GetAttributes();

            if (attribs.Any())
            {
                if (keyValueInfo == null)
                {
                    var filter = "[" + string.Join(" and ", element.GetAttributes().Select(a => a.FQN() + "=" + "\"" + a.Value.XmlEncode() + "\"")) + "]";
                    res += filter;
                }
                else
                {
                    var filterAttrs = element.GetAttributes().Where(a => keyValueInfo.KeyNames.Any(k => k == a.Name.LocalName)).ToList();
                    if (!filterAttrs.Any())
                    {
                        Debugger.Break();
                    }
                    var filter = "[" + string.Join(" and ", filterAttrs.Select(a => a.FQN() + "=" + "\"" + a.Value.XmlEncode() + "\"")) + "]";
                    res += filter;
                }
            }

            return(res);
        }
        public static string GetXPath(this XElement element, KeyValueElementInfo keyValueInfo)
        {
            if (element == null)
                return string.Empty;

            if (element == element.Document.Root)
            {
                var s = "/" + element.FQN();
                return s;
            }

            var kvParent = element.Parent.GetBestKeyValueInfo();

            var res = element.Parent.GetXPath(kvParent) + "/" + element.FQN();

            var attribs = element.GetAttributes();

            if (attribs.Any())
            {
                if (keyValueInfo == null)
                {
                    var filter = "[" + string.Join(" and ", element.GetAttributes().Select(a => a.FQN() + "=" + "\"" + a.Value.XmlEncode() + "\"")) + "]";
                    res += filter;
                }
                else
                {
                    var filterAttrs = element.GetAttributes().Where(a => keyValueInfo.KeyNames.Any(k => k == a.Name.LocalName)).ToList();
                    if (!filterAttrs.Any())
                        Debugger.Break();
                    var filter = "[" + string.Join(" and ", filterAttrs.Select(a => a.FQN() + "=" + "\"" + a.Value.XmlEncode() + "\"")) + "]";
                    res += filter;
                }
            }

            return res;
        }