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