/// <summary> /// Parses parentXml and finds MapCommand and ReadCommand objects that should be added to the parent container. /// </summary> private static void DeserializeMappings(MappingConfiguration config, MappingContainer parent, XmlReader parentXml) { int currentDepth = parentXml.Depth; string currentName = parentXml.Name; while (parentXml.Read()) { // This is the exit condition if (parentXml.NodeType == XmlNodeType.EndElement && parentXml.Name == currentName && parentXml.Depth == currentDepth) { break; } else if (parentXml.NodeType == XmlNodeType.Text) { throw new MappingConfigurationException(String.Format("<{0}> is not allowed here.", parentXml.Name), parentXml); } else if (parentXml.NodeType == XmlNodeType.Element) { // Just an alias to make a distinction XmlReader element = parentXml; // If a field is specified, create a read command (implicit or explicit) ReadCommand read = null; string field = element.GetAttribute("Field"); // Check if mapping command is required bool required = true; bool requiredAlert = false; string srequired = element.GetAttribute("Required"); string srequiredAlert = element.GetAttribute("RequiredAlert"); if (srequired != null && !bool.TryParse(srequired, out required)) { throw new MappingConfigurationException("Invalid value for Required.", element.Name, element); } if (srequiredAlert != null && !bool.TryParse(srequiredAlert, out requiredAlert)) { throw new MappingConfigurationException("Invalid value for requiredAlert.", element.Name, element); } if (field != null) { read = new ReadCommand() { Field = field, VarName = element.GetAttribute("Var") ?? field, RegexPattern = element.GetAttribute("Regex"), IsRequired = required, IsRequiredAlert = requiredAlert }; } if (element.Name == "Read") { // Field is required for an explicit read command if (read == null) { throw new MappingConfigurationException("Missing 'Field' attribute.", "Read", element); } // Register it as a read command parent.ReadCommands.Add(read); // Add the command to the parent's inherited list, so that child map commands inherit it also parent.InheritedReads[read.VarName] = read; } else if (element.Name == "Map") { // Handle mappings string to = element.GetAttribute("To"); if (to == null) { throw new MappingConfigurationException("Missing 'To' attribute.", "Map", element); } if (read != null) { read.IsImplicit = true; } MapCommand map = MapCommand.CreateChild(parent, to, element, read, returnInnermost: true); // Force parent to re-inherit, and then inherit from it map.Inherit(); map.IsRequired = required; // Condition string condition = element.GetAttribute("Condition"); if (condition != null) { map.Condition = new EvalComponent(map, condition, element); } // Handle value expressions string valueFormat = element.GetAttribute("Value"); try { if (valueFormat != null) { map.Value = new ValueFormat(map, valueFormat, element); } else { if (read != null) { map.Value = new ValueFormat(map, "{" + read.VarName + "}", element); } } } catch (MappingConfigurationException ex) { throw new MappingConfigurationException(ex.Message, "Map", element, ex); } // Recursively add child nodes if (!element.IsEmptyElement) { DeserializeMappings(config, map, element); } } else { throw new MappingConfigurationException(String.Format("Element '{0}' is not allowed here.", parentXml.Name), parentXml); } } } }
/// <summary> /// Combines the current configuration with the specified configuration, overriding any conflicting mappings. /// </summary> /// <param name="otherConfig">Mappings with which to extend the current configuration.</param> public void Extend(MappingConfiguration otherConfig) { foreach (MappingContainer objectMappings in otherConfig.Objects.Values) { } }