示例#1
0
        /// <summary>
        /// Build an xpath by prepending the data from lastnode
        /// </summary>
        private string BuildXpath(TreeNode tn)
        {
            IDiffNode lastNode = tn.Tag as IDiffNode;

            if (lastNode.TypeName == "XmlSchemaAttribute" &&
                String.IsNullOrEmpty(lastNode.NodeNamespace))
            {
                return(string.Format("{0}/@{1}",
                                     BuildXpath(tn.Parent), lastNode.FriendlyName));
            }
            else if (lastNode.TypeName == "XmlSchemaAttribute")
            {
                return(string.Format("{0}/*@[namespace-uri() = '{1}' and local-name() = '{2}']",
                                     BuildXpath(tn.Parent), lastNode.NodeNamespace, lastNode.FriendlyName));
            }
            else if (lastNode.Parent != null && lastNode.TypeName == "XmlSchemaElement")
            {
                return(string.Format("{0}/*[namespace-uri() = '{1}' and local-name() = '{2}']",
                                     BuildXpath(tn.Parent), lastNode.NodeNamespace, lastNode.FriendlyName));
            }
            else if (lastNode.TypeName == "XmlSchemaElement")
            {
                return(string.Format("/*[namespace-uri() = '{0}' and local-name() = '{1}']",
                                     lastNode.NodeNamespace, lastNode.FriendlyName));
            }
            else if (lastNode.Parent != null)
            {
                return(BuildXpath(tn.Parent));
            }
            else
            {
                return("");
            }
        }
示例#2
0
        private void CopyChildNodes(XmlSchemaSequence sequence, IDiffNode parent, Stack<String> typeStack)
        {
            if (sequence.Content == null || sequence.Content.Count == 0) return;

            IDiffNode seqNode = parent;

            if (TreatSequenceAsNode)
                seqNode = new SequenceDiffNode()
                {
                    Original = sequence
                };
            // Build the children of this 
            foreach (XmlSchemaObject child in sequence.Content)
                if (child is XmlSchemaChoice)
                    CopyChildNodes(child as XmlSchemaChoice, seqNode, typeStack);
                else if (child is XmlSchemaSequence)
                    CopyChildNodes(child as XmlSchemaSequence, seqNode, typeStack);
                else if (child is XmlSchemaElement)
                    CopyChildNodes(child as XmlSchemaElement, seqNode, typeStack);
                else if (child is XmlSchemaAny)
                    seqNode.AddChild(new DiffNode<XmlSchemaAny>() { Original = child as XmlSchemaAny });

            if (TreatSequenceAsNode)
                parent.AddChild(seqNode);
        }
示例#3
0
        /// <summary>
        /// Process the schema object
        /// </summary>
        private void ProcessSchemaObject()
        {
            if (schemaObject == null)
            {
                lblError.Visible = true;
                lblError.Text    = "Object not available";
                return;
            }
            else
            {
                lblError.Visible = false;
            }

            DiffBuilder builder  = new DiffBuilder();
            IDiffNode   diffNode = builder.BuildTree(SchemaObject);

            trvObjectView.Visible = false;
            trvObjectView.Nodes.Clear();
            ShowDiffTreeNodes(new List <IDiffNode>()
            {
                diffNode
            }, null, trvObjectView);
            if (trvObjectView.Nodes.Count > 0)
            {
                trvObjectView.Nodes[0].Expand();
            }
            trvObjectView.Visible = true;
        }
示例#4
0
        /// <summary>
        /// Build a tree of only one schema
        /// </summary>
        /// <param name="schemaA"></param>
        /// <returns></returns>
        public IDiffNode BuildTree(XmlSchemaObject obj)
        {
            // Setup the schema
            IDiffNode retVal = null;
            if (obj is XmlSchemaAttribute)
                retVal = new AttributeDiffNode() { Original = obj as XmlSchemaAttribute };
            else if (obj is XmlSchemaElement)
            {
                retVal = new ElementDiffNode() { Original = obj as XmlSchemaElement };
                CopyChildNodes((obj as XmlSchemaElement).SchemaType as XmlSchemaComplexType, retVal, new Stack<string>(), true);
            }
            else if (obj is XmlSchemaChoice)
            {
                retVal = new ChoiceDiffNode() { Original = obj as XmlSchemaChoice };
                CopyChildNodes(obj as XmlSchemaChoice, retVal, new Stack<string>());
                retVal = retVal.Children[0];
            }
            else if (obj is XmlSchemaSequence)
            {
                retVal = new SequenceDiffNode() { Original = obj as XmlSchemaSequence };
                CopyChildNodes(obj as XmlSchemaSequence, retVal, new Stack<string>());
                if (TreatSequenceAsNode)
                    retVal = retVal.Children[0];
            }
            else
                return null;

            return retVal;
        }
示例#5
0
 /// <summary>
 /// Swap the content
 /// </summary>
 private void SwapContent(IDiffNode node)
 {
     node.SetData(node.GetComparedNode(), node.GetOriginalNode());
     foreach (IDiffNode child in node.Children ?? new List<IDiffNode>())
     {
         SwapContent(child);
     }
     
 }
示例#6
0
        public Diff(object a, object b)
        {
            if (a.GetType() != b.GetType())
            {
                throw new InvalidOperationException("Can't diff objects of different types");
            }

            _root = DiffNode(a, b, a.GetType());
        }
示例#7
0
 /// <summary>
 /// Add a child to this node
 /// </summary>
 public void AddChild(IDiffNode child)
 {
     if (Children == null)
     {
         Children = new List <IDiffNode>();
     }
     child.Parent = this;
     Children.Add(child);
 }
示例#8
0
        /// <summary>
        /// Process a diff node of xmlschemaelement
        /// </summary>
        /// <param name="rootNode"></param>
        private void CopyChildNodes(XmlSchemaComplexType type, IDiffNode parent, Stack<String> typeStack, bool quickSearch)
        {
            if (type == null || typeStack.Contains(type.Name))
                return;
            typeStack.Push(type.Name);

            IDiffNode idn = null;
            if (currentDiffNodes.TryGetValue(type.ToString(), out idn) && quickSearch)
            {
                // Validator
                typeStack.Pop(); // Pop off
                if (idn.Children != null)
                {
                    foreach (var child in idn.Children)
                        parent.AddChild(child.Clone());
                }
                return;
            }
            else if(quickSearch)
                currentDiffNodes.Add(type.ToString(), parent);

            // Process base content
            if (type.BaseClass != null && type.BaseClass is XmlSchemaComplexType)
                CopyChildNodes(type.BaseClass as XmlSchemaComplexType, parent, typeStack, false);

            foreach (XmlSchemaAttribute att in type.Attributes)
            {
                if (!att.Prohibited && (parent.Children == null || parent.Children.Find(o => o.FriendlyName == att.Name) == null))
                {
                    parent.AddChild(new AttributeDiffNode() { Original = att });
                }
                else if(parent.Children != null) // prohibited use, if it was declared in previous class lets remove it!
                {
                    IDiffNode foundNode = parent.Children.Find(o => o.FriendlyName == att.Name);
                    parent.Children.Remove(foundNode);
                }
            }

            // Process the type
            if (type.Content is XmlSchemaSequence)
                CopyChildNodes(type.Content as XmlSchemaSequence, parent, typeStack);
            else if (type.Content is XmlSchemaChoice)
                CopyChildNodes(type.Content as XmlSchemaChoice, parent, typeStack);

            if (type.Mixed && parent.Children != null && parent.Children.Find(o => o is MixedContentDiffNode) == null)
                parent.AddChild(new MixedContentDiffNode() { Original = type });


            string s = typeStack.Pop();
            System.Diagnostics.Debug.Assert(s.Equals(type.Name));

        }
示例#9
0
        /// <summary>
        /// Clone this object
        /// </summary>
        /// <returns></returns>
        public IDiffNode Clone()
        {
            IDiffNode retVal = MemberwiseClone() as IDiffNode;

            if (Children != null)
            {
                retVal.Children = new List <IDiffNode>();
                foreach (var child in Children)
                {
                    retVal.AddChild(child.Clone());
                }
            }

            return(retVal);
        }
示例#10
0
        /// <summary>
        /// Item has been selected
        /// </summary>
        private void trvOverview_AfterSelect(object sender, TreeViewEventArgs e)
        {
            // Display what has changed
            if (!(e.Node.Tag is IDiffNode))
            {
                return;
            }

            IDiffNode difference = e.Node.Tag as IDiffNode;

            switch (difference.Type)
            {
            case DiffType.Added:
                lblDifference.Text = String.Format("'{0}' appears in new schema, but not in old schema", difference.FriendlyName);
                break;

            case DiffType.Removed:
                lblDifference.Text = string.Format("'{0}' appears in old schema, but not in new schema", difference.FriendlyName);
                break;

            case DiffType.ChildDifferent:
                lblDifference.Text = String.Format("At this level, '{0}' is the same in both schemas, however a child node has been changed", difference.FriendlyName);
                break;

            case DiffType.TypeChanged:
                lblDifference.Text = String.Format("'{0}' shares the same name in both schemas, but the data type has been changed from '{1}' to '{2}' (child differences noted)", difference.FriendlyName, difference.ChangeDetails[0], difference.ChangeDetails[1]);
                break;

            case DiffType.FixedChanged:
                lblDifference.Text = string.Format("The fixed value of '{0}' has changed from '{1}' to '{2}'", difference.FriendlyName, difference.ChangeDetails[0], difference.ChangeDetails[1]);
                break;

            case DiffType.Namespace:
                lblDifference.Text = string.Format("'{0}' is the same in both schemas but the namespace changes from '{1}' to '{2}'", difference.FriendlyName, difference.ChangeDetails[0], difference.ChangeDetails[1]);
                break;

            case DiffType.None:
                lblDifference.Text = "Node is identical in both schemas";
                break;
            }

            // Set the grid view
            schemaObjectA.SchemaObject = difference.GetOriginalNode();
            schemaObjectB.SchemaObject = difference.GetComparedNode();

            SelectedObject = difference;
        }
示例#11
0
        private void copyToClipboardToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (trvObjectView.SelectedNode == null)
            {
                return;
            }

            // Get the diff node
            IDiffNode idn = trvObjectView.SelectedNode.Tag as IDiffNode;

            if (idn == null)
            {
                return;
            }

            Clipboard.SetText(BuildXpath(trvObjectView.SelectedNode));
        }
示例#12
0
        /// <summary>
        /// Adds a child to this node and preserves its sequence order
        /// </summary>
        public void AddChildPreserveOrder(IDiffNode child)
        {
            if (Children == null)
            {
                Children = new List <IDiffNode>();
            }

            // Now time to preserve!
            if (child.Parent == null)
            {
                Children.Add(child);
            }
            else
            {
                // Find the node that appeard prior to this child in the original tree
                int idx = child.Parent.Children.IndexOf(child);
                if (idx > 0)
                {
                    IDiffNode dn = null;
                    int       fi = -1;
                    while (fi == -1 && idx > 0)
                    {
                        idx--;
                        dn = child.Parent.Children[idx];
                        fi = Children.FindIndex(o => o.FullName == dn.FullName); // find the index of the same node in this file ..
                    }

                    // Could we find a reference?
                    if (fi == -1) // nope, so add
                    {
                        Children.Add(child);
                    }
                    else
                    {
                        Children.Insert(fi + 1, child);
                    }
                }
                else  // Appears first
                {
                    Children.Insert(0, child);
                }
            }
        }
示例#13
0
        /// <summary>
        /// Copy element data
        /// </summary>
        private void CopyChildNodes(XmlSchemaElement element, IDiffNode parent, Stack<String> typeStack)
        {
            if (element.MaxOccurs == "0")
            {
                if (parent.Children != null)
                {
                    IDiffNode foundNode = parent.Children.Find(o => o.FriendlyName == element.Name);
                    parent.Children.Remove(foundNode);
                }
                return;
            }
            else if (parent.Children != null &&
                parent.Children.Find(o => o.FriendlyName == element.Name) != null)
                return;

            ElementDiffNode rootNode = new ElementDiffNode() { Original = element };
            if (rootNode.Original.SchemaType is XmlSchemaComplexType)
                CopyChildNodes(rootNode.Original.SchemaType as XmlSchemaComplexType, rootNode, typeStack, true);
            parent.AddChild(rootNode);
        }
示例#14
0
        private void trvObjectView_AfterSelect(object sender, TreeViewEventArgs e)
        {
            // Get the diff node
            IDiffNode idn = e.Node.Tag as IDiffNode;

            if (idn == null)
            {
                return;
            }

            // Set the selected object
            this.SelectedObject = idn;
            if (!ShowXpath)
            {
                return;
            }
            // Show the XPath
            txtXPath.Text           = BuildXpath(e.Node);
            txtXPath.SelectionStart = txtXPath.Text.Length;
        }
示例#15
0
        /// <summary>
        /// Copy child nodes for a choice
        /// </summary>
        private void CopyChildNodes(XmlSchemaChoice choice, IDiffNode parent, Stack<String> typeStack)
        {
            if (choice.Content == null || choice.Content.Count == 0) return;

            ChoiceDiffNode chcNode = new ChoiceDiffNode()
            {
                Original = choice
            };
            // Build the children of this 
            foreach (XmlSchemaObject child in choice.Content)
                if (child is XmlSchemaChoice)
                    CopyChildNodes(child as XmlSchemaChoice, chcNode, typeStack);
                else if (child is XmlSchemaSequence)
                    CopyChildNodes(child as XmlSchemaSequence, chcNode, typeStack);
                else if (child is XmlSchemaElement)
                    CopyChildNodes(child as XmlSchemaElement, chcNode, typeStack);
                else if (child is XmlSchemaAny)
                    chcNode.AddChild(new DiffNode<XmlSchemaAny>() { Original = child as XmlSchemaAny });

            // Don't duplicate on structure
            if (parent.Children == null || FindProbableCandidate(parent.Children, chcNode) == null)
                parent.AddChild(chcNode);
        }
示例#16
0
        private void CompareNodes(List<IDiffNode> haystack, IDiffNode needle, IDiffNode parent)
        {
            // Comparing
            if (Comparing != null)
                Comparing(this, -1.0f);
            switch (needle.TypeName)
            {
                case "XmlSchemaChoice":
                    var haystackNeedleChoice = from node in haystack
                                               where node.TypeName == "XmlSchemaChoice"
                                               select node;
                    // If there was only one other choice in the haystack, then we can assume these are the same choices and process them
                    if (haystackNeedleChoice.Count() == 1)
                    {
                        foreach (var node in haystackNeedleChoice)
                        {
                            node.SetData(node.GetOriginalNode(), needle.GetOriginalNode());
                            CompareNodes(node.Children, needle.Children, node);
                            break;
                        }
                    }
                    else // A little more complicated how can we tell if A.Choice1 matches B.Choice1 vs A.Choice2 and b.Choice1 if 
                    // something has been added... We need to find the most probable match
                    {
                        DiffNode<XmlSchemaChoice> cdn = FindProbableCandidate(haystackNeedleChoice, needle);
                        if (cdn == null) // This choice has been added
                        {
                            // Everything underneath of this needle is also "added"
                            SwapContent(needle);

                            // Add the "added record" to the parent
                            if (parent != null)
                                parent.AddChildPreserveOrder(needle);
                        }
                        else
                        {
                            cdn.SetData(cdn.GetOriginalNode(), needle.GetOriginalNode());
                            CompareNodes(cdn.Children, needle.Children, cdn);
                        }
                    }
                    break;
                case "XmlSchemaObject": // Mixed Content
                    var haystackNeedleAny = from node in haystack
                                            where node.TypeName == "XmlSchemaObject"
                                            select node;

                    // If there was only one other choice in the haystack, then we can assume these are the same choices and process them
                    if (haystackNeedleAny.Count() > 0)
                    {
                        foreach (var node in haystackNeedleAny)
                        {
                            node.SetData(node.GetOriginalNode(), needle.GetOriginalNode());
                            break;
                        }
                    }
                    break;
                default:
                    // Can we find the needle in the haystack?
                    var haystackNeedle = from node in haystack
                                         where needle.FriendlyName.Equals(node.FriendlyName) && node.TypeName == needle.TypeName
                                         select node;
                    if (haystackNeedle.Count() == 0) // We couldn't find the needle in the haystack, so the needle was added
                    {
                        // Everything underneath of this needle is also "added"
                        SwapContent(needle);

                        // Add the "added record" to the parent
                        if (parent != null)
                            parent.AddChildPreserveOrder(needle);
                    }
                    else // We found the needle in the haystack, the needle represents the "original"
                        foreach (var node in haystackNeedle)
                        {
                            node.SetData(node.GetOriginalNode(), needle.GetOriginalNode());
                            CompareNodes(node.Children, needle.Children, node);
                            break;
                        }
                    break;
            }
        }
示例#17
0
        /// <summary>
        /// Find a probable candidate for match 
        /// </summary>
        private DiffNode<XmlSchemaChoice> FindProbableCandidate(IEnumerable<IDiffNode> haystackNeedleChoice, IDiffNode needle)
        {
            bool wasChoiceFound = false;
            foreach (IDiffNode candidate in haystackNeedleChoice)
            {
                if (candidate.TypeName != "XmlSchemaChoice") continue;

                wasChoiceFound = true;

                if (candidate.Children == null && needle.Children == null) // best we can do as children don't exist
                    return candidate as ChoiceDiffNode;
                else if (candidate.Children != null && needle.Children != null) // More details analisys
                {
                    // If we find all children originally in the choice in the new choice, we have a good match
                    int childrenInNeedle = 0;
                    foreach (IDiffNode child in candidate.Children)
                    {
                        bool foundChildInNeedle = false;
                        foreach (IDiffNode nChild in needle.Children)
                            foundChildInNeedle |= child.FullName.Equals(nChild.FullName); // We found an instance of the candidate child in the needle
                        childrenInNeedle += (int)Convert.ToUInt32(foundChildInNeedle);
                    }

                    if (childrenInNeedle == candidate.Children.Count) // we found all children of the original in the compared so it is a good match
                        return candidate as ChoiceDiffNode;

                    // The same is true for the reverse
                    childrenInNeedle = 0;
                    foreach (IDiffNode nChild in needle.Children)
                    {
                        bool foundNeedleInCandidate = false;
                        foreach (IDiffNode child in candidate.Children)
                            foundNeedleInCandidate |= child.FullName.Equals(nChild.FullName);
                        childrenInNeedle += (int)Convert.ToUInt32(foundNeedleInCandidate);
                    }

                    if (childrenInNeedle == needle.Children.Count)
                        return candidate as ChoiceDiffNode;
                }
            }

            return null;
        }
示例#18
0
 public ObjectDiffNodeMember(string name, IDiffNode node)
 {
     Name = name;
     Node = node;
 }
示例#19
0
 public IEnumerableDiffNodeItem(int index, IDiffNode node)
 {
     Index = index;
     Node  = node;
 }
示例#20
0
 /// <summary>
 /// Compare a list of needles to a the haystack
 /// </summary>
 private void CompareNodes(List<IDiffNode> haystack, List<IDiffNode> needles, IDiffNode parent)
 {
     foreach (IDiffNode node in needles ?? new List<IDiffNode>())
         CompareNodes(haystack, node, parent);
 }