internal static XmlNodeList SelectNodes(
            XmlNode rootNode,
            XmlNode currentParentNode,
            string pathDescriptor)
        {
            switch (pathDescriptor[0])
            {
            case '*':
                if (pathDescriptor.Length == 1)
                {
                    return(PathDescriptorParser.SelectAllChildren(currentParentNode));
                }
                PathDescriptorParser.OnInvalidExpression(pathDescriptor);
                return((XmlNodeList)null);

            case '/':
                return(PathDescriptorParser.SelectAbsoluteNodes(rootNode, pathDescriptor));

            case '@':
                if (pathDescriptor.Length < 2)
                {
                    PathDescriptorParser.OnInvalidExpression(pathDescriptor);
                }
                return(pathDescriptor[1] == '*' ? PathDescriptorParser.SelectAllAttributes(currentParentNode) : PathDescriptorParser.SelectAttributes(currentParentNode, pathDescriptor));

            default:
                return(PathDescriptorParser.SelectChildNodes(currentParentNode, pathDescriptor, 0));
            }
        }
        private static XmlNodeList SelectAbsoluteNodes(XmlNode rootNode, string path)
        {
            var pos     = 1;
            var xmlNode = rootNode;
            int startPos;

            while (true)
            {
                startPos = pos;
                var childNodes = xmlNode.ChildNodes;
                var num        = PathDescriptorParser.ReadPosition(path, ref pos);
                if (pos == path.Length || path[pos] == '/')
                {
                    if (childNodes.Count == 0 || num < 0 || num > childNodes.Count)
                    {
                        PathDescriptorParser.OnNoMatchingNode(path);
                    }
                    xmlNode = childNodes.Item(num - 1);
                    if (pos != path.Length)
                    {
                        ++pos;
                    }
                    else
                    {
                        break;
                    }
                }
                else if (path[pos] != '-' && path[pos] != '|')
                {
                    PathDescriptorParser.OnInvalidExpression(path);
                }
                else
                {
                    goto label_8;
                }
            }
            var xmlPatchNodeList = (XmlPatchNodeList) new SingleNodeList();

            xmlPatchNodeList.AddNode(xmlNode);
            return((XmlNodeList)xmlPatchNodeList);

label_8:
            return(PathDescriptorParser.SelectChildNodes(xmlNode, path, startPos));
        }
        private static XmlNodeList SelectAttributes(XmlNode parentNode, string path)
        {
            var pos              = 1;
            var attributes       = parentNode.Attributes;
            var xmlPatchNodeList = (XmlPatchNodeList)null;

            while (true)
            {
                var name = PathDescriptorParser.ReadAttrName(path, ref pos);
                if (xmlPatchNodeList == null)
                {
                    xmlPatchNodeList = pos != path.Length ? (XmlPatchNodeList) new MultiNodeList() : (XmlPatchNodeList) new SingleNodeList();
                }
                var namedItem = attributes.GetNamedItem(name);
                if (namedItem == null)
                {
                    PathDescriptorParser.OnNoMatchingNode(path);
                }
                xmlPatchNodeList.AddNode(namedItem);
                if (pos != path.Length)
                {
                    if (path[pos] == '|')
                    {
                        ++pos;
                        if (path[pos] != '@')
                        {
                            PathDescriptorParser.OnInvalidExpression(path);
                        }
                        ++pos;
                    }
                    else
                    {
                        PathDescriptorParser.OnInvalidExpression(path);
                    }
                }
                else
                {
                    break;
                }
            }
            return((XmlNodeList)xmlPatchNodeList);
        }
        private static XmlNodeList SelectAllChildren(XmlNode parentNode)
        {
            var childNodes = parentNode.ChildNodes;

            if (childNodes.Count == 0)
            {
                PathDescriptorParser.OnNoMatchingNode("*");
                return((XmlNodeList)null);
            }
            if (childNodes.Count == 1)
            {
                var xmlPatchNodeList = (XmlPatchNodeList) new SingleNodeList();
                xmlPatchNodeList.AddNode(childNodes.Item(0));
                return((XmlNodeList)xmlPatchNodeList);
            }
            var enumerator        = childNodes.GetEnumerator();
            var xmlPatchNodeList1 = (XmlPatchNodeList) new MultiNodeList();

            while (enumerator.MoveNext())
            {
                xmlPatchNodeList1.AddNode((XmlNode)enumerator.Current);
            }
            return((XmlNodeList)xmlPatchNodeList1);
        }
Beispiel #5
0
        private void CreatePatchForChildren(
            XmlNode sourceParent,
            XmlElement diffgramParent,
            XmlPatchParentOperation patchParent)
        {
            XmlPatchOperation child = null;
            var xmlNode1            = diffgramParent.FirstChild;

            while (xmlNode1 != null)
            {
                if (xmlNode1.NodeType != XmlNodeType.Element)
                {
                    xmlNode1 = xmlNode1.NextSibling;
                }
                else
                {
                    var         diffgramParent1 = (XmlElement)xmlNode1;
                    XmlNodeList xmlNodeList     = null;
                    var         attribute1      = diffgramParent1.GetAttribute("match");
                    if (attribute1 != string.Empty)
                    {
                        xmlNodeList = PathDescriptorParser.SelectNodes(this._sourceRootNode, sourceParent, attribute1);
                        if (xmlNodeList.Count == 0)
                        {
                            XmlPatchError.Error("Invalid XDL diffgram. No node matches the path descriptor '{0}'.", attribute1);
                        }
                    }
                    XmlPatchOperation newChild = null;
                    switch (diffgramParent1.LocalName)
                    {
                    case "node":
                        if (xmlNodeList.Count != 1)
                        {
                            XmlPatchError.Error("Invalid XDL diffgram; more than one node matches the '{0}' path descriptor on the xd:node or xd:change element.", attribute1);
                        }
                        var xmlNode2 = xmlNodeList.Item(0);
                        if (this._sourceRootNode.NodeType != XmlNodeType.Document || xmlNode2.NodeType != XmlNodeType.XmlDeclaration && xmlNode2.NodeType != XmlNodeType.DocumentType)
                        {
                            newChild = new PatchSetPosition(xmlNode2);
                            this.CreatePatchForChildren(xmlNode2, diffgramParent1, (XmlPatchParentOperation)newChild);
                            break;
                        }
                        break;

                    case "add":
                        if (attribute1 != string.Empty)
                        {
                            var bSubtree = diffgramParent1.GetAttribute("subtree") != "no";
                            newChild = new PatchCopy(xmlNodeList, bSubtree);
                            if (!bSubtree)
                            {
                                this.CreatePatchForChildren(sourceParent, diffgramParent1, (XmlPatchParentOperation)newChild);
                                break;
                            }
                            break;
                        }
                        var attribute2 = diffgramParent1.GetAttribute("type");
                        if (attribute2 != string.Empty)
                        {
                            var nodeType = (XmlNodeType)int.Parse(attribute2);
                            var flag     = nodeType == XmlNodeType.Element;
                            if (nodeType != XmlNodeType.DocumentType)
                            {
                                newChild = new PatchAddNode(nodeType, diffgramParent1.GetAttribute("name"), diffgramParent1.GetAttribute("ns"), diffgramParent1.GetAttribute("prefix"), flag ? string.Empty : diffgramParent1.InnerText, this._ignoreChildOrder);
                                if (flag)
                                {
                                    this.CreatePatchForChildren(sourceParent, diffgramParent1, (XmlPatchParentOperation)newChild);
                                    break;
                                }
                                break;
                            }
                            newChild = new PatchAddNode(nodeType, diffgramParent1.GetAttribute("name"), diffgramParent1.GetAttribute("systemId"), diffgramParent1.GetAttribute("publicId"), diffgramParent1.InnerText, this._ignoreChildOrder);
                            break;
                        }
                        newChild = new PatchAddXmlFragment(diffgramParent1.ChildNodes);
                        break;

                    case "remove":
                        var bSubtree1 = diffgramParent1.GetAttribute("subtree") != "no";
                        newChild = new PatchRemove(xmlNodeList, bSubtree1);
                        if (!bSubtree1)
                        {
                            this.CreatePatchForChildren(xmlNodeList.Item(0), diffgramParent1, (XmlPatchParentOperation)newChild);
                            break;
                        }
                        break;

                    case "change":
                        if (xmlNodeList.Count != 1)
                        {
                            XmlPatchError.Error("Invalid XDL diffgram; more than one node matches the '{0}' path descriptor on the xd:node or xd:change element.", attribute1);
                        }
                        var xmlNode3 = xmlNodeList.Item(0);
                        newChild = xmlNode3.NodeType == XmlNodeType.DocumentType ? new PatchChange(xmlNode3, diffgramParent1.HasAttribute("name") ? diffgramParent1.GetAttribute("name") : null, diffgramParent1.HasAttribute("systemId") ? diffgramParent1.GetAttribute("systemId") : null, diffgramParent1.HasAttribute("publicId") ? diffgramParent1.GetAttribute("publicId") : null, diffgramParent1.IsEmpty ? null : diffgramParent1) : new PatchChange(xmlNode3, diffgramParent1.HasAttribute("name") ? diffgramParent1.GetAttribute("name") : null, diffgramParent1.HasAttribute("ns") ? diffgramParent1.GetAttribute("ns") : null, diffgramParent1.HasAttribute("prefix") ? diffgramParent1.GetAttribute("prefix") : null, xmlNode3.NodeType == XmlNodeType.Element ? null : diffgramParent1);
                        if (xmlNode3.NodeType == XmlNodeType.Element)
                        {
                            this.CreatePatchForChildren(xmlNode3, diffgramParent1, (XmlPatchParentOperation)newChild);
                            break;
                        }
                        break;

                    case "descriptor":
                        return;
                    }
                    if (newChild != null)
                    {
                        patchParent.InsertChildAfter(child, newChild);
                        child = newChild;
                    }
                    xmlNode1 = xmlNode1.NextSibling;
                }
            }
        }
        private static XmlNodeList SelectChildNodes(
            XmlNode parentNode,
            string path,
            int startPos)
        {
            var pos              = startPos;
            var childNodes       = parentNode.ChildNodes;
            var num1             = PathDescriptorParser.ReadPosition(path, ref pos);
            var xmlPatchNodeList = pos != path.Length ? (XmlPatchNodeList) new MultiNodeList() : (XmlPatchNodeList) new SingleNodeList();

            while (true)
            {
                if (num1 <= 0 || num1 > childNodes.Count)
                {
                    PathDescriptorParser.OnNoMatchingNode(path);
                }
                var node = childNodes.Item(num1 - 1);
                xmlPatchNodeList.AddNode(node);
                if (pos != path.Length)
                {
                    if (path[pos] == '|')
                    {
                        ++pos;
                    }
                    else if (path[pos] == '-')
                    {
                        ++pos;
                        var num2 = PathDescriptorParser.ReadPosition(path, ref pos);
                        if (num2 <= 0 || num2 > childNodes.Count)
                        {
                            PathDescriptorParser.OnNoMatchingNode(path);
                        }
                        while (num1 < num2)
                        {
                            ++num1;
                            node = node.NextSibling;
                            xmlPatchNodeList.AddNode(node);
                        }
                        if (pos != path.Length)
                        {
                            if (path[pos] == '|')
                            {
                                ++pos;
                            }
                            else
                            {
                                PathDescriptorParser.OnInvalidExpression(path);
                            }
                        }
                        else
                        {
                            break;
                        }
                    }
                    num1 = PathDescriptorParser.ReadPosition(path, ref pos);
                }
                else
                {
                    break;
                }
            }
            return((XmlNodeList)xmlPatchNodeList);
        }
Beispiel #7
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;
            }
        }