private void Merge(XmlModelCommand newCommand)
 {
     // Some commands have to be merged (for example if the name or value of the same
     // node is changed twice) because the SourceModifier is not designed to update 
     // stuff it just inserted into the buffer during the same transaction.
     List<XmlModelCommand> toRemove = null;
     foreach (var cmd in txCommands)
     {
         if (newCommand != cmd
             && newCommand.Merge(cmd))
         {
             if (toRemove == null)
             {
                 toRemove = new List<XmlModelCommand>();
             }
             toRemove.Add(cmd);
         }
     }
     RemoveRange(txCommands, toRemove);
     // And remove this from undo list also, since we have edited the same command objects!
     RemoveRange(undoCommands, toRemove);
 }
        internal void AddCommand(XmlModelCommand cmd)
        {
            var change = cmd.Change;
            var node = change.Node;

            if (change.Action == XObjectChange.Remove)
            {
                // If we are removing a node, then all changes to any descendent of this node
                // can be discarded since the whole thing will be ripped out of the buffer anyway.
                var rs = RemoveAllDescendentChanges(change);
                if (rs == RemoveStatus.FoundSelfAdd)
                {
                    /*
                     * 9/21/2007 - not sure what to do about the stuff below.  Seems specific to the editor
                     * so commenting it out.
                     * 
                    // then this remove is a no-op, unless the Add operation is one of those
                    // special ones where the buffer already contained the value - in this case
                    // the Remove operation is real, and the add operation is a no-op, otherwise
                    // they both cancel each other out.
                    string bufferValue = XmlEditorNoPushToBuffer(change.Node);
                    if (bufferValue == null) {
                        return;
                    }
                     */
                }
            }
            if (IsAncestorAdded(node, change.Parent))
            {
                // If the ancestor was added by this transaction, then we can ignore the child
                // command because the XLink insert will insert the entire thing into the buffer
                // including all changes already made by the child transaction.
                return;
            }

            switch (change.Action)
            {
                case XObjectChange.Add:
                    AddNode(node); // record the add operation.
                    break;
                case XObjectChange.Name:
                    Merge(cmd);
                    // Name changes must be done first, because an Add operation might 
                    // cause a short end tag <A/> to be converted to <A></A>, and then
                    // a rename after that of the same node would result in two edit 
                    // operations on the same end tag which is not supported by SourceModifier.
                    undoCommands.Insert(0, cmd);
                    txCommands.Insert(0, cmd);
                    return;
                case XObjectChange.Value:
                    Merge(cmd);
                    break;
                case XObjectChange.Remove:
                    break;
            }

            txCommands.Add(cmd);
        }