public override void MergeNodes([NotNull] XmlNode target, [NotNull] IXmlElement patch, [NotNull] XmlPatchNamespaces ns) { Assert.ArgumentNotNull(target, "target"); Assert.ArgumentNotNull(patch, "patch"); Assert.ArgumentNotNull(ns, "ns"); if (target.NamespaceURI != patch.NamespaceURI || target.LocalName != patch.LocalName) { return; } var exit = false; foreach (var attribute in patch.GetAttributes()) { if (exit) { continue; } if (attribute.NamespaceURI == RoleNamespace && !RoleConfigurationHelper.ProcessRolesNamespace(attribute)) { // we need to finish enumerating attributes to avoid reader problem exit = true; } } if (exit) { foreach (var node in patch.GetChildren()) { // we need to get children to avoid reader problem } return; } base.MergeNodes(target, patch, ns); }
protected override void MergeChildren(XmlNode target, IXmlElement patch, XmlPatchNamespaces ns, bool targetWasInserted) { Assert.ArgumentNotNull(target, "target"); Assert.ArgumentNotNull(patch, "patch"); Assert.ArgumentNotNull(ns, "ns"); var exit = false; string savedComment = null; var pendingOperations = new Stack <InsertOperation>(); // copy child nodes foreach (IXmlElement node in patch.GetChildren()) { if (exit) { continue; } if (node.NodeType == XmlNodeType.Text) { target.InnerText = node.Value; continue; } if (node.NodeType == XmlNodeType.Comment) { savedComment = node.Value; continue; } if (node.NodeType != XmlNodeType.Element) { continue; } if (node.NamespaceURI == ns.PatchNamespace) { ProcessConfigNode(target, node); continue; } var queryAttributes = new List <IXmlNode>(); var setAttributes = new List <IXmlNode>(); InsertOperation operation = null; foreach (IXmlNode attribute in node.GetAttributes()) { if (exit) { continue; } if (attribute.NamespaceURI == RoleNamespace) { if (!RoleConfigurationHelper.ProcessRolesNamespace(attribute)) { // we need to finish enumerating attributes to avoid reader problem exit = true; pendingOperations.Clear(); } continue; } if (attribute.NamespaceURI == ns.PatchNamespace) { switch (attribute.LocalName) { case "b": case "before": case "a": case "after": case "i": case "instead": operation = new InsertOperation { Reference = attribute.Value, Disposition = attribute.LocalName[0] }; break; } continue; } if (attribute.NamespaceURI == ns.SetNamespace) { setAttributes.Add(new XmlNodeInfo { NodeType = attribute.NodeType, NamespaceURI = string.Empty, // "set" NS translates into an empty NS LocalName = attribute.LocalName, Prefix = string.Empty, Value = attribute.Value }); continue; } if (attribute.Prefix != "xmlns") { queryAttributes.Add(new XmlNodeInfo { NodeType = attribute.NodeType, NamespaceURI = attribute.NamespaceURI, LocalName = attribute.LocalName, Prefix = attribute.Prefix, Value = attribute.Value }); } } if (exit) { continue; } var nsManager = new XmlNamespaceManager(new NameTable()); var predicateBuilder = new StringBuilder(); var added = false; foreach (var a in queryAttributes) { if (added) { predicateBuilder.Append(" and "); } if (a.Prefix != null && string.IsNullOrEmpty(nsManager.LookupPrefix(a.Prefix))) { nsManager.AddNamespace(a.Prefix, a.NamespaceURI); } predicateBuilder.Append("@" + MakeName(a.Prefix, a.LocalName) + "=\"" + a.Value + "\""); added = true; } if (node.Prefix != null && string.IsNullOrEmpty(nsManager.LookupPrefix(node.Prefix))) { nsManager.AddNamespace(node.Prefix, node.NamespaceURI); } XmlNode targetChild = null; bool created = false; if (!targetWasInserted) { string predicate = MakeName(node.Prefix, node.LocalName); var expression = predicateBuilder.ToString(); if (expression.Length > 0) { predicate = predicate + "[" + expression + "]"; } targetChild = target.SelectSingleNode(predicate, nsManager); } if (targetChild == null) { Assert.IsNotNull(target.OwnerDocument, "document"); targetChild = target.OwnerDocument.CreateElement(MakeName(node.Prefix, node.LocalName), node.NamespaceURI); created = true; if (!InsertChild(target, targetChild, operation) && operation != null) { operation.Node = targetChild; pendingOperations.Push(operation); } AssignAttributes(targetChild, queryAttributes); } else if (operation != null) { if (!InsertChild(target, targetChild, operation)) { operation.Node = targetChild; pendingOperations.Push(operation); } } if (savedComment != null) { Assert.IsNotNull(targetChild.OwnerDocument, "document"); XmlComment comment = targetChild.OwnerDocument.CreateComment(savedComment); Assert.IsNotNull(targetChild.ParentNode, "parent"); targetChild.ParentNode.InsertBefore(comment, targetChild); savedComment = null; } AssignAttributes(targetChild, setAttributes); MergeChildren(targetChild, node, ns, /*targetWasInserted = */ created); if ((created || setAttributes.Any()) && !targetWasInserted) { AssignSource(targetChild, node, ns); } } while (pendingOperations.Count > 0) { InsertOperation operation = pendingOperations.Pop(); Assert.IsNotNull(operation.Node.ParentNode, "parent"); InsertChild(operation.Node.ParentNode, operation.Node, operation); } }