private void OnRemove(XmlElement diffgramElement, XmlDiffPathNodeList matchNodes,
                              XmlDiffViewParentNode sourceParent, ref XmlDiffViewNode currentPosition)
        {
            // opid & descriptor
            XmlDiffViewOperation op = XmlDiffViewOperation.Remove;
            int opid = 0;
            OperationDescriptor opDesc = null;

            string opidAttr = diffgramElement.GetAttribute("opid");

            if (opidAttr != string.Empty)
            {
                opid   = int.Parse(opidAttr);
                opDesc = GetDescriptor(opid);
                if (opDesc._type == OperationDescriptor.Type.Move)
                {
                    op = XmlDiffViewOperation.MoveFrom;
                }
            }

            // subtree
            string subtreeAttr = diffgramElement.GetAttribute("subtree");
            bool   bSubtree    = (subtreeAttr != "no");

            if (!bSubtree)
            {
                if (matchNodes.Count != 1)
                {
                    throw new Exception("The 'match' attribute of 'remove' element must select a single node when the 'subtree' attribute is specified.");
                }
                // annotate node
                matchNodes.MoveNext();
                XmlDiffViewNode node = matchNodes.Current;
                AnnotateNode(node, op, opid, false);
                if (opid != 0)
                {
                    opDesc._nodeList.AddNode(node);
                }

                // recurse
                ApplyDiffgram(diffgramElement, (XmlDiffViewParentNode)node);
            }
            else
            {
                // annotate nodes
                matchNodes.Reset();
                while (matchNodes.MoveNext())
                {
                    if (opid != 0)
                    {
                        opDesc._nodeList.AddNode(matchNodes.Current);
                    }
                    AnnotateNode(matchNodes.Current, op, opid, true);
                }
            }
        }
        private void OnAddMatch(XmlElement diffgramElement, XmlDiffPathNodeList matchNodes, XmlDiffViewParentNode sourceParent,
                                ref XmlDiffViewNode currentPosition)
        {
            string opidAttr = diffgramElement.GetAttribute("opid");

            if (opidAttr == string.Empty)
            {
                throw new Exception("Missing opid attribute.");
            }

            // opid & descriptor
            int opid = int.Parse(opidAttr);
            OperationDescriptor opDesc = GetDescriptor(opid);

            string subtreeAttr = diffgramElement.GetAttribute("subtree");
            bool   bSubtree    = (subtreeAttr != "no");

            // move single node without subtree
            if (!bSubtree)
            {
                if (matchNodes.Count != 1)
                {
                    throw new Exception("The 'match' attribute of 'add' element must select a single node when the 'subtree' attribute is specified.");
                }

                // clone node
                matchNodes.MoveNext();
                XmlDiffViewNode newNode = matchNodes.Current.Clone(false);
                AnnotateNode(newNode, XmlDiffViewOperation.MoveTo, opid, true);

                opDesc._nodeList.AddNode(newNode);

                // insert in tree
                sourceParent.InsertChildAfter(newNode, currentPosition, false);
                currentPosition = newNode;

                // recurse
                ApplyDiffgram(diffgramElement, (XmlDiffViewParentNode)newNode);
            }
            // move subtree
            else
            {
                matchNodes.Reset();
                while (matchNodes.MoveNext())
                {
                    XmlDiffViewNode newNode = matchNodes.Current.Clone(true);
                    AnnotateNode(newNode, XmlDiffViewOperation.MoveTo, opid, true);

                    opDesc._nodeList.AddNode(newNode);

                    sourceParent.InsertChildAfter(newNode, currentPosition, false);
                    currentPosition = newNode;
                }
            }
        }
        static XmlDiffPathNodeList SelectAttributes(XmlDiffViewElement parentElement, string path)
        {
            Debug.Assert(path[0] == '@');

            int pos = 1;
            XmlDiffPathNodeList nodeList = null;

            for (;;)
            {
                string name = ReadAttrName(path, ref pos);

                if (nodeList == null)
                {
                    if (pos == path.Length)
                    {
                        nodeList = new XmlDiffPathSingleNodeList();
                    }
                    else
                    {
                        nodeList = new XmlDiffPathMultiNodeList();
                    }
                }

                XmlDiffViewAttribute attr = parentElement.GetAttribute(name);
                if (attr == null)
                {
                    OnNoMatchingNode(path);
                }

                nodeList.AddNode(attr);

                if (pos == path.Length)
                {
                    break;
                }
                else if (path[pos] == '|')
                {
                    pos++;
                    if (path[pos] != '@')
                    {
                        OnInvalidExpression(path);
                    }
                    pos++;
                }
                else
                {
                    OnInvalidExpression(path);
                }
            }

            return(nodeList);
        }
Exemple #4
0
        private void OnRemove(
            XmlElement diffgramElement,
            XmlDiffPathNodeList matchNodes,
            XmlDiffViewParentNode sourceParent,
            ref XmlDiffViewNode currentPosition)
        {
            var op   = XmlDiffViewOperation.Remove;
            var opid = 0;
            OperationDescriptor operationDescriptor = null;
            var attribute = diffgramElement.GetAttribute("opid");

            if (attribute != string.Empty)
            {
                opid = int.Parse(attribute);
                operationDescriptor = this.GetDescriptor(opid);
                if (operationDescriptor._type == OperationDescriptor.Type.Move)
                {
                    op = XmlDiffViewOperation.MoveFrom;
                }
            }
            if (!(diffgramElement.GetAttribute("subtree") != "no"))
            {
                if (matchNodes.Count != 1)
                {
                    throw new Exception("The 'match' attribute of 'remove' element must select a single node when the 'subtree' attribute is specified.");
                }
                matchNodes.MoveNext();
                var current = matchNodes.Current;
                this.AnnotateNode(current, op, opid, false);
                if (opid != 0)
                {
                    operationDescriptor._nodeList.AddNode(current);
                }
                this.ApplyDiffgram(diffgramElement, (XmlDiffViewParentNode)current);
            }
            else
            {
                matchNodes.Reset();
                while (matchNodes.MoveNext())
                {
                    if (opid != 0)
                    {
                        operationDescriptor._nodeList.AddNode(matchNodes.Current);
                    }
                    this.AnnotateNode(matchNodes.Current, op, opid, true);
                }
            }
        }
Exemple #5
0
        private void OnAddMatch(
            XmlElement diffgramElement,
            XmlDiffPathNodeList matchNodes,
            XmlDiffViewParentNode sourceParent,
            ref XmlDiffViewNode currentPosition)
        {
            var attribute = diffgramElement.GetAttribute("opid");

            if (attribute == string.Empty)
            {
                throw new Exception("Missing opid attribute.");
            }
            var opid       = int.Parse(attribute);
            var descriptor = this.GetDescriptor(opid);

            if (!(diffgramElement.GetAttribute("subtree") != "no"))
            {
                if (matchNodes.Count != 1)
                {
                    throw new Exception("The 'match' attribute of 'add' element must select a single node when the 'subtree' attribute is specified.");
                }
                matchNodes.MoveNext();
                var xmlDiffViewNode = matchNodes.Current.Clone(false);
                this.AnnotateNode(xmlDiffViewNode, XmlDiffViewOperation.MoveTo, opid, true);
                descriptor._nodeList.AddNode(xmlDiffViewNode);
                sourceParent.InsertChildAfter(xmlDiffViewNode, currentPosition, false);
                currentPosition = xmlDiffViewNode;
                this.ApplyDiffgram(diffgramElement, (XmlDiffViewParentNode)xmlDiffViewNode);
            }
            else
            {
                matchNodes.Reset();
                while (matchNodes.MoveNext())
                {
                    var xmlDiffViewNode = matchNodes.Current.Clone(true);
                    this.AnnotateNode(xmlDiffViewNode, XmlDiffViewOperation.MoveTo, opid, true);
                    descriptor._nodeList.AddNode(xmlDiffViewNode);
                    sourceParent.InsertChildAfter(xmlDiffViewNode, currentPosition, false);
                    currentPosition = xmlDiffViewNode;
                }
            }
        }
Exemple #6
0
        private void OnChange(
            XmlElement diffgramElement,
            XmlDiffPathNodeList matchNodes,
            XmlDiffViewParentNode sourceParent,
            ref XmlDiffViewNode currentPosition)
        {
            Debug.Assert(matchNodes.Count == 1);
            matchNodes.Reset();
            matchNodes.MoveNext();
            var current = matchNodes.Current;

            if (current._nodeType != XmlNodeType.Attribute)
            {
                currentPosition = current;
            }
            var changeInfo = new XmlDiffViewNode.ChangeInfo();
            var str1       = diffgramElement.HasAttribute("name") ? diffgramElement.GetAttribute("name") : null;
            var str2       = diffgramElement.HasAttribute("prefix") ? diffgramElement.GetAttribute("prefix") : null;
            var str3       = diffgramElement.HasAttribute("ns") ? diffgramElement.GetAttribute("ns") : null;

            switch (current._nodeType)
            {
            case XmlNodeType.Element:
                changeInfo._localName = str1 == null ? ((XmlDiffViewElement)current)._localName : str1;
                changeInfo._prefix    = str2 == null ? ((XmlDiffViewElement)current)._prefix : str2;
                changeInfo._ns        = str3 == null ? ((XmlDiffViewElement)current)._ns : str3;
                break;

            case XmlNodeType.Attribute:
                var innerText = diffgramElement.InnerText;
                if (str1 == string.Empty && str2 == string.Empty && innerText == string.Empty)
                {
                    return;
                }
                changeInfo._localName = str1 == null ? ((XmlDiffViewAttribute)current)._localName : str1;
                changeInfo._prefix    = str2 == null ? ((XmlDiffViewAttribute)current)._prefix : str2;
                changeInfo._ns        = str3 == null ? ((XmlDiffViewAttribute)current)._ns : str3;
                changeInfo._value     = diffgramElement.InnerText;
                break;

            case XmlNodeType.Text:
            case XmlNodeType.CDATA:
                Debug.Assert(diffgramElement.FirstChild != null);
                changeInfo._value = diffgramElement.InnerText;
                break;

            case XmlNodeType.EntityReference:
                Debug.Assert(str1 != null);
                changeInfo._localName = str1;
                break;

            case XmlNodeType.ProcessingInstruction:
                if (str1 == null)
                {
                    Debug.Assert(diffgramElement.FirstChild != null);
                    Debug.Assert(diffgramElement.FirstChild.NodeType == XmlNodeType.ProcessingInstruction);
                    changeInfo._localName = diffgramElement.FirstChild.Name;
                    changeInfo._value     = diffgramElement.FirstChild.Value;
                    break;
                }
                changeInfo._localName = str1;
                changeInfo._value     = ((XmlDiffViewCharData)current)._value;
                break;

            case XmlNodeType.Comment:
                Debug.Assert(diffgramElement.FirstChild != null);
                Debug.Assert(diffgramElement.FirstChild.NodeType == XmlNodeType.Comment);
                changeInfo._value = diffgramElement.FirstChild.Value;
                break;

            case XmlNodeType.DocumentType:
                changeInfo._localName = str1 == null ? ((XmlDiffViewDocumentType)current)._name : str1;
                changeInfo._prefix    = !diffgramElement.HasAttribute("publicId") ? ((XmlDiffViewDocumentType)current)._publicId : diffgramElement.GetAttribute("publicId");
                changeInfo._ns        = !diffgramElement.HasAttribute("systemId") ? ((XmlDiffViewDocumentType)current)._systemId : diffgramElement.GetAttribute("systemId");
                changeInfo._value     = diffgramElement.FirstChild == null ? ((XmlDiffViewDocumentType)current)._subset : diffgramElement.InnerText;
                break;

            case XmlNodeType.XmlDeclaration:
                Debug.Assert(diffgramElement.FirstChild != null);
                changeInfo._value = diffgramElement.InnerText;
                break;

            default:
                Debug.Assert(false, "Invalid node type.");
                break;
            }
            current._changeInfo = changeInfo;
            current._op         = XmlDiffViewOperation.Change;
            var attribute = diffgramElement.GetAttribute("opid");

            if (attribute != string.Empty)
            {
                current._opid = int.Parse(attribute);
            }
            if (current._nodeType != XmlNodeType.Element || diffgramElement.FirstChild == null)
            {
                return;
            }
            this.ApplyDiffgram(diffgramElement, (XmlDiffViewParentNode)current);
        }
Exemple #7
0
        private void ApplyDiffgram(XmlNode diffgramParent, XmlDiffViewParentNode sourceParent)
        {
            sourceParent.CreateSourceNodesIndex();
            XmlDiffViewNode currentPosition = null;
            var             enumerator      = diffgramParent.ChildNodes.GetEnumerator();

            while (enumerator.MoveNext())
            {
                if (((XmlNode)enumerator.Current).NodeType != XmlNodeType.Comment)
                {
                    if (!(enumerator.Current is XmlElement))
                    {
                        throw new Exception("Invalid node in diffgram.");
                    }
                    var current = enumerator.Current as XmlElement;
                    if (current.NamespaceURI != "http://schemas.microsoft.com/xmltools/2002/xmldiff")
                    {
                        throw new Exception("Invalid element in diffgram.");
                    }
                    var attribute1 = current.GetAttribute("match");
                    XmlDiffPathNodeList matchNodes = null;
                    if (attribute1 != string.Empty)
                    {
                        matchNodes = XmlDiffPath.SelectNodes(this._doc, sourceParent, attribute1);
                    }
                    switch (current.LocalName)
                    {
                    case "node":
                        if (matchNodes.Count != 1)
                        {
                            throw new Exception("The 'match' attribute of 'node' element must select a single node.");
                        }
                        matchNodes.MoveNext();
                        if (current.ChildNodes.Count > 0)
                        {
                            this.ApplyDiffgram(current, (XmlDiffViewParentNode)matchNodes.Current);
                        }
                        currentPosition = matchNodes.Current;
                        continue;

                    case "add":
                        if (attribute1 != string.Empty)
                        {
                            this.OnAddMatch(current, matchNodes, sourceParent, ref currentPosition);
                            continue;
                        }
                        var attribute2 = current.GetAttribute("type");
                        if (attribute2 != string.Empty)
                        {
                            this.OnAddNode(current, attribute2, sourceParent, ref currentPosition);
                            continue;
                        }
                        this.OnAddFragment(current, sourceParent, ref currentPosition);
                        continue;

                    case "remove":
                        this.OnRemove(current, matchNodes, sourceParent, ref currentPosition);
                        continue;

                    case "change":
                        this.OnChange(current, matchNodes, sourceParent, ref currentPosition);
                        continue;

                    default:
                        continue;
                    }
                }
            }
        }
        private void OnChange(XmlElement diffgramElement, XmlDiffPathNodeList matchNodes,
                              XmlDiffViewParentNode sourceParent, ref XmlDiffViewNode currentPosition)
        {
            Debug.Assert(matchNodes.Count == 1);
            matchNodes.Reset();
            matchNodes.MoveNext();
            XmlDiffViewNode node = matchNodes.Current;

            if (node._nodeType != XmlNodeType.Attribute)
            {
                currentPosition = node;
            }

            XmlDiffViewNode.ChangeInfo changeInfo = new XmlDiffViewNode.ChangeInfo();
            string name   = diffgramElement.HasAttribute("name") ? diffgramElement.GetAttribute("name") : null;
            string prefix = diffgramElement.HasAttribute("prefix") ? diffgramElement.GetAttribute("prefix") : null;
            string ns     = diffgramElement.HasAttribute("ns") ? diffgramElement.GetAttribute("ns") : null;

            switch (node._nodeType)
            {
            case XmlNodeType.Element:
                changeInfo._localName = (name == null)? ((XmlDiffViewElement)node)._localName : name;
                changeInfo._prefix    = (prefix == null) ? ((XmlDiffViewElement)node)._prefix : prefix;
                changeInfo._ns        = (ns == null) ? ((XmlDiffViewElement)node)._ns : ns;
                break;

            case XmlNodeType.Attribute:
                string value = diffgramElement.InnerText;
                if (name == string.Empty && prefix == string.Empty && value == string.Empty)
                {
                    return;
                }
                changeInfo._localName = (name == null) ? ((XmlDiffViewAttribute)node)._localName : name;
                changeInfo._prefix    = (prefix == null) ? ((XmlDiffViewAttribute)node)._prefix      : prefix;
                changeInfo._ns        = (ns == null) ? ((XmlDiffViewAttribute)node)._ns : ns;
                changeInfo._value     = diffgramElement.InnerText;
                break;

            case XmlNodeType.Text:
            case XmlNodeType.CDATA:
                Debug.Assert(diffgramElement.FirstChild != null);
                changeInfo._value = diffgramElement.InnerText;
                break;

            case XmlNodeType.Comment:
                Debug.Assert(diffgramElement.FirstChild != null);
                Debug.Assert(diffgramElement.FirstChild.NodeType == XmlNodeType.Comment);
                changeInfo._value = diffgramElement.FirstChild.Value;
                break;

            case XmlNodeType.ProcessingInstruction:
                if (name == null)
                {
                    Debug.Assert(diffgramElement.FirstChild != null);
                    Debug.Assert(diffgramElement.FirstChild.NodeType == XmlNodeType.ProcessingInstruction);
                    changeInfo._localName = diffgramElement.FirstChild.Name;
                    changeInfo._value     = diffgramElement.FirstChild.Value;
                }
                else
                {
                    changeInfo._localName = name;
                    changeInfo._value     = ((XmlDiffViewPI)node)._value;
                }
                break;

            case XmlNodeType.EntityReference:
                Debug.Assert(name != null);
                changeInfo._localName = name;
                break;

            case XmlNodeType.XmlDeclaration:
                Debug.Assert(diffgramElement.FirstChild != null);
                changeInfo._value = diffgramElement.InnerText;
                break;

            case XmlNodeType.DocumentType:
                changeInfo._localName = (name == null) ? ((XmlDiffViewDocumentType)node)._name : name;

                if (diffgramElement.HasAttribute("publicId"))
                {
                    changeInfo._prefix = diffgramElement.GetAttribute("publicId");
                }
                else
                {
                    changeInfo._prefix = ((XmlDiffViewDocumentType)node)._publicId;
                }

                if (diffgramElement.HasAttribute("systemId"))
                {
                    changeInfo._ns = diffgramElement.GetAttribute("systemId");
                }
                else
                {
                    changeInfo._ns = ((XmlDiffViewDocumentType)node)._systemId;
                }

                if (diffgramElement.FirstChild != null)
                {
                    changeInfo._value = diffgramElement.InnerText;
                }
                else
                {
                    changeInfo._value = ((XmlDiffViewDocumentType)node)._subset;
                }
                break;

            default:
                Debug.Assert(false, "Invalid node type.");
                break;
            }
            node._changeInfo = changeInfo;
            node._op         = XmlDiffViewOperation.Change;

            string opidAttr = diffgramElement.GetAttribute("opid");

            if (opidAttr != string.Empty)
            {
                node._opid = int.Parse(opidAttr);
            }

            if (node._nodeType == XmlNodeType.Element &&
                diffgramElement.FirstChild != null)
            {
                ApplyDiffgram(diffgramElement, (XmlDiffViewParentNode)node);
            }
        }
        private void ApplyDiffgram(XmlNode diffgramParent, XmlDiffViewParentNode sourceParent)
        {
            sourceParent.CreateSourceNodesIndex();
            XmlDiffViewNode currentPosition = null;

            IEnumerator diffgramChildren = diffgramParent.ChildNodes.GetEnumerator();

            while (diffgramChildren.MoveNext())
            {
                XmlNode diffgramNode = (XmlNode)diffgramChildren.Current;
                if (diffgramNode.NodeType == XmlNodeType.Comment)
                {
                    continue;
                }
                XmlElement diffgramElement = diffgramChildren.Current as XmlElement;
                if (diffgramElement == null)
                {
                    throw new Exception("Invalid node in diffgram.");
                }

                if (diffgramElement.NamespaceURI != XmlDiff.NamespaceUri)
                {
                    throw new Exception("Invalid element in diffgram.");
                }

                string matchAttr = diffgramElement.GetAttribute("match");
                XmlDiffPathNodeList matchNodes = null;
                if (matchAttr != string.Empty)
                {
                    matchNodes = XmlDiffPath.SelectNodes(_doc, sourceParent, matchAttr);
                }

                switch (diffgramElement.LocalName)
                {
                case "node":
                    if (matchNodes.Count != 1)
                    {
                        throw new Exception("The 'match' attribute of 'node' element must select a single node.");
                    }
                    matchNodes.MoveNext();
                    if (diffgramElement.ChildNodes.Count > 0)
                    {
                        ApplyDiffgram(diffgramElement, (XmlDiffViewParentNode)matchNodes.Current);
                    }
                    currentPosition = matchNodes.Current;
                    break;

                case "add":
                    if (matchAttr != string.Empty)
                    {
                        OnAddMatch(diffgramElement, matchNodes, sourceParent, ref currentPosition);
                    }
                    else
                    {
                        string typeAttr = diffgramElement.GetAttribute("type");
                        if (typeAttr != string.Empty)
                        {
                            OnAddNode(diffgramElement, typeAttr, sourceParent, ref currentPosition);
                        }
                        else
                        {
                            OnAddFragment(diffgramElement, sourceParent, ref currentPosition);
                        }
                    }
                    break;

                case "remove":
                    OnRemove(diffgramElement, matchNodes, sourceParent, ref currentPosition);
                    break;

                case "change":
                    OnChange(diffgramElement, matchNodes, sourceParent, ref currentPosition);
                    break;
                }
            }
        }
        /// <summary>
        /// Tag the relocated data 
        /// </summary>
        /// <param name="diffgramElement">node in diffgram</param>
        /// <param name="matchNodes">the path to the baseline node</param>
        /// <param name="sourceParent">the baseline parent node</param>
        /// <param name="currentPosition">the resulting node</param>
        private void OnRemove(
            XmlElement diffgramElement,
            XmlDiffPathNodeList matchNodes,
            XmlDiffViewParentNode sourceParent,
            ref XmlDiffViewNode currentPosition)
        {
            // opid & descriptor
            XmlDiffViewOperation operation = XmlDiffViewOperation.Remove;
            int operationId = 0;
            OperationDescriptor operationDesc = null;

            string opidAttr = diffgramElement.GetAttribute("opid");
            if (opidAttr != string.Empty) {
                operationId = int.Parse(opidAttr);
                operationDesc = this.GetDescriptor(operationId);
                if (operationDesc.OperationType == OperationDescriptor.Type.Move) {
                    operation = XmlDiffViewOperation.MoveFrom;
                }
            } else {
                operationId = NextOperationId;
            }

            // subtree
            string subtreeAttr = diffgramElement.GetAttribute("subtree");
            bool subtree = (subtreeAttr != "no");
            if (!subtree)
            {
                if (matchNodes.Count != 1)
                {
                    throw new Exception("The 'match' attribute of 'remove' " +
                        "element must select a single node when the 'subtree' " +
                        "attribute is specified.");
                }

                // annotate node
                matchNodes.MoveNext();
                XmlDiffViewNode node = matchNodes.Current;
                this.AnnotateNode(node, operation, operationId, false);
                if (operationId != 0 && operationDesc != null)
                {
                    operationDesc.NodeList.AddNode(node);
                }

                // recurse
                this.ApplyDiffgram(diffgramElement, (XmlDiffViewParentNode)node);
            }
            else
            {
                // annotate nodes
                matchNodes.Reset();
                while (matchNodes.MoveNext())
                {
                    if (operationId != 0 && operationDesc != null)
                    {
                        operationDesc.NodeList.AddNode(matchNodes.Current);
                    }
                    this.AnnotateNode(matchNodes.Current, operation, operationId, true);
                }
            }
        }
        /// <summary>
        /// Store changes in the ChangeInfo object of the marked-up-baseline node
        /// </summary>
        /// <param name="diffgramElement">current element in the diffgram</param>
        /// <param name="matchNodes">Object containing the list of baseline nodes
        ///  which match the position in the diffgram</param>
        /// <param name="sourceParent">parent node in the baseline data</param>
        /// <param name="currentPosition">current position</param>
        private void OnChange(
            XmlElement diffgramElement,
            XmlDiffPathNodeList matchNodes,
            XmlDiffViewParentNode sourceParent,
            ref XmlDiffViewNode currentPosition)
        {
            Debug.Assert(matchNodes.Count == 1);
            matchNodes.Reset();
            matchNodes.MoveNext();
            XmlDiffViewNode node = matchNodes.Current;

            if (node.NodeType != XmlNodeType.Attribute)
            {
                currentPosition = node;
            }
            XmlDiffViewNode.ChangeInfo changeInfo = new XmlDiffViewNode.ChangeInfo();
            string name = diffgramElement.HasAttribute("name") ? diffgramElement.GetAttribute("name") : null;
            string prefix = diffgramElement.HasAttribute("prefix") ? diffgramElement.GetAttribute("prefix") : null;
            string ns = diffgramElement.HasAttribute("ns") ? diffgramElement.GetAttribute("ns") : null;

            switch (node.NodeType)
            {
                case XmlNodeType.Element:
                    changeInfo.LocalName = (name == null) ? ((XmlDiffViewElement)node).LocalName : name;
                    changeInfo.Prefix = (prefix == null) ? ((XmlDiffViewElement)node).Prefix : prefix;
                    changeInfo.NamespaceUri = (ns == null) ? ((XmlDiffViewElement)node).NamespaceUri : ns;
                    break;
                case XmlNodeType.Attribute:
                    string value = diffgramElement.InnerText;
                    if (name == string.Empty && prefix == string.Empty && value == string.Empty)
                    {
                        return;
                    }
                    changeInfo.LocalName = (name == null) ? ((XmlDiffViewAttribute)node).LocalName : name;
                    changeInfo.Prefix = (prefix == null) ? ((XmlDiffViewAttribute)node).Prefix : prefix;
                    changeInfo.NamespaceUri = (ns == null) ? ((XmlDiffViewAttribute)node).NamespaceUri : ns;
                    changeInfo.Subset = diffgramElement.InnerText;
                    break;
                case XmlNodeType.Text:
                case XmlNodeType.CDATA:
                    Debug.Assert(diffgramElement.FirstChild != null);
                    changeInfo.Subset = diffgramElement.InnerText;
                    break;
                case XmlNodeType.Comment:
                    Debug.Assert(diffgramElement.FirstChild != null);
                    Debug.Assert(diffgramElement.FirstChild.NodeType == XmlNodeType.Comment);
                    changeInfo.Subset = diffgramElement.FirstChild.Value;
                    break;
                case XmlNodeType.ProcessingInstruction:
                    if (name == null)
                    {
                        Debug.Assert(diffgramElement.FirstChild != null);
                        Debug.Assert(diffgramElement.FirstChild.NodeType == XmlNodeType.ProcessingInstruction);
                        changeInfo.LocalName = diffgramElement.FirstChild.Name;
                        changeInfo.Subset = diffgramElement.FirstChild.Value;
                    }
                    else
                    {
                        changeInfo.LocalName = name;
                        changeInfo.Subset = ((XmlDiffViewPI)node).InnerText;
                    }
                    break;
                case XmlNodeType.EntityReference:
                    Debug.Assert(name != null);
                    changeInfo.LocalName = name;
                    break;
                case XmlNodeType.XmlDeclaration:
                    Debug.Assert(diffgramElement.FirstChild != null);
                    changeInfo.Subset = diffgramElement.InnerText;
                    break;
                case XmlNodeType.DocumentType:
                    changeInfo.LocalName = (name == null) ? ((XmlDiffViewDocumentType)node).Name : name;

                    if (diffgramElement.HasAttribute("publicId"))
                    {
                        changeInfo.Prefix = diffgramElement.GetAttribute("publicId");
                    }
                    else
                    {
                        changeInfo.Prefix = ((XmlDiffViewDocumentType)node).PublicId;
                    }

                    if (diffgramElement.HasAttribute("systemId"))
                    {
                        changeInfo.NamespaceUri = diffgramElement.GetAttribute("systemId");
                    }
                    else
                    {
                        changeInfo.NamespaceUri = ((XmlDiffViewDocumentType)node).SystemId;
                    }

                    if (diffgramElement.FirstChild != null)
                    {
                        changeInfo.Subset = diffgramElement.InnerText;
                    }
                    else
                    {
                        changeInfo.Subset = ((XmlDiffViewDocumentType)node).Subset;
                    }
                    break;
                default:
                    Debug.Assert(false, "Invalid node type.");
                    break;
            }
            node.ChangeInformation = changeInfo;
            node.Operation = XmlDiffViewOperation.Change;

            string opidAttr = diffgramElement.GetAttribute("opid");
            if (opidAttr != string.Empty) {
                node.OperationId = int.Parse(opidAttr);
            } else {
                node.OperationId = NextOperationId;
            }

            if (node.NodeType == XmlNodeType.Element &&
                diffgramElement.FirstChild != null)
            {
                this.ApplyDiffgram(diffgramElement, (XmlDiffViewParentNode)node);
            }
        }
        /// <summary>
        /// Relocate matched data. 
        /// </summary>
        /// <param name="diffgramElement">node in diffgram</param>
        /// <param name="matchNodes">the path to the baseline node</param>
        /// <param name="sourceParent">the baseline parent node</param>
        /// <param name="currentPosition">the resulting node</param>
        private void OnAddMatch(
            XmlElement diffgramElement,
            XmlDiffPathNodeList matchNodes,
            XmlDiffViewParentNode sourceParent,
            ref XmlDiffViewNode currentPosition)
        {
            string opidAttr = diffgramElement.GetAttribute("opid");
            if (opidAttr == string.Empty)
            {
                throw new Exception("Missing opid attribute.");
            }

            // opid & descriptor
            int opid = ParseOpId(opidAttr);
            OperationDescriptor operationDesc = this.GetDescriptor(opid);

            string subtreeAttr = diffgramElement.GetAttribute("subtree");
            bool subtree = (subtreeAttr != "no");

            // move single node without subtree
            if (!subtree)
            {
                if (matchNodes.Count != 1)
                {
                    throw new Exception("The 'match' attribute of 'add' " +
                        "element must select a single node when the 'subtree' " +
                        "attribute is specified.");
                }

                // clone node
                matchNodes.MoveNext();
                XmlDiffViewNode newNode = matchNodes.Current.Clone(false);
                this.AnnotateNode(
                    newNode,
                    XmlDiffViewOperation.MoveTo,
                    opid,
                    true);

                operationDesc.NodeList.AddNode(newNode);

                // insert in tree
                sourceParent.InsertChildAfter(newNode, currentPosition, false);
                currentPosition = newNode;

                // recurse
                this.ApplyDiffgram(
                    diffgramElement,
                    (XmlDiffViewParentNode)newNode);
            }
            else
            {
                // move subtree
                matchNodes.Reset();
                while (matchNodes.MoveNext())
                {
                    XmlDiffViewNode newNode = matchNodes.Current.Clone(true);
                    this.AnnotateNode(
                        newNode,
                        XmlDiffViewOperation.MoveTo,
                        opid,
                        true);

                    operationDesc.NodeList.AddNode(newNode);

                    sourceParent.InsertChildAfter(newNode, currentPosition, false);
                    currentPosition = newNode;
                }
            }
        }
        static XmlDiffPathNodeList SelectChildNodes(XmlDiffViewParentNode parentNode, string path, int startPos)
        {
            int pos = startPos;
            XmlDiffPathNodeList nodeList = null;

            for (;;)
            {
                int nodePos = ReadPosition(path, ref pos);

                if (pos == path.Length)
                {
                    nodeList = new XmlDiffPathSingleNodeList();
                }
                else
                {
                    nodeList = new XmlDiffPathMultiNodeList();
                }

                if (nodePos <= 0 || nodePos > parentNode._sourceChildNodesCount)
                {
                    OnNoMatchingNode(path);
                }

                nodeList.AddNode(parentNode.GetSourceChildNode(nodePos - 1));

                if (pos == path.Length)
                {
                    break;
                }
                else if (path[pos] == '|')
                {
                    pos++;
                }
                else if (path[pos] == '-')
                {
                    pos++;
                    int endNodePos = ReadPosition(path, ref pos);
                    if (endNodePos <= 0 || endNodePos > parentNode._sourceChildNodesCount)
                    {
                        OnNoMatchingNode(path);
                    }

                    while (nodePos < endNodePos)
                    {
                        nodePos++;
                        nodeList.AddNode(parentNode.GetSourceChildNode(nodePos - 1));
                    }

                    if (pos == path.Length)
                    {
                        break;
                    }
                    else if (path[pos] == '|')
                    {
                        pos++;
                    }
                    else
                    {
                        OnInvalidExpression(path);
                    }
                }
            }
            return(nodeList);
        }