private void OnRemove( DiffgramParentOperation parent )
        {
            EditScriptRemove remOp = _editScript as EditScriptRemove;

            Debug.Assert( remOp._endSourceIndex == _curSourceIndex );
            XmlDiffNode sourceRoot = _sourceNodes[ remOp._endSourceIndex ];

            // remove subtree or leaf node and no descendant node matches (=has been moved somewhere else)
            if ( remOp._startSourceIndex <= sourceRoot.Left )
            {
            bool bShrankNode = sourceRoot is XmlDiffShrankNode;

            if ( sourceRoot._bSomeDescendantMatches && !bShrankNode )
            {
                DiffgramOperation newDiffOp = GenerateDiffgramRemoveWhenDescendantMatches( (XmlDiffParentNode)sourceRoot );
                if ( _bBuildingAddTree )
                {
                    PostponedOperation( newDiffOp, sourceRoot.Left, remOp._endSourceIndex );
                }
                else
                {
                    parent.InsertAtBeginning( newDiffOp );
                }
            }
            else
            {
                ulong opid = 0;
                // shrank node -> output as 'move' operation
                if ( bShrankNode )
                {
                    XmlDiffShrankNode shrankNode = (XmlDiffShrankNode) sourceRoot;
                    if ( shrankNode.MoveOperationId == 0 )
                        shrankNode.MoveOperationId = GenerateOperationID( XmlDiffDescriptorType.Move );
                    opid = shrankNode.MoveOperationId;

                    Debug.Assert( sourceRoot == _sourceNodes[ sourceRoot.Left ] );
                }

                // insert 'remove' operation
                if ( _bBuildingAddTree )
                {
                    PostponedRemoveSubtrees( sourceRoot, opid,
                    //AddToPosponedOperations( new DiffgramRemoveSubtrees( sourceRoot, opid ),
                        sourceRoot.Left, remOp._endSourceIndex );
                }
                else
                {
                    if ( opid != 0 ||
                        !parent.MergeRemoveSubtreeAtBeginning( sourceRoot ) )
                    {
                        parent.InsertAtBeginning( new DiffgramRemoveSubtrees( sourceRoot, opid, !_xmlDiff.IgnoreChildOrder ) );
                    }
                }
            }

            // adjust current position
            _curSourceIndex = sourceRoot.Left - 1;

            // adjust boundaries in the edit script or move to next edit script operation
            remOp._endSourceIndex = sourceRoot.Left - 1;
            if ( remOp._startSourceIndex > remOp._endSourceIndex )
                _editScript = _editScript._nextEditScript;
            }
            // remove single but non-leaf node or some descendant matches (=has been moved somewhere else)
            // -> recursively process diffgram subtree
            else
            {
            Debug.Assert( !( sourceRoot is XmlDiffShrankNode) );

            // adjust current position
            _curSourceIndex--;

            // adjust boundaries in the edit script or move to next edit script operation
            remOp._endSourceIndex--;
            if ( remOp._startSourceIndex > remOp._endSourceIndex )
                _editScript = _editScript._nextEditScript;

            bool bRemoveSubtree = sourceRoot.NodeType != XmlDiffNodeType.Element;

            if ( _bBuildingAddTree )
            {
                // add 'remove' to postponed operations
                PostponedRemoveNode( sourceRoot, bRemoveSubtree, 0,
                //AddToPosponedOperations( new DiffgramRemoveNode( sourceRoot, bRemoveSubtree, 0 ),
                    remOp._endSourceIndex + 1, remOp._endSourceIndex + 1 );

                // recursively parse subtree
                GenerateDiffgramAdd( parent, sourceRoot.Left, _targetNodes[ _curTargetIndex ].Left );
            }
            else
            {
                // 'remove' operation
                DiffgramRemoveNode remNode = new DiffgramRemoveNode( sourceRoot, bRemoveSubtree, 0 );

                // parse subtree
                GenerateDiffgramMatch( remNode, sourceRoot.Left, _targetNodes[ _curTargetIndex ].Left );

                parent.InsertAtBeginning( remNode );
            }
            }
        }
        private DiffgramOperation GenerateDiffgramRemoveWhenDescendantMatches( XmlDiffNode sourceParent )
        {
            Debug.Assert( sourceParent._bSomeDescendantMatches );
            Debug.Assert( sourceParent.NodeType != XmlDiffNodeType.ShrankNode );

            DiffgramParentOperation diffOp = new DiffgramRemoveNode( sourceParent, false, 0 );
            XmlDiffNode child = ((XmlDiffParentNode)sourceParent)._firstChildNode;
            while ( child != null )
            {
            if ( child.NodeType == XmlDiffNodeType.ShrankNode )
            {
                XmlDiffShrankNode shrankNode = (XmlDiffShrankNode) child;

                if ( shrankNode.MoveOperationId == 0 )
                    shrankNode.MoveOperationId = GenerateOperationID( XmlDiffDescriptorType.Move );

                diffOp.InsertAtEnd( new DiffgramRemoveSubtrees( child, shrankNode.MoveOperationId, !_xmlDiff.IgnoreChildOrder ) );

            }
            else if ( child.HasChildNodes && child._bSomeDescendantMatches )
            {
                diffOp.InsertAtEnd( GenerateDiffgramRemoveWhenDescendantMatches( (XmlDiffParentNode)child ) );
            }
            else
            {
                if ( !diffOp.MergeRemoveSubtreeAtEnd( child ) )
                    diffOp.InsertAtEnd( new DiffgramRemoveSubtrees( child, 0, !_xmlDiff.IgnoreChildOrder ) );
            }

            child = child._nextSibling;
            }
            return diffOp;
        }