Ejemplo n.º 1
0
    private void CreatePatchForChildren( XmlNode sourceParent, 
                                         XmlElement diffgramParent, 
                                         XmlPatchParentOperation patchParent )
    {
        Debug.Assert( sourceParent != null );
        Debug.Assert( diffgramParent != null );
        Debug.Assert( patchParent != null );

        XmlPatchOperation lastPatchOp = null;

        XmlNode node = diffgramParent.FirstChild;
        while ( node != null )
        {
            if ( node.NodeType != XmlNodeType.Element ) {
                node = node.NextSibling;
                continue;
            }

            XmlElement diffOp = (XmlElement)node;
            XmlNodeList matchNodes = null;
            string matchAttr = diffOp.GetAttribute( "match" );

            if ( matchAttr != string.Empty )
            {
                matchNodes = PathDescriptorParser.SelectNodes( _sourceRootNode, sourceParent, matchAttr );
                
                if ( matchNodes.Count == 0 )
                    XmlPatchError.Error( XmlPatchError.NoMatchingNode, matchAttr );
            }

            XmlPatchOperation patchOp = null;

            switch ( diffOp.LocalName )
            {
                case "node":
                {
                    Debug.Assert( matchAttr != string.Empty );

                    if ( matchNodes.Count != 1 )
                        XmlPatchError.Error( XmlPatchError.MoreThanOneNodeMatched, matchAttr );

                    XmlNode matchNode = matchNodes.Item( 0 );

                    if ( _sourceRootNode.NodeType != XmlNodeType.Document ||
                         ( matchNode.NodeType != XmlNodeType.XmlDeclaration && matchNode.NodeType != XmlNodeType.DocumentType ) ) {
                        patchOp = new PatchSetPosition( matchNode );
                        CreatePatchForChildren( matchNode, diffOp, (XmlPatchParentOperation) patchOp );
                    }
                    break;
                }
                case "add":
                {
                    // copy node/subtree
                    if ( matchAttr != string.Empty )
                    {
                        bool bSubtree = diffOp.GetAttribute( "subtree" ) != "no";
                        patchOp = new PatchCopy( matchNodes, bSubtree );
                        if ( !bSubtree )
                            CreatePatchForChildren( sourceParent, diffOp, (XmlPatchParentOperation) patchOp );
                    }
                    else
                    {
                        string type = diffOp.GetAttribute( "type" );
                        // add single node
                        if ( type != string.Empty )
                        {
                            XmlNodeType nodeType = (XmlNodeType) int.Parse( type );
                            bool bElement = (nodeType == XmlNodeType.Element);

                            if ( nodeType != XmlNodeType.DocumentType ) {
                                patchOp = new PatchAddNode( nodeType,  
                                                            diffOp.GetAttribute( "name" ), 
                                                            diffOp.GetAttribute( "ns" ), 
                                                            diffOp.GetAttribute( "prefix" ), 
                                                            bElement ? string.Empty : diffOp.InnerText,
                                                            _ignoreChildOrder );
                                if ( bElement )
                                    CreatePatchForChildren( sourceParent, diffOp, (XmlPatchParentOperation) patchOp );
                            }
                            else {
                                patchOp = new PatchAddNode( nodeType,  
                                                            diffOp.GetAttribute( "name" ), 
                                                            diffOp.GetAttribute( "systemId" ), 
                                                            diffOp.GetAttribute( "publicId" ), 
                                                            diffOp.InnerText,
                                                            _ignoreChildOrder );
                            }
                        }
                        // add blob
                        else
                        {
                            Debug.Assert( diffOp.ChildNodes.Count > 0 );
                            patchOp = new PatchAddXmlFragment( diffOp.ChildNodes );
                        }
                    }

                    break;
                }
                case "remove":
                {
                    Debug.Assert( matchAttr != string.Empty );

                    bool bSubtree = diffOp.GetAttribute( "subtree" ) != "no";
                    patchOp = new PatchRemove( matchNodes, bSubtree );
                    if ( !bSubtree )
                    {
                        Debug.Assert( matchNodes.Count == 1 );
                        CreatePatchForChildren( matchNodes.Item(0), diffOp, (XmlPatchParentOperation) patchOp );
                    }

                    break;
                }
                case "change":
                {
                    Debug.Assert( matchAttr != string.Empty );
                    if ( matchNodes.Count != 1 )
                        XmlPatchError.Error( XmlPatchError.MoreThanOneNodeMatched, matchAttr );

                    XmlNode matchNode = matchNodes.Item( 0 );
                    if ( matchNode.NodeType != XmlNodeType.DocumentType ) {
                        patchOp = new PatchChange( matchNode, 
                                                diffOp.HasAttribute( "name" ) ? diffOp.GetAttribute( "name" ) : null,
                                                diffOp.HasAttribute( "ns" ) ? diffOp.GetAttribute( "ns" ) : null, 
                                                diffOp.HasAttribute( "prefix" ) ? diffOp.GetAttribute( "prefix" ) : null, 
                                                (matchNode.NodeType == XmlNodeType.Element) ? null : diffOp );
                    }
                    else {
                        patchOp = new PatchChange( matchNode,
                                                   diffOp.HasAttribute( "name" ) ? diffOp.GetAttribute( "name" ) : null, 
                                                   diffOp.HasAttribute( "systemId" ) ? diffOp.GetAttribute( "systemId" ) : null,
                                                   diffOp.HasAttribute( "publicId" ) ? diffOp.GetAttribute( "publicId" ) : null,
                                                   diffOp.IsEmpty ? null : diffOp );
                    }

                    if ( matchNode.NodeType == XmlNodeType.Element )
                        CreatePatchForChildren( matchNode, diffOp, (XmlPatchParentOperation) patchOp );
                    break;
                }
                case "descriptor":
                    return;

                default:
                    Debug.Assert( false, "Invalid element in the XDL diffgram ." );
                    break;
            }

            if ( patchOp != null ) {
                patchParent.InsertChildAfter( lastPatchOp, patchOp );
                lastPatchOp = patchOp;
            }
            node = node.NextSibling;
        }
    }
Ejemplo n.º 2
0
        private void CreatePatchForChildren(XmlNode sourceParent,
                                            XmlElement diffgramParent,
                                            XmlPatchParentOperation patchParent)
        {
            Debug.Assert(sourceParent != null);
            Debug.Assert(diffgramParent != null);
            Debug.Assert(patchParent != null);

            XmlPatchOperation lastPatchOp = null;

            XmlNode node = diffgramParent.FirstChild;

            while (node != null)
            {
                if (node.NodeType != XmlNodeType.Element)
                {
                    node = node.NextSibling;
                    continue;
                }

                XmlElement  diffOp     = (XmlElement)node;
                XmlNodeList matchNodes = null;
                string      matchAttr  = diffOp.GetAttribute("match");

                if (matchAttr != string.Empty)
                {
                    matchNodes = PathDescriptorParser.SelectNodes(_sourceRootNode, sourceParent, matchAttr);

                    if (matchNodes.Count == 0)
                    {
                        XmlPatchError.Error(XmlPatchError.NoMatchingNode, matchAttr);
                    }
                }

                XmlPatchOperation patchOp = null;

                switch (diffOp.LocalName)
                {
                case "node":
                {
                    Debug.Assert(matchAttr != string.Empty);

                    if (matchNodes.Count != 1)
                    {
                        XmlPatchError.Error(XmlPatchError.MoreThanOneNodeMatched, matchAttr);
                    }

                    XmlNode matchNode = matchNodes.Item(0);

                    if (_sourceRootNode.NodeType != XmlNodeType.Document ||
                        (matchNode.NodeType != XmlNodeType.XmlDeclaration && matchNode.NodeType != XmlNodeType.DocumentType))
                    {
                        patchOp = new PatchSetPosition(matchNode);
                        CreatePatchForChildren(matchNode, diffOp, (XmlPatchParentOperation)patchOp);
                    }
                    break;
                }

                case "add":
                {
                    // copy node/subtree
                    if (matchAttr != string.Empty)
                    {
                        bool bSubtree = diffOp.GetAttribute("subtree") != "no";
                        patchOp = new PatchCopy(matchNodes, bSubtree);
                        if (!bSubtree)
                        {
                            CreatePatchForChildren(sourceParent, diffOp, (XmlPatchParentOperation)patchOp);
                        }
                    }
                    else
                    {
                        string type = diffOp.GetAttribute("type");
                        // add single node
                        if (type != string.Empty)
                        {
                            XmlNodeType nodeType = (XmlNodeType)int.Parse(type);
                            bool        bElement = (nodeType == XmlNodeType.Element);

                            if (nodeType != XmlNodeType.DocumentType)
                            {
                                patchOp = new PatchAddNode(nodeType,
                                                           diffOp.GetAttribute("name"),
                                                           diffOp.GetAttribute("ns"),
                                                           diffOp.GetAttribute("prefix"),
                                                           bElement ? string.Empty : diffOp.InnerText,
                                                           _ignoreChildOrder);
                                if (bElement)
                                {
                                    CreatePatchForChildren(sourceParent, diffOp, (XmlPatchParentOperation)patchOp);
                                }
                            }
                            else
                            {
                                patchOp = new PatchAddNode(nodeType,
                                                           diffOp.GetAttribute("name"),
                                                           diffOp.GetAttribute("systemId"),
                                                           diffOp.GetAttribute("publicId"),
                                                           diffOp.InnerText,
                                                           _ignoreChildOrder);
                            }
                        }
                        // add blob
                        else
                        {
                            Debug.Assert(diffOp.ChildNodes.Count > 0);
                            patchOp = new PatchAddXmlFragment(diffOp.ChildNodes);
                        }
                    }

                    break;
                }

                case "remove":
                {
                    Debug.Assert(matchAttr != string.Empty);

                    bool bSubtree = diffOp.GetAttribute("subtree") != "no";
                    patchOp = new PatchRemove(matchNodes, bSubtree);
                    if (!bSubtree)
                    {
                        Debug.Assert(matchNodes.Count == 1);
                        CreatePatchForChildren(matchNodes.Item(0), diffOp, (XmlPatchParentOperation)patchOp);
                    }

                    break;
                }

                case "change":
                {
                    Debug.Assert(matchAttr != string.Empty);
                    if (matchNodes.Count != 1)
                    {
                        XmlPatchError.Error(XmlPatchError.MoreThanOneNodeMatched, matchAttr);
                    }

                    XmlNode matchNode = matchNodes.Item(0);
                    if (matchNode.NodeType != XmlNodeType.DocumentType)
                    {
                        patchOp = new PatchChange(matchNode,
                                                  diffOp.HasAttribute("name") ? diffOp.GetAttribute("name") : null,
                                                  diffOp.HasAttribute("ns") ? diffOp.GetAttribute("ns") : null,
                                                  diffOp.HasAttribute("prefix") ? diffOp.GetAttribute("prefix") : null,
                                                  (matchNode.NodeType == XmlNodeType.Element) ? null : diffOp);
                    }
                    else
                    {
                        patchOp = new PatchChange(matchNode,
                                                  diffOp.HasAttribute("name") ? diffOp.GetAttribute("name") : null,
                                                  diffOp.HasAttribute("systemId") ? diffOp.GetAttribute("systemId") : null,
                                                  diffOp.HasAttribute("publicId") ? diffOp.GetAttribute("publicId") : null,
                                                  diffOp.IsEmpty ? null : diffOp);
                    }

                    if (matchNode.NodeType == XmlNodeType.Element)
                    {
                        CreatePatchForChildren(matchNode, diffOp, (XmlPatchParentOperation)patchOp);
                    }
                    break;
                }

                case "descriptor":
                    return;

                default:
                    Debug.Assert(false, "Invalid element in the XDL diffgram .");
                    break;
                }

                if (patchOp != null)
                {
                    patchParent.InsertChildAfter(lastPatchOp, patchOp);
                    lastPatchOp = patchOp;
                }
                node = node.NextSibling;
            }
        }