/// <summary> /// Check for and convert inline XML dynamic value notation into <see cref="IDynamicValue"/> definitions. /// </summary> /// <param name="typeTable">The type table.</param> /// <param name="inputNode">The node to process.</param> /// <param name="exclusions">Any elements to exclude.</param> /// <returns></returns> public static XmlNode ConvertXmlToDynamicValues(NetReflectorTypeTable typeTable, XmlNode inputNode, params string[] exclusions) { var resultNode = inputNode; var doc = inputNode.OwnerDocument; var parameters = new List<XmlElement>(); // Initialise the values from the reflection var inputMembers = new Dictionary<string, XmlMemberSerialiser>(); buildMembers(ref inputMembers, typeTable, inputNode); var nodes = inputNode.SelectNodes("descendant::text()|descendant-or-self::*[@*]/@*"); foreach (XmlNode nodeWithParam in nodes) { var text = nodeWithParam.Value; var isExcluded = CheckForExclusion(nodeWithParam, exclusions); if (!isExcluded && parameterRegex.Match(text).Success) { // Generate the format string var parametersEl = doc.CreateElement("parameters"); var index = 0; var lastReplacement = string.Empty; var format = parameterRegex.Replace(text, (match) => { // Split into it's component parts var parts = paramPartRegex.Split(match.Value.Substring(2, match.Value.Length - 3)); // Generate the value element var dynamicValueEl = doc.CreateElement("namedValue"); dynamicValueEl.SetAttribute("name", parts[0].Replace("\\|", "|")); if (parts.Length > 1) { dynamicValueEl.SetAttribute("value", parts[1].Replace("\\|", "|")); } parametersEl.AppendChild(dynamicValueEl); // Generate the replacement lastReplacement = string.Format(CultureInfo.CurrentCulture, "{{{0}{1}}}", index++, parts.Length > 2 ? ":" + parts[2].Replace("\\|", "|") : string.Empty); return lastReplacement; }); // Generate the dynamic value element var replacementValue = string.Empty; XmlElement replacementEl; if (lastReplacement != format) { replacementEl = doc.CreateElement("replacementValue"); AddElement(replacementEl, "format", format); replacementEl.AppendChild(parametersEl); } else { replacementEl = doc.CreateElement("directValue"); AddElement(replacementEl, "parameter", parametersEl.SelectSingleNode("namedValue/@name").InnerText); var innerValue = parametersEl.SelectSingleNode("namedValue/@value"); if (innerValue != null) { replacementValue = innerValue.InnerText; AddElement(replacementEl, "default", replacementValue); } } parameters.Add(replacementEl); // Generate the path var propertyName = new StringBuilder(); var currentNode = nodeWithParam is XmlAttribute ? nodeWithParam : nodeWithParam.ParentNode; var previousNode = currentNode; var lastName = string.Empty; bool hasDynamicValues = false; while ((currentNode != null) && (currentNode.NodeType != XmlNodeType.Document)) { var nodeName = currentNode.Name; var currentNodeType = typeTable.ContainsType(nodeName) ? typeTable[nodeName] : null; if (currentNodeType != null) { hasDynamicValues = currentNodeType.Type. GetInterface(typeof(IWithDynamicValuesItem).Name) != null; if (hasDynamicValues) break; } // we don't want to take into account the input node, but we need to know if it has // dynamic values, hence the break here and not in the while loop if (currentNode == inputNode) break; // Check if we are dealing with an array if (inputMembers.ContainsKey(nodeName) && inputMembers[nodeName].ReflectorMember.MemberType.IsArray) { // Do some convoluted processing to handle array items propertyName.Remove(0, lastName.Length + 1); // Remove the previous name, since this is now an index position var position = 0; var indexNode = previousNode; // Find the index of the node while (indexNode.PreviousSibling != null) { if (indexNode.NodeType != XmlNodeType.Comment) position++; indexNode = indexNode.PreviousSibling; } // Add the node as an indexed node propertyName.Insert(0, "." + nodeName + "[" + position.ToString(CultureInfo.CurrentCulture) + "]"); } else { // Just add the node name propertyName.Insert(0, "." + nodeName); } // Move to the parent lastName = nodeName; previousNode = currentNode; currentNode = getParentNode(currentNode); } propertyName.Remove(0, 1); AddElement(replacementEl, "property", propertyName.ToString()); // Set a replacement value nodeWithParam.Value = replacementValue; // add the parameters already there if the current node has dynamic values if (hasDynamicValues) addParameters(ref parameters, currentNode); } } // Add the remaining parameters to the root element addParameters(ref parameters, inputNode); return resultNode; }
private static void buildImputMembers(ref Dictionary<string, XmlMemberSerialiser> inputMembers, NetReflectorTypeTable typeTable, XmlNode inputNode) { var inputNodeType = typeTable.ContainsType(inputNode.Name) ? typeTable[inputNode.Name] : null; if (inputNodeType != null) { foreach (XmlMemberSerialiser value in inputNodeType.MemberSerialisers) { if (value != null) { if (!inputMembers.ContainsKey(value.Attribute.Name)) inputMembers.Add(value.Attribute.Name, value); } } } foreach (XmlNode childNode in inputNode.ChildNodes) { buildImputMembers(ref inputMembers, typeTable, childNode); } }
private static void buildMembers(ref Dictionary<string, XmlMemberSerialiser> members, NetReflectorTypeTable typeTable, XmlNode node) { if (node == null) return; var nodeType = typeTable.ContainsType(node.Name) ? typeTable[node.Name] : null; if (nodeType != null) { foreach (XmlMemberSerialiser value in nodeType.MemberSerialisers) { if (value != null) { if (!members.ContainsKey(value.Attribute.Name)) members.Add(value.Attribute.Name, value); } } } foreach (XmlNode childNode in node.ChildNodes) { buildMembers(ref members, typeTable, childNode); } }
/// <summary> /// Check for and convert inline XML dynamic value notation into <see cref="IDynamicValue"/> definitions. /// </summary> /// <param name="typeTable">The type table.</param> /// <param name="inputNode">The node to process.</param> /// <param name="exclusions">Any elements to exclude.</param> /// <returns></returns> public static XmlNode ConvertXmlToDynamicValues(NetReflectorTypeTable typeTable, XmlNode inputNode, params string[] exclusions) { var resultNode = inputNode; var doc = inputNode.OwnerDocument; var parameters = new List<XmlElement>(); // Initialise the values from the reflection var inputNodeType = typeTable.ContainsType(inputNode.Name) ? typeTable[inputNode.Name] : null; var inputMembers = new Dictionary<string, XmlMemberSerialiser>(); if (inputNodeType != null) { foreach (XmlMemberSerialiser value in inputNodeType.MemberSerialisers) { if (value != null) { inputMembers.Add(value.Attribute.Name, value); } } } var nodes = inputNode.SelectNodes("descendant::text()|descendant-or-self::*[@*]/@*"); foreach (XmlNode nodeWithParam in nodes) { var text = nodeWithParam.Value; var isExcluded = CheckForExclusion(nodeWithParam, exclusions); if (!isExcluded && parameterRegex.Match(text).Success) { // Generate the format string var parametersEl = doc.CreateElement("parameters"); var index = 0; var lastReplacement = string.Empty; var format = parameterRegex.Replace(text, (match) => { // Split into it's component parts var parts = paramPartRegex.Split(match.Value.Substring(2, match.Value.Length - 3)); // Generate the value element var dynamicValueEl = doc.CreateElement("namedValue"); dynamicValueEl.SetAttribute("name", parts[0].Replace("\\|", "|")); if (parts.Length > 1) { dynamicValueEl.SetAttribute("value", parts[1].Replace("\\|", "|")); } parametersEl.AppendChild(dynamicValueEl); // Generate the replacement lastReplacement = string.Format("{{{0}{1}}}", index++, parts.Length > 2 ? ":" + parts[2].Replace("\\|", "|") : string.Empty); return lastReplacement; }); // Generate the dynamic value element var replacementValue = string.Empty; XmlElement replacementEl; if (lastReplacement != format) { replacementEl = doc.CreateElement("replacementValue"); AddElement(replacementEl, "format", format); replacementEl.AppendChild(parametersEl); } else { replacementEl = doc.CreateElement("directValue"); AddElement(replacementEl, "parameter", parametersEl.SelectSingleNode("namedValue/@name").InnerText); var innerValue = parametersEl.SelectSingleNode("namedValue/@value"); if (innerValue != null) { replacementValue = innerValue.InnerText; AddElement(replacementEl, "default", replacementValue); } } parameters.Add(replacementEl); // Generate the path var propertyName = new StringBuilder(); var currentNode = nodeWithParam is XmlAttribute ? nodeWithParam : nodeWithParam.ParentNode; var previousNode = currentNode; var lastName = string.Empty; while ((currentNode != inputNode) && (currentNode != null)) { // Check if we are dealing with an array var nodeName = currentNode.Name; if (inputMembers.ContainsKey(nodeName) && inputMembers[nodeName].ReflectorMember.MemberType.IsArray) { // Do some convoluted processing to handle array items propertyName.Remove(0, lastName.Length + 1); // Remove the previous name, since this is now an index position var position = 0; var indexNode = previousNode; // Find the index of the node while (indexNode.PreviousSibling != null) { position++; indexNode = indexNode.PreviousSibling; } // Add the node as an indexed node propertyName.Insert(0, "." + nodeName + "[" + position.ToString() + "]"); } else { // Just add the node name propertyName.Insert(0, "." + nodeName); } // Move to the parent lastName = nodeName; previousNode = currentNode; if (currentNode is XmlAttribute) { currentNode = (currentNode as XmlAttribute).OwnerElement; } else { currentNode = currentNode.ParentNode; } } propertyName.Remove(0, 1); AddElement(replacementEl, "property", propertyName.ToString()); // Set a replacement value nodeWithParam.Value = replacementValue; } } // Add the parameters to the element if (parameters.Count > 0) { var parametersEl = inputNode.SelectSingleNode("dynamicValues"); if (parametersEl == null) { parametersEl = doc.CreateElement("dynamicValues"); inputNode.AppendChild(parametersEl); } foreach (var element in parameters) { parametersEl.AppendChild(element); } } return resultNode; }