public override void Validate(object state)
        {
            base.Validate(state);

            if (XPath.IsNull())
            {
                throw new ChoRecordConfigurationException("XPath can't be null or whitespace.");
            }

            if (XPath.IsNullOrWhiteSpace())
            {
                if (RecordType != null)
                {
                    NodeName = RecordType.Name;
                    RootName = RecordType.Namespace;
                }
            }
            else
            {
                RootName = XPath.SplitNTrim("/").Where(t => !t.IsNullOrWhiteSpace() && t.NTrim() != "." && t.NTrim() != ".." && t.NTrim() != "*").FirstOrDefault();
                NodeName = XPath.SplitNTrim("/").Where(t => !t.IsNullOrWhiteSpace() && t.NTrim() != "." && t.NTrim() != ".." && t.NTrim() != "*").Skip(1).FirstOrDefault();
            }

            if (RootName.IsNullOrWhiteSpace())
            {
                ChoXmlDocumentRootAttribute da = TypeDescriptor.GetAttributes(RecordType).OfType <ChoXmlDocumentRootAttribute>().FirstOrDefault();
                if (da != null)
                {
                    NodeName = da.Name;
                }
                if (RootName.IsNullOrWhiteSpace())
                {
                    RootName = "Root";
                }
            }

            if (NodeName.IsNullOrWhiteSpace())
            {
                if (!IsDynamicObject)
                {
                    XmlRootAttribute ra = TypeDescriptor.GetAttributes(RecordType).OfType <XmlRootAttribute>().FirstOrDefault();
                    if (ra != null)
                    {
                        NodeName = ra.ElementName;
                    }
                }

                if (NodeName.IsNullOrWhiteSpace())
                {
                    NodeName = "XElement";
                }
            }

            //Encode Root and node names
            RootName = System.Net.WebUtility.HtmlEncode(RootName);
            NodeName = System.Net.WebUtility.HtmlEncode(NodeName);

            string[] fieldNames = null;
            XElement xpr        = null;

            if (state is Tuple <long, XElement> )
            {
                xpr = ((Tuple <long, XElement>)state).Item2;
            }
            else
            {
                fieldNames = state as string[];
            }

            if (AutoDiscoverColumns &&
                XmlRecordFieldConfigurations.Count == 0)
            {
                if (RecordType != null && !IsDynamicObject &&
                    ChoTypeDescriptor.GetProperties(RecordType).Where(pd => pd.Attributes.OfType <ChoXmlNodeRecordFieldAttribute>().Any()).Any())
                {
                    IsComplexXPathUsed = false;

                    long   startIndex = 0;
                    long   size       = 0;
                    string xpath      = null;
                    bool   useCache   = true;
                    ChoXmlNodeRecordFieldAttribute attr = null;
                    foreach (PropertyDescriptor pd in ChoTypeDescriptor.GetProperties(RecordType).Where(pd => pd.Attributes.OfType <ChoXmlNodeRecordFieldAttribute>().Any()))
                    {
                        //if (!pd.PropertyType.IsSimple())
                        //    throw new ChoRecordConfigurationException("Property '{0}' is not a simple type.".FormatString(pd.Name));

                        attr = ChoTypeDescriptor.GetPropetyAttribute <ChoXmlNodeRecordFieldAttribute>(pd);
                        if (attr.XPath.IsNullOrEmpty())
                        {
                            xpath = $"//{pd.Name}|//@{pd.Name}";
                            IsComplexXPathUsed = true;
                        }
                        else
                        {
                            useCache = false;
                        }

                        var obj = new ChoXmlRecordFieldConfiguration(pd.Name, xpath);
                        obj.FieldType = pd.PropertyType;
                        obj.UseCache  = useCache;
                        XmlRecordFieldConfigurations.Add(obj);

                        startIndex += size;
                    }

                    //RecordLength = startIndex;
                }
                else if (xpr != null)
                {
                    IsComplexXPathUsed = false;
                    ChoXmlNamespaceManager nsMgr = new ChoXmlNamespaceManager(NamespaceManager);

                    Dictionary <string, ChoXmlRecordFieldConfiguration> dict = new Dictionary <string, ChoXmlRecordFieldConfiguration>(StringComparer.CurrentCultureIgnoreCase);
                    string name = null;
                    foreach (var attr in xpr.Attributes())
                    {
                        //if (!attr.Name.NamespaceName.IsNullOrWhiteSpace()) continue;

                        name = GetNameWithNamespace(attr.Name);

                        if (!dict.ContainsKey(name))
                        {
                            dict.Add(name, new ChoXmlRecordFieldConfiguration(name, $"//@{name}")); // DefaultNamespace.IsNullOrWhiteSpace() ? $"//@{name}" : $"//@{DefaultNamespace}" + ":" + $"{name}") { IsXmlAttribute = true });
                        }
                        else
                        {
                            throw new ChoRecordConfigurationException("Duplicate field(s) [Name(s): {0}] found.".FormatString(name));
                        }
                    }

                    bool hasElements = false;
                    var  z           = xpr.Elements().Where(a => !a.HasElements).ToArray();
                    foreach (var ele in xpr.Elements().Where(a => !a.HasElements))
                    {
                        name = GetNameWithNamespace(ele.Name);

                        hasElements = true;
                        if (!dict.ContainsKey(name))
                        {
                            dict.Add(name, new ChoXmlRecordFieldConfiguration(name, $"//{name}")); // DefaultNamespace.IsNullOrWhiteSpace() ? $"//{name}" : $"//{DefaultNamespace}" + ":" + $"{name}"));
                        }
                        else
                        {
                            if (dict[name].IsXmlAttribute)
                            {
                                throw new ChoRecordConfigurationException("Duplicate field(s) [Name(s): {0}] found.".FormatString(name));
                            }

                            dict[name].IsCollection = true;
                        }
                    }

                    if (!hasElements)
                    {
                        name = xpr.Name.LocalName;
                        dict.Add(name, new ChoXmlRecordFieldConfiguration(name, "text()"));
                    }

                    foreach (ChoXmlRecordFieldConfiguration obj in dict.Values)
                    {
                        XmlRecordFieldConfigurations.Add(obj);
                    }
                }
                else if (!fieldNames.IsNullOrEmpty())
                {
                    foreach (string fn in fieldNames)
                    {
                        var obj = new ChoXmlRecordFieldConfiguration(fn, xPath: $"//{fn}");
                        XmlRecordFieldConfigurations.Add(obj);
                    }
                }
            }
            else
            {
                IsComplexXPathUsed = false;

                foreach (var fc in XmlRecordFieldConfigurations)
                {
                    if (fc.XPath.IsNullOrWhiteSpace())
                    {
                        fc.XPath = $"//{fc.FieldName}|//@{fc.FieldName}";
                    }
                    else
                    {
                        if (fc.XPath == fc.FieldName ||
                            fc.XPath == $"//{fc.FieldName}" || fc.XPath == $"/{fc.FieldName}" || fc.XPath == $"./{fc.FieldName}" ||
                            fc.XPath == $"//@{fc.FieldName}" || fc.XPath == $"/@{fc.FieldName}" || fc.XPath == $"./@{fc.FieldName}"
                            )
                        {
                        }
                        else
                        {
                            IsComplexXPathUsed = true;
                            fc.UseCache        = false;
                        }
                    }
                }
            }

            if (XmlRecordFieldConfigurations.Count <= 0)
            {
                throw new ChoRecordConfigurationException("No record fields specified.");
            }

            //Validate each record field
            foreach (var fieldConfig in XmlRecordFieldConfigurations)
            {
                fieldConfig.Validate(this);
            }

            //Check field position for duplicate
            string[] dupFields = XmlRecordFieldConfigurations.GroupBy(i => i.Name)
                                 .Where(g => g.Count() > 1)
                                 .Select(g => g.Key).ToArray();

            if (dupFields.Length > 0)
            {
                throw new ChoRecordConfigurationException("Duplicate field(s) [Name(s): {0}] found.".FormatString(String.Join(",", dupFields)));
            }

            RecordFieldConfigurationsDict = XmlRecordFieldConfigurations.OrderBy(c => c.IsXmlAttribute).Where(i => !i.Name.IsNullOrWhiteSpace()).ToDictionary(i => i.Name);

            LoadNCacheMembers(XmlRecordFieldConfigurations);
        }
        public override void Validate(object state)
        {
            base.Validate(state);

            //if (XPath.IsNull())
            //    throw new ChoRecordConfigurationException("XPath can't be null or whitespace.");

            if (XPath.IsNullOrWhiteSpace())
            {
                if (!IsDynamicObject && (RecordType.IsGenericType && RecordType.GetGenericTypeDefinition() == typeof(KeyValuePair <,>)))
                {
                    NodeName = NodeName.IsNullOrWhiteSpace() ? "KeyValuePair" : NodeName;
                    RootName = RootName.IsNullOrWhiteSpace() ? "KeyValuePairs" : RootName;
                }
                else if (!IsDynamicObject && !typeof(IChoScalarObject).IsAssignableFrom(RecordType))
                {
                    NodeName = NodeName.IsNullOrWhiteSpace() ? RecordType.Name : NodeName;
                    RootName = RootName.IsNullOrWhiteSpace() ? NodeName.ToPlural() : RootName;
                }
            }
            else
            {
                RootName = RootName.IsNullOrWhiteSpace() ? XPath.SplitNTrim("/").Where(t => !t.IsNullOrWhiteSpace() && t.NTrim() != "." && t.NTrim() != ".." && t.NTrim() != "*").FirstOrDefault() : RootName;
                NodeName = NodeName.IsNullOrWhiteSpace() ? XPath.SplitNTrim("/").Where(t => !t.IsNullOrWhiteSpace() && t.NTrim() != "." && t.NTrim() != ".." && t.NTrim() != "*").Skip(1).FirstOrDefault() : NodeName;
            }

            string rootName = null;
            string nodeName = null;
            ChoXmlDocumentRootAttribute da = TypeDescriptor.GetAttributes(RecordType).OfType <ChoXmlDocumentRootAttribute>().FirstOrDefault();

            if (da != null)
            {
                rootName = da.Name;
            }
            else
            {
                XmlRootAttribute ra = TypeDescriptor.GetAttributes(RecordType).OfType <XmlRootAttribute>().FirstOrDefault();
                if (ra != null)
                {
                    nodeName = ra.ElementName;
                }
            }

            RootName = RootName.IsNullOrWhiteSpace() && !rootName.IsNullOrWhiteSpace() ? rootName : RootName;
            NodeName = NodeName.IsNullOrWhiteSpace() && !nodeName.IsNullOrWhiteSpace() ? nodeName : NodeName;

            RootName = RootName.IsNullOrWhiteSpace() && !NodeName.IsNullOrWhiteSpace() ? NodeName.ToPlural() : RootName;
            if (!RootName.IsNullOrWhiteSpace() && RootName.ToSingular() != RootName)
            {
                NodeName = NodeName.IsNullOrWhiteSpace() && !RootName.IsNullOrWhiteSpace() ? RootName.ToSingular() : NodeName;
            }

            if (RootName.IsNullOrWhiteSpace())
            {
                RootName = "Root";
            }
            if (NodeName.IsNullOrWhiteSpace())
            {
                NodeName = "XElement";
            }

            //Encode Root and node names
            RootName = System.Net.WebUtility.HtmlEncode(RootName);
            NodeName = System.Net.WebUtility.HtmlEncode(NodeName);

            string[] fieldNames = null;
            XElement xpr        = null;

            if (state is Tuple <long, XElement> )
            {
                xpr = ((Tuple <long, XElement>)state).Item2;
            }
            else
            {
                fieldNames = state as string[];
            }

            if (AutoDiscoverColumns &&
                XmlRecordFieldConfigurations.Count == 0)
            {
                if (RecordType != null && !IsDynamicObject &&
                    ChoTypeDescriptor.GetProperties(RecordType).Where(pd => pd.Attributes.OfType <ChoXmlNodeRecordFieldAttribute>().Any()).Any())
                {
                    DiscoverRecordFields(RecordType);
                }
                else if (xpr != null)
                {
                    XmlRecordFieldConfigurations.AddRange(DiscoverRecordFieldsFromXElement(xpr));
                }
                else if (!fieldNames.IsNullOrEmpty())
                {
                    foreach (string fn in fieldNames)
                    {
                        if (IgnoredFields.Contains(fn))
                        {
                            continue;
                        }

                        if (fn.StartsWith("_"))
                        {
                            string fn1 = fn.Substring(1);
                            var    obj = new ChoXmlRecordFieldConfiguration(fn, xPath: $"./{fn1}");
                            obj.FieldName      = fn1;
                            obj.IsXmlAttribute = true;
                            XmlRecordFieldConfigurations.Add(obj);
                        }
                        else if (fn.EndsWith("_"))
                        {
                            string fn1 = fn.Substring(0, fn.Length - 1);
                            var    obj = new ChoXmlRecordFieldConfiguration(fn, xPath: $"./{fn1}");
                            obj.FieldName  = fn1;
                            obj.IsXmlCDATA = true;
                            XmlRecordFieldConfigurations.Add(obj);
                        }
                        else
                        {
                            var obj = new ChoXmlRecordFieldConfiguration(fn, xPath: $"./{fn}");
                            XmlRecordFieldConfigurations.Add(obj);
                        }
                    }
                }
            }
            else
            {
                IsComplexXPathUsed = false;

                foreach (var fc in XmlRecordFieldConfigurations)
                {
                    if (fc.IsArray == null)
                    {
                        fc.IsArray = typeof(ICollection).IsAssignableFrom(fc.FieldType);
                    }

                    if (fc.FieldName.IsNullOrWhiteSpace())
                    {
                        fc.FieldName = fc.Name;
                    }

                    if (fc.XPath.IsNullOrWhiteSpace())
                    {
                        fc.XPath = $"/{fc.FieldName}|/@{fc.FieldName}";
                    }
                    else
                    {
                        if (fc.XPath == fc.FieldName ||
                            fc.XPath == $"/{fc.FieldName}" || fc.XPath == $"/{fc.FieldName}" || fc.XPath == $"/{fc.FieldName}" ||
                            fc.XPath == $"/@{fc.FieldName}" || fc.XPath == $"/@{fc.FieldName}" || fc.XPath == $"/@{fc.FieldName}"
                            )
                        {
                        }
                        else
                        {
                            IsComplexXPathUsed = true;
                            fc.UseCache        = false;
                        }
                    }
                }
            }

            if (XmlRecordFieldConfigurations.Count <= 0)
            {
                throw new ChoRecordConfigurationException("No record fields specified.");
            }

            //Validate each record field
            foreach (var fieldConfig in XmlRecordFieldConfigurations)
            {
                fieldConfig.Validate(this);
            }

            //Check field position for duplicate
            string[] dupFields = XmlRecordFieldConfigurations.GroupBy(i => i.Name)
                                 .Where(g => g.Count() > 1)
                                 .Select(g => g.Key).ToArray();

            if (dupFields.Length > 0)
            {
                throw new ChoRecordConfigurationException("Duplicate field(s) [Name(s): {0}] found.".FormatString(String.Join(",", dupFields)));
            }

            PIDict = new Dictionary <string, System.Reflection.PropertyInfo>();
            PDDict = new Dictionary <string, PropertyDescriptor>();
            foreach (var fc in XmlRecordFieldConfigurations)
            {
                var pd1 = fc.DeclaringMember.IsNullOrWhiteSpace() ? ChoTypeDescriptor.GetProperty(RecordType, fc.Name)
                    : ChoTypeDescriptor.GetProperty(RecordType, fc.DeclaringMember);
                if (pd1 != null)
                {
                    fc.PropertyDescriptor = pd1;
                }

                if (fc.PropertyDescriptor == null)
                {
                    fc.PropertyDescriptor = TypeDescriptor.GetProperties(RecordType).AsTypedEnumerable <PropertyDescriptor>().Where(pd => pd.Name == fc.Name).FirstOrDefault();
                }
                if (fc.PropertyDescriptor == null)
                {
                    continue;
                }

                PIDict.Add(fc.Name, fc.PropertyDescriptor.ComponentType.GetProperty(fc.PropertyDescriptor.Name));
                PDDict.Add(fc.Name, fc.PropertyDescriptor);
            }

            RecordFieldConfigurationsDict = XmlRecordFieldConfigurations.OrderBy(c => c.IsXmlAttribute).Where(i => !i.Name.IsNullOrWhiteSpace()).ToDictionary(i => i.Name);

            if (XmlRecordFieldConfigurations.Where(e => e.IsNullable).Any() ||
                NullValueHandling == ChoNullValueHandling.Default)
            {
                if (NamespaceManager != null)
                {
                    if (!NamespaceManager.HasNamespace("xsi"))
                    {
                        NamespaceManager.AddNamespace("xsi", ChoXmlSettings.XmlSchemaInstanceNamespace);
                    }
                    if (!NamespaceManager.HasNamespace("xsd"))
                    {
                        NamespaceManager.AddNamespace("xsd", ChoXmlSettings.XmlSchemaNamespace);
                    }
                }
            }

            LoadNCacheMembers(XmlRecordFieldConfigurations);
        }
        public override void Validate(object state)
        {
            base.Validate(state);

            //if (XPath.IsNull())
            //    throw new ChoRecordConfigurationException("XPath can't be null or whitespace.");

            if (XPath.IsNullOrWhiteSpace())
            {
                if (!IsDynamicObject && (RecordType.IsGenericType && RecordType.GetGenericTypeDefinition() == typeof(KeyValuePair <,>)))
                {
                    NodeName = NodeName.IsNullOrWhiteSpace() ? "KeyValuePair" : NodeName;
                    RootName = RootName.IsNullOrWhiteSpace() ? "KeyValuePairs" : RootName;
                }
                else if (!IsDynamicObject && !typeof(IChoScalarObject).IsAssignableFrom(RecordType))
                {
                    NodeName = NodeName.IsNullOrWhiteSpace() ? RecordType.Name : NodeName;
                    RootName = RootName.IsNullOrWhiteSpace() ? NodeName.ToPlural() : NodeName;
                }
            }
            else
            {
                RootName = RootName.IsNullOrWhiteSpace() ? XPath.SplitNTrim("/").Where(t => !t.IsNullOrWhiteSpace() && t.NTrim() != "." && t.NTrim() != ".." && t.NTrim() != "*").FirstOrDefault() : RootName;
                NodeName = NodeName.IsNullOrWhiteSpace() ? XPath.SplitNTrim("/").Where(t => !t.IsNullOrWhiteSpace() && t.NTrim() != "." && t.NTrim() != ".." && t.NTrim() != "*").Skip(1).FirstOrDefault() : NodeName;
            }

            string rootName = null;
            string nodeName = null;
            ChoXmlDocumentRootAttribute da = TypeDescriptor.GetAttributes(RecordType).OfType <ChoXmlDocumentRootAttribute>().FirstOrDefault();

            if (da != null)
            {
                rootName = da.Name;
            }
            else
            {
                XmlRootAttribute ra = TypeDescriptor.GetAttributes(RecordType).OfType <XmlRootAttribute>().FirstOrDefault();
                if (ra != null)
                {
                    nodeName = ra.ElementName;
                }
            }

            RootName = RootName.IsNullOrWhiteSpace() && !rootName.IsNullOrWhiteSpace() ? rootName : RootName;
            NodeName = NodeName.IsNullOrWhiteSpace() && !nodeName.IsNullOrWhiteSpace() ? nodeName : NodeName;

            RootName = RootName.IsNullOrWhiteSpace() && !NodeName.IsNullOrWhiteSpace() ? NodeName.ToPlural() : RootName;
            if (!RootName.IsNullOrWhiteSpace() && RootName.ToSingular() != RootName)
            {
                NodeName = NodeName.IsNullOrWhiteSpace() && !RootName.IsNullOrWhiteSpace() ? RootName.ToSingular() : NodeName;
            }

            if (RootName.IsNullOrWhiteSpace())
            {
                RootName = "Root";
            }
            if (NodeName.IsNullOrWhiteSpace())
            {
                NodeName = "XElement";
            }

            //Encode Root and node names
            RootName = System.Net.WebUtility.HtmlEncode(RootName);
            NodeName = System.Net.WebUtility.HtmlEncode(NodeName);

            string[] fieldNames = null;
            XElement xpr        = null;

            if (state is Tuple <long, XElement> )
            {
                xpr = ((Tuple <long, XElement>)state).Item2;
            }
            else
            {
                fieldNames = state as string[];
            }

            if (AutoDiscoverColumns &&
                XmlRecordFieldConfigurations.Count == 0)
            {
                if (RecordType != null && !IsDynamicObject &&
                    ChoTypeDescriptor.GetProperties(RecordType).Where(pd => pd.Attributes.OfType <ChoXmlNodeRecordFieldAttribute>().Any()).Any())
                {
                    DiscoverRecordFields(RecordType);
                }
                else if (xpr != null)
                {
                    IsComplexXPathUsed = false;
                    ChoXmlNamespaceManager nsMgr = new ChoXmlNamespaceManager(NamespaceManager);

                    Dictionary <string, ChoXmlRecordFieldConfiguration> dict = new Dictionary <string, ChoXmlRecordFieldConfiguration>(StringComparer.CurrentCultureIgnoreCase);
                    string name = null;
                    foreach (var attr in xpr.Attributes())
                    {
                        if (!attr.IsValidAttribute(XmlSchemaNamespace, JSONSchemaNamespace))
                        {
                            continue;
                        }

                        if (!IsInNamespace(xpr.Name, attr.Name))
                        {
                            continue;
                        }
                        //if (!attr.Name.NamespaceName.IsNullOrWhiteSpace()) continue;

                        name = GetNameWithNamespace(xpr.Name, attr.Name);

                        if (!dict.ContainsKey(name))
                        {
                            dict.Add(name, new ChoXmlRecordFieldConfiguration(attr.Name.LocalName, $"./@{name}")
                            {
                                FieldName = name
                            });                                                                                                         // DefaultNamespace.IsNullOrWhiteSpace() ? $"//@{name}" : $"//@{DefaultNamespace}" + ":" + $"{name}") { IsXmlAttribute = true });
                        }
                        else
                        {
                            throw new ChoRecordConfigurationException("Duplicate field(s) [Name(s): {0}] found.".FormatString(name));
                        }
                    }

                    bool hasElements = false;
                    //var z = xpr.Elements().ToArray();
                    XElement ele = null;
                    foreach (var kvp in xpr.Elements().GroupBy(e => e.Name.LocalName).Select(g => new { Name = g.Key, Value = g.ToArray() }))
                    {
                        if (kvp.Value.Length == 1)
                        {
                            ele = kvp.Value.First();
                            if (!IsInNamespace(ele.Name))
                            {
                                continue;
                            }

                            name = GetNameWithNamespace(ele.Name);

                            hasElements = true;
                            if (!dict.ContainsKey(name))
                            {
                                dict.Add(name, new ChoXmlRecordFieldConfiguration(ele.Name.LocalName, $"./{name}")
                                {
                                    FieldName = name
                                });                                                                                                       // DefaultNamespace.IsNullOrWhiteSpace() ? $"//{name}" : $"//{DefaultNamespace}" + ":" + $"{name}"));
                            }
                            else
                            {
                                if (dict[name].IsXmlAttribute)
                                {
                                    throw new ChoRecordConfigurationException("Duplicate field(s) [Name(s): {0}] found.".FormatString(name));
                                }

                                dict[name].IsArray = true;
                            }
                        }
                        else if (kvp.Value.Length > 1)
                        {
                            ele = kvp.Value.First();
                            if (!IsInNamespace(ele.Name))
                            {
                                continue;
                            }

                            name = GetNameWithNamespace(ele.Name);

                            hasElements = true;
                            if (!dict.ContainsKey(name))
                            {
                                dict.Add(name, new ChoXmlRecordFieldConfiguration(xpr.Name.LocalName, $"./{name}")
                                {
                                    FieldName = name
                                });                                                                                                       // DefaultNamespace.IsNullOrWhiteSpace() ? $"//{name}" : $"//{DefaultNamespace}" + ":" + $"{name}"));
                            }
                            else
                            {
                                if (dict[name].IsXmlAttribute)
                                {
                                    throw new ChoRecordConfigurationException("Duplicate field(s) [Name(s): {0}] found.".FormatString(name));
                                }

                                dict[name].IsArray = true;
                            }
                        }
                    }

                    //foreach (var ele in xpr.Elements())
                    //{
                    //    if (!IsInNamespace(ele.Name))
                    //        continue;

                    //    name = GetNameWithNamespace(ele.Name);

                    //    hasElements = true;
                    //    if (!dict.ContainsKey(name))
                    //        dict.Add(name, new ChoXmlRecordFieldConfiguration(ele.Name.LocalName, $"/{name}") { FieldName = name }); // DefaultNamespace.IsNullOrWhiteSpace() ? $"//{name}" : $"//{DefaultNamespace}" + ":" + $"{name}"));
                    //    else
                    //    {
                    //        if (dict[name].IsXmlAttribute)
                    //            throw new ChoRecordConfigurationException("Duplicate field(s) [Name(s): {0}] found.".FormatString(name));

                    //        dict[name].IsArray = true;
                    //    }
                    //}

                    if (!hasElements)
                    {
                        if (IsInNamespace(xpr.Name))
                        {
                            //name = xpr.Name.LocalName;
                            name = GetNameWithNamespace(xpr.Name);
                            dict.Add(name, new ChoXmlRecordFieldConfiguration(name, "text()")
                            {
                                FieldName = name
                            });
                        }
                    }

                    foreach (ChoXmlRecordFieldConfiguration obj in dict.Values)
                    {
                        XmlRecordFieldConfigurations.Add(obj);
                    }
                }
                else if (!fieldNames.IsNullOrEmpty())
                {
                    foreach (string fn in fieldNames)
                    {
                        if (fn.StartsWith("_"))
                        {
                            string fn1 = fn.Substring(1);
                            var    obj = new ChoXmlRecordFieldConfiguration(fn, xPath: $"./{fn1}");
                            obj.FieldName      = fn1;
                            obj.IsXmlAttribute = true;
                            XmlRecordFieldConfigurations.Add(obj);
                        }
                        else if (fn.EndsWith("_"))
                        {
                            string fn1 = fn.Substring(0, fn.Length - 1);
                            var    obj = new ChoXmlRecordFieldConfiguration(fn, xPath: $"./{fn1}");
                            obj.FieldName  = fn1;
                            obj.IsXmlCDATA = true;
                            XmlRecordFieldConfigurations.Add(obj);
                        }
                        else
                        {
                            var obj = new ChoXmlRecordFieldConfiguration(fn, xPath: $"./{fn}");
                            XmlRecordFieldConfigurations.Add(obj);
                        }
                    }
                }
            }
            else
            {
                IsComplexXPathUsed = false;

                foreach (var fc in XmlRecordFieldConfigurations)
                {
                    if (fc.IsArray == null)
                    {
                        fc.IsArray = typeof(ICollection).IsAssignableFrom(fc.FieldType);
                    }

                    if (fc.FieldName.IsNullOrWhiteSpace())
                    {
                        fc.FieldName = fc.Name;
                    }

                    if (fc.XPath.IsNullOrWhiteSpace())
                    {
                        fc.XPath = $"./{fc.FieldName}|.//@{fc.FieldName}";
                    }
                    else
                    {
                        if (fc.XPath == fc.FieldName ||
                            fc.XPath == $"./{fc.FieldName}" || fc.XPath == $"./{fc.FieldName}" || fc.XPath == $"./{fc.FieldName}" ||
                            fc.XPath == $"./@{fc.FieldName}" || fc.XPath == $"./@{fc.FieldName}" || fc.XPath == $"./@{fc.FieldName}"
                            )
                        {
                        }
                        else
                        {
                            IsComplexXPathUsed = true;
                            fc.UseCache        = false;
                        }
                    }
                }
            }

            if (XmlRecordFieldConfigurations.Count <= 0)
            {
                throw new ChoRecordConfigurationException("No record fields specified.");
            }

            //Validate each record field
            foreach (var fieldConfig in XmlRecordFieldConfigurations)
            {
                fieldConfig.Validate(this);
            }

            //Check field position for duplicate
            string[] dupFields = XmlRecordFieldConfigurations.GroupBy(i => i.Name)
                                 .Where(g => g.Count() > 1)
                                 .Select(g => g.Key).ToArray();

            if (dupFields.Length > 0)
            {
                throw new ChoRecordConfigurationException("Duplicate field(s) [Name(s): {0}] found.".FormatString(String.Join(",", dupFields)));
            }

            PIDict = new Dictionary <string, System.Reflection.PropertyInfo>();
            PDDict = new Dictionary <string, PropertyDescriptor>();
            foreach (var fc in XmlRecordFieldConfigurations)
            {
                if (fc.PropertyDescriptor == null)
                {
                    fc.PropertyDescriptor = ChoTypeDescriptor.GetProperties(RecordType).Where(pd => pd.Name == fc.Name).FirstOrDefault();
                }
                if (fc.PropertyDescriptor == null)
                {
                    continue;
                }

                PIDict.Add(fc.PropertyDescriptor.Name, fc.PropertyDescriptor.ComponentType.GetProperty(fc.PropertyDescriptor.Name));
                PDDict.Add(fc.PropertyDescriptor.Name, fc.PropertyDescriptor);
            }

            RecordFieldConfigurationsDict = XmlRecordFieldConfigurations.OrderBy(c => c.IsXmlAttribute).Where(i => !i.Name.IsNullOrWhiteSpace()).ToDictionary(i => i.Name);

            if (XmlRecordFieldConfigurations.Where(e => e.IsNullable).Any() ||
                NullValueHandling == ChoNullValueHandling.Default)
            {
                if (NamespaceManager != null)
                {
                    if (!NamespaceManager.HasNamespace("xsi"))
                    {
                        NamespaceManager.AddNamespace("xsi", ChoXmlSettings.XmlSchemaInstanceNamespace);
                    }
                    if (!NamespaceManager.HasNamespace("xsd"))
                    {
                        NamespaceManager.AddNamespace("xsd", ChoXmlSettings.XmlSchemaNamespace);
                    }
                }
            }

            LoadNCacheMembers(XmlRecordFieldConfigurations);
        }