internal ChoXmlRecordFieldConfiguration(string name, ChoXmlNodeRecordFieldAttribute attr = null) : base(name, attr) { FieldName = name; UseCache = true; if (attr != null) { XPath = attr.XPath; FieldName = attr.FieldName.IsNullOrWhiteSpace() ? Name.NTrim() : attr.FieldName.NTrim(); IsXmlAttribute = attr is ChoXmlAttributeRecordFieldAttribute; } }
internal ChoXmlRecordFieldConfiguration(string name, ChoXmlNodeRecordFieldAttribute attr = null, Attribute[] otherAttrs = null) : base(name, attr, otherAttrs) { EncodeValue = true; FieldName = name; if (attr != null) { XPath = attr.XPath; EncodeValue = attr.EncodeValue; UseXmlSerialization = attr.UseXmlSerialization; FieldName = attr.FieldName.IsNullOrWhiteSpace() ? Name.NTrim() : attr.FieldName.NTrim(); IsXmlAttribute = attr is ChoXmlAttributeRecordFieldAttribute; } }
internal ChoXmlRecordFieldConfiguration GetFieldConfiguration(string propertyName, ChoXmlNodeRecordFieldAttribute attr = null, Attribute[] otherAttrs = null) { if (!XmlRecordFieldConfigurations.Any(fc => fc.Name == propertyName)) { XmlRecordFieldConfigurations.Add(new ChoXmlRecordFieldConfiguration(propertyName, attr, otherAttrs)); } return(XmlRecordFieldConfigurations.First(fc => fc.Name == propertyName)); }
private void DiscoverRecordFields(Type recordType, string declaringMember, bool optIn = false) { if (recordType == null) { return; } if (!recordType.IsDynamicType()) { IsComplexXPathUsed = false; Type pt = null; if (optIn) //ChoTypeDescriptor.GetProperties(recordType).Where(pd => pd.Attributes.OfType<ChoXmlNodeRecordFieldAttribute>().Any()).Any()) { foreach (PropertyDescriptor pd in ChoTypeDescriptor.GetProperties(recordType)) { pt = pd.PropertyType.GetUnderlyingType(); var fa = pd.Attributes.OfType <ChoXmlNodeRecordFieldAttribute>().FirstOrDefault(); bool optIn1 = fa == null || fa.UseXmlSerialization ? optIn : ChoTypeDescriptor.GetProperties(pt).Where(pd1 => pd1.Attributes.OfType <ChoXmlNodeRecordFieldAttribute>().Any()).Any(); if (false) //optIn1 && !pt.IsSimple() && !typeof(IEnumerable).IsAssignableFrom(pt)) { DiscoverRecordFields(pt, declaringMember == null ? pd.Name : "{0}.{1}".FormatString(declaringMember, pd.Name), optIn1); } else if (pd.Attributes.OfType <ChoXmlNodeRecordFieldAttribute>().Any()) { bool useCache = true; string xpath = null; ChoXmlNodeRecordFieldAttribute attr = ChoTypeDescriptor.GetPropetyAttribute <ChoXmlNodeRecordFieldAttribute>(pd); if (attr.XPath.IsNullOrEmpty()) { if (!attr.FieldName.IsNullOrWhiteSpace()) { attr.XPath = $"/{attr.FieldName}|/@{attr.FieldName}"; } else { attr.XPath = xpath = $"/{pd.Name}|/@{pd.Name}"; } IsComplexXPathUsed = true; } else { useCache = false; } var obj = new ChoXmlRecordFieldConfiguration(pd.Name, attr, pd.Attributes.OfType <Attribute>().ToArray()); obj.FieldType = pt; obj.PropertyDescriptor = pd; obj.DeclaringMember = declaringMember == null ? null : "{0}.{1}".FormatString(declaringMember, pd.Name); obj.UseCache = useCache; if (obj.XPath.IsNullOrWhiteSpace()) { if (!obj.FieldName.IsNullOrWhiteSpace()) { obj.XPath = $"/{obj.FieldName}|/@{obj.FieldName}"; } else { obj.XPath = $"/{obj.Name}|/@{obj.Name}"; } } obj.FieldType = pd.PropertyType.GetUnderlyingType(); if (!XmlRecordFieldConfigurations.Any(c => c.Name == pd.Name)) { XmlRecordFieldConfigurations.Add(obj); } } } } else { foreach (PropertyDescriptor pd in ChoTypeDescriptor.GetProperties(recordType)) { XmlIgnoreAttribute xiAttr = pd.Attributes.OfType <XmlIgnoreAttribute>().FirstOrDefault(); if (xiAttr != null) { continue; } pt = pd.PropertyType.GetUnderlyingType(); if (false) //pt != typeof(object) && !pt.IsSimple() && !typeof(IEnumerable).IsAssignableFrom(pt)) { DiscoverRecordFields(pt, declaringMember == null ? pd.Name : "{0}.{1}".FormatString(declaringMember, pd.Name), optIn); } else { var obj = new ChoXmlRecordFieldConfiguration(pd.Name, $"/{pd.Name}|/@{pd.Name}"); obj.FieldType = pt; obj.PropertyDescriptor = pd; obj.DeclaringMember = declaringMember == null ? null : "{0}.{1}".FormatString(declaringMember, pd.Name); StringLengthAttribute slAttr = pd.Attributes.OfType <StringLengthAttribute>().FirstOrDefault(); if (slAttr != null && slAttr.MaximumLength > 0) { obj.Size = slAttr.MaximumLength; } XmlElementAttribute xAttr = pd.Attributes.OfType <XmlElementAttribute>().FirstOrDefault(); if (xAttr != null && !xAttr.ElementName.IsNullOrWhiteSpace()) { obj.FieldName = xAttr.ElementName; } else { XmlAttributeAttribute xaAttr = pd.Attributes.OfType <XmlAttributeAttribute>().FirstOrDefault(); if (xAttr != null && !xaAttr.AttributeName.IsNullOrWhiteSpace()) { obj.FieldName = xaAttr.AttributeName; } else { DisplayNameAttribute dnAttr = pd.Attributes.OfType <DisplayNameAttribute>().FirstOrDefault(); if (dnAttr != null && !dnAttr.DisplayName.IsNullOrWhiteSpace()) { obj.FieldName = dnAttr.DisplayName.Trim(); } else { DisplayAttribute dpAttr = pd.Attributes.OfType <DisplayAttribute>().FirstOrDefault(); if (dpAttr != null) { if (!dpAttr.ShortName.IsNullOrWhiteSpace()) { obj.FieldName = dpAttr.ShortName; } else if (!dpAttr.Name.IsNullOrWhiteSpace()) { obj.FieldName = dpAttr.Name; } } } } } DisplayFormatAttribute dfAttr = pd.Attributes.OfType <DisplayFormatAttribute>().FirstOrDefault(); if (dfAttr != null && !dfAttr.DataFormatString.IsNullOrWhiteSpace()) { obj.FormatText = dfAttr.DataFormatString; } if (dfAttr != null && !dfAttr.NullDisplayText.IsNullOrWhiteSpace()) { obj.NullValue = dfAttr.NullDisplayText; } if (!XmlRecordFieldConfigurations.Any(c => c.Name == pd.Name)) { XmlRecordFieldConfigurations.Add(obj); } } } } } }
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); }