public XmElementCollection Except(List <string> lExcept) { Dictionary <string, bool> dEx = new Dictionary <string, bool>(); if (lExcept != null) { foreach (string str in lExcept) { if (str != null) { dEx[str] = true; } else { Debug.Assert(false); } } } else { Debug.Assert(false); } XmElementCollection c = new XmElementCollection(); foreach (KeyValuePair <string, XmlElement> kvp in m_l) { if (!dEx.ContainsKey(kvp.Key)) { c.Add(kvp.Key, kvp.Value); } } return(c); }
public static XmElementCollection FromChildNodes(XmlElement xeParent, string strParentXPath, XmContext ctx) { XmElementCollection c = new XmElementCollection(); if (xeParent == null) { Debug.Assert(false); return(c); } if (strParentXPath == null) { Debug.Assert(false); return(c); } if (ctx == null) { Debug.Assert(false); return(c); } Dictionary <string, XmlElement> d = c.m_d; foreach (XmlNode xn in xeParent.ChildNodes) { XmlElement xe = (xn as XmlElement); if (xe == null) { continue; } string strNameC = xe.Name; string strXPathC = strParentXPath + "/" + strNameC; string strKeyCustomC = ctx.GetNodeKey(xe, strXPathC); string strKey = BuildNodeKey(strNameC, strKeyCustomC, 0); if (d.ContainsKey(strKey)) { // In general, custom node keys should be unique Debug.Assert(string.IsNullOrEmpty(strKeyCustomC)); for (int i = d.Count; i >= 0; --i) { string strKeyTest = BuildNodeKey(strNameC, strKeyCustomC, i); if (d.ContainsKey(strKeyTest)) { Debug.Assert(i != d.Count); // Key must change in first iteration break; } strKey = strKeyTest; } Debug.Assert(!d.ContainsKey(strKey)); } c.Add(strKey, xe); } return(c); }
internal static XmlElement MergeElements(XmlElement xeBase, XmlElement xeOverride, string strXPath, XmlElement xeBaseParent, XmContext ctx) { if (xeOverride == null) { throw new ArgumentNullException("xeOverride"); } if (strXPath == null) { throw new ArgumentNullException("strXPath"); } if (ctx == null) { throw new ArgumentNullException("ctx"); } string strName = xeOverride.Name; Debug.Assert((xeBase == null) || (xeBase.Name == strName)); Debug.Assert((strXPath == strName) || strXPath.EndsWith("/" + strName)); Debug.Assert((xeBase == null) || (xeBaseParent == null) || object.ReferenceEquals(xeBase.ParentNode, xeBaseParent)); XmNodeOptions o = GetNodeOptions(xeOverride, strXPath, ctx); bool bContinue = false; switch (o.NodeMode) { case XmNodeMode.None: break; case XmNodeMode.Create: if ((xeBase == null) && (xeBaseParent != null)) { xeBase = ctx.BaseDocument.CreateElement(strName); xeBaseParent.AppendChild(xeBase); bContinue = true; } break; case XmNodeMode.Open: if (xeBase != null) { bContinue = true; } break; case XmNodeMode.OpenOrCreate: if (xeBase != null) { bContinue = true; } else if (xeBaseParent != null) { xeBase = ctx.BaseDocument.CreateElement(strName); xeBaseParent.AppendChild(xeBase); bContinue = true; } break; case XmNodeMode.Remove: if (xeBase != null) { if (xeBaseParent != null) { xeBaseParent.RemoveChild(xeBase); xeBase = null; // Return value, indicate removal } else { // Cannot remove element; clear it instead xeBase.InnerXml = string.Empty; } } break; default: Debug.Assert(false); break; } if (!bContinue) { return(xeBase); } if (xeBase == null) { Debug.Assert(false); return(null); } XmContentMode cm = o.ContentMode; if ((cm == XmContentMode.Merge) && !HasChildElement(xeBase) && !HasChildElement(xeOverride)) { cm = XmContentMode.Replace; } XmElementCollection xcBase = null, xcOverride = null; if (cm == XmContentMode.Merge) { xcBase = XmElementCollection.FromChildNodes(xeBase, strXPath, ctx); xcOverride = XmElementCollection.FromChildNodes(xeOverride, strXPath, ctx); if (o.ChildrenOtherMode == XmChildrenOtherMode.Remove) { List <string> lRemove = new List <string>(); foreach (KeyValuePair <string, XmlElement> kvpBaseC in xcBase) { if (xcOverride[kvpBaseC.Key] == null) { xeBase.RemoveChild(kvpBaseC.Value); lRemove.Add(kvpBaseC.Key); } } // Do not simply rebuild xcBase, because indices in // node keys would change xcBase = xcBase.Except(lRemove); } } switch (cm) { case XmContentMode.None: Debug.Assert(false); break; // Currently unused case XmContentMode.Merge: foreach (KeyValuePair <string, XmlElement> kvpOverrideC in xcOverride) { string strKeyC = kvpOverrideC.Key; XmlElement xeBaseC = xcBase[strKeyC]; XmlElement xeOverrideC = kvpOverrideC.Value; string strXPathC = strXPath + "/" + xeOverrideC.Name; XmlElement xeBaseCNew = MergeElements(xeBaseC, xeOverrideC, strXPathC, xeBase, ctx); if (!object.ReferenceEquals(xeBaseCNew, xeBaseC)) { Debug.Assert((xeBaseCNew == null) || (xeBaseC == null)); if (xeBaseCNew == null) { xcBase.Remove(strKeyC); } else { xcBase.Add(strKeyC, xeBaseCNew); } } } break; case XmContentMode.Replace: xeBase.InnerXml = SafeInnerXml(xeOverride); break; default: Debug.Assert(false); break; } if ((cm == XmContentMode.Merge) && (o.ChildrenSortOrder == XmChildrenSortOrder.This)) { xcBase.SortBy(xcOverride); xcBase.ReorderElementsOf(xeBase); } return(xeBase); }