private void AddChildren(Collection<SPWebConfigModification> collection, XmlNode node, SPWebConfigModification mod)
{
string name = GetAttributeString(node);
mod = new SPWebConfigModification(node.Name, GetOuterPath(node.ParentNode));
if (node.HasChildNodes)
{
mod.Value = mod.Name;
mod.Type = SPWebConfigModification.SPWebConfigModificationType.EnsureSection;
}
else
{
mod.Name += name;
mod.Value = string.IsNullOrEmpty(node.InnerXml) ? node.OuterXml : node.OuterXml.Replace(node.InnerXml, "");
mod.Type = SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode;
}
mod.Owner = _modificationOwner;
mod.Sequence = ++_seq;
collection.Add(mod);
if (node.HasChildNodes)
foreach (XmlNode childNode in node.ChildNodes)
if (childNode.NodeType != XmlNodeType.Comment)
AddChildren(collection, childNode, mod);
}
And just so you know what they do, here are the smaller, supporting functions:
private string GetOuterPath(XmlNode node)
{
if (node.ParentNode == null)
return "/";
else if (node.ParentNode.NodeType == XmlNodeType.Document)
return node.Name + GetAttributeString(node);
return GetOuterPath(node.ParentNode) + "/" + node.Name + GetAttributeString(node);
}
private string GetAttributeString(XmlNode node)
{
StringBuilder sb = new StringBuilder();
foreach (XmlAttribute at in node.Attributes)
sb.Append(string.Format("[@{0}='{1}']", at.Name, at.Value));
return sb.ToString();
}
I wrote it in a way that each node that has child nodes would generate a SPWebConfigModification with its type as EnsureSection. I ran into a problem when you have sections that have attributes. The Name property of a SPWebConfigModification whose type is EnsureSection cannot contain any non-alphanumeric characters (so no ‘[‘ or ‘=’ in there, like you’d expect in XPath). For example, consider this fragment of XML:
<configuration>
<location path="_some/path/here">
<system.web>
<identity impersonate="false" />
</system.web>
</location>
</configuration>
There are problems with this code, which I'll talk about in Part 4!