/// <summary> /// Initializes a new instance of the <see cref="XmlParserContext"/> class. /// </summary> /// <param name="parserSettings">Parser settings.</param> /// <param name="schema">Schema to use for parsing.</param> /// <param name="messages">Optional message list.</param> /// <param name="parsersCache">Optional parsers cache.</param> /// <param name="schemaCache">Optional schemas cache.</param> /// <param name="validatorsCache">Optional validators cache.</param> public XmlParserContext( IXmlParserSettings parserSettings, ISchema?schema, IMutableMessageList <Message>?messages = null, ConcurrentDictionary <IProperty, IValueParser>?parsersCache = null, ConcurrentDictionary <IProperty, ISchema>?schemaCache = null, ConcurrentDictionary <IProperty, IPropertyValidationRules>?validatorsCache = null) { parserSettings.AssertArgumentNotNull(nameof(parserSettings)); ParserSettings = parserSettings; Schema = schema ?? new MutableObjectSchema(); Messages = messages ?? new MutableMessageList <Message>(); ParsersCache = parsersCache ?? new ConcurrentDictionary <IProperty, IValueParser>(comparer: parserSettings.PropertyComparer); SchemaCache = schemaCache ?? new ConcurrentDictionary <IProperty, ISchema>(comparer: parserSettings.PropertyComparer); ValidatorsCache = validatorsCache ?? new ConcurrentDictionary <IProperty, IPropertyValidationRules>(comparer: parserSettings.PropertyComparer); }
private static IPropertyContainer?ParseXmlElement( XElement objectElement, IObjectSchema objectSchema, IXmlParserSettings settings, IXmlParserContext context, IMutablePropertyContainer?container = null) { if (objectElement.HasElements) { container ??= new MutablePropertyContainer(); foreach (XElement propertyElement in objectElement.Elements()) { string elementName = settings.GetElementName(propertyElement); string propertyName = settings.StringProvider.GetString(elementName); IProperty?property = objectSchema.GetProperty(propertyName); if (propertyElement.HasElements) { IObjectSchema propertyInternalSchema = context.GetOrCreateNewSchemaCached(property).ToObjectSchema(); IPropertyContainer?internalObject = ParseXmlElement(propertyElement, propertyInternalSchema, settings, context); if (internalObject != null && internalObject.Count > 0) { if (settings.SetSchemaForObjects) { internalObject.SetSchema(propertyInternalSchema); } if (property == null) { property = new Property <IPropertyContainer>(propertyName) .SetIsNotFromSchema() .SetSchema(propertyInternalSchema); if (objectSchema is IMutableObjectSchema mutableObjectSchema) { property = mutableObjectSchema.AddProperty(property); } } IPropertyValue propertyValue = settings.PropertyValueFactory.CreateUntyped(property, internalObject); container.Add(propertyValue); // Validate property. if (settings.ValidateOnParse) { ValidateProperty(context, container, property, propertyElement); } } } else { if (property != null && property.Type == typeof(IPropertyContainer)) { // Composite object, no value. bool isNullAllowed = property.GetOrEvaluateNullability().IsNullAllowed; if (!isNullAllowed) { context.Messages.AddError( $"Property '{property.Name}' can not be null but xml element has no value.{GetXmlLineInfo(propertyElement)}"); } continue; } if (property == null) { property = new Property <string>(propertyName) .SetIsNotFromSchema(); if (objectSchema is IMutableObjectSchema mutableObjectSchema) { property = mutableObjectSchema.AddProperty(property); } } IValueParser valueParser = context.GetParserCached(property); if (valueParser != EmptyParser.Instance) { string elementValue = propertyElement.Value; // Parse value. IParseResult parseResult = valueParser.ParseUntyped(elementValue); if (parseResult.IsSuccess) { // Add property to container. object? parsedValue = parseResult.ValueUntyped; IPropertyValue propertyValue = settings.PropertyValueFactory.CreateUntyped(property, parsedValue); container.Add(propertyValue); // Validate property. if (settings.ValidateOnParse) { ValidateProperty(context, container, property, propertyElement); } } else { string?parseResultErrorMessage = parseResult.Error?.FormattedMessage; string parseResultError = parseResultErrorMessage != null ? $" Error: '{parseResultErrorMessage}'." : string.Empty; string errorMessage = $"Property '{property.Name}' failed to parse from string '{elementValue}'.{parseResultError}{GetXmlLineInfo(propertyElement)}"; context.Messages.AddError(errorMessage); } } else { string errorMessage = $"Property '{property.Name}' can not be parsed because no parser found for type {property.Type}.{GetXmlLineInfo(propertyElement)}"; context.Messages.AddError(errorMessage); } } } return(container); } return(null); }