private void BuildChildrenElementResponses(ComparisonXmlElement toCompare, List <AreEquivalentResponse> responses)
        {
            //Compare all children elements
            //Are they missing elements?
            var missingElementsOnPrimary    = Children.Keys.Except(toCompare.Children.Keys);
            var missingElementsOnComparison = toCompare.Children.Keys.Except(Children.Keys);

            if (missingElementsOnPrimary.Any())
            {
                responses.Add(new AreEquivalentResponse(false,
                                                        String.Format("{0}/-> Elements missing from document: {1}", GetFullPath(),
                                                                      missingElementsOnPrimary.Aggregate((x, y) => x + ", " + y))));
            }
            if (missingElementsOnComparison.Any())
            {
                responses.Add(new AreEquivalentResponse(false,
                                                        String.Format("{0}/-> Elements missing from document: {1}", toCompare.GetFullPath(),
                                                                      missingElementsOnComparison.Aggregate((x, y) => x + ", " + y))));
            }

            //Are the elements equivalent?
            foreach (var child in Children)
            {
                ComparisonXmlElement toCompareChild;
                toCompare.Children.TryGetValue(child.Key, out toCompareChild);
                if (toCompareChild == null)
                {
                    continue;
                }

                var response = child.Value.IsElementEquivalent(toCompareChild);

                responses.AddRange(response);
            }
        }
        public ComparisonXmlElement(XElement actualElement, ComparisonConfiguration config, ComparisonXmlElement parentElement = null)
        {
            ActualElement = actualElement;
            Config        = config;
            ParentElement = parentElement;

            Attributes = actualElement.Attributes().ToDictionary(x => x.Name.ToString().ToLower(), x => new ComparisonXmlAttribute(x, this, Config));
            Children   = BuildChildren(actualElement);
        }
        public IList <AreEquivalentResponse> IsElementEquivalent(ComparisonXmlElement toCompare)
        {
            var responses = new List <AreEquivalentResponse>();

            BuildSelfElementResponses(toCompare, responses);
            BuildAttributeResponses(toCompare, responses);
            BuildChildrenElementResponses(toCompare, responses);

            return(responses);
        }
        private void BuildSelfElementResponses(ComparisonXmlElement toCompare, List <AreEquivalentResponse> responses)
        {
            var toCompareElement = toCompare.ActualElement;

            if (ActualElement.Name.ToString() != toCompareElement.Name.ToString())
            {
                responses.Add(new AreEquivalentResponse(false,
                                                        String.Format("{0}/-> Element name incorrect. Expected <{1}>, but was <{2}>", GetFullPath(),
                                                                      ActualElement.Name, toCompareElement.Name)));
            }

            //Value concatenates all element values. We want to ensure that it's an element at the leaf, without any children elements, then we can do a value check
            if (!ActualElement.HasElements && ActualElement.Value != toCompareElement.Value)
            {
                responses.Add(new AreEquivalentResponse(false,
                                                        String.Format("{0}/-> VALUE is incorrect. Expected {1}, but was {2}", GetFullPath(), ActualElement.Value,
                                                                      toCompareElement.Value)));
            }
        }
        private void BuildAttributeResponses(ComparisonXmlElement toCompare, List <AreEquivalentResponse> responses)
        {
            var missingAttributesOnPrimary = Attributes.Keys.Except(toCompare.Attributes.Keys);

            if (missingAttributesOnPrimary.Any())
            {
                responses.Add(new AreEquivalentResponse(false,
                                                        String.Format("{0}/-> Attributes missing: {1}", GetFullPath(),
                                                                      missingAttributesOnPrimary.Aggregate((x, y) => x + ", " + y))));
            }
            var missingAttributesOnComparison = toCompare.Attributes.Keys.Except(Attributes.Keys);

            if (missingAttributesOnComparison.Any())
            {
                responses.Add(new AreEquivalentResponse(false,
                                                        String.Format("{0}/-> Attributes missing: {1}", toCompare.GetFullPath(),
                                                                      missingAttributesOnComparison.Aggregate((x, y) => x + ", " + y))));
            }

            var toCompareAttributes = toCompare.Attributes;

            foreach (var attribute in Attributes)
            {
                ComparisonXmlAttribute toCompareAttribute;
                toCompareAttributes.TryGetValue(attribute.Key, out toCompareAttribute);
                if (toCompareAttribute == null)
                {
                    continue;
                }

                var response = attribute.Value.AreAttributesEquivalent(toCompareAttribute);

                if (response.Equivalent)
                {
                    continue;
                }
                responses.Add(response);
            }
        }
        public string Compare(string expectedDocument, string comparisonDocument)
        {
            var expectedXmlText     = expectedDocument;
            var comparisonXmlText   = comparisonDocument;
            var stringPreProcessors = new List <StringPreProcessor>
            {
                new ClearXmlnsAttributeStringPreProcessor()
            };

            foreach (var stringPreProcessor in stringPreProcessors)
            {
                expectedXmlText   = stringPreProcessor.Process(expectedXmlText);
                comparisonXmlText = stringPreProcessor.Process(comparisonXmlText);
            }

            var expectedXmlDoc   = XElement.Parse(expectedXmlText);
            var comparisonXmlDoc = XElement.Parse(comparisonXmlText);
            var xmlPreProcessors = new List <XmlPreProcessor>
            {
                new AddSchemaToTableAttributeXmlPreProcessor(),
                new RemoveAttributesFromXmlPreProcessor(_attributesToIgnore),
                new PromoteElementToAttributeXmlPreProcessor(XName.Get("column"), XName.Get("name"))
            };

            foreach (var xmlPreProcessor in xmlPreProcessors)
            {
                expectedXmlDoc   = xmlPreProcessor.Process(expectedXmlDoc);
                comparisonXmlDoc = xmlPreProcessor.Process(comparisonXmlDoc);
            }

            var rootOne = new ComparisonXmlElement(expectedXmlDoc, new ComparisonConfiguration("expectedDoc"));
            var rootTwo = new ComparisonXmlElement(comparisonXmlDoc, new ComparisonConfiguration("comparisonDoc"));

            var results = rootOne.IsElementEquivalent(rootTwo);

            return(results.Any()
                ? results.Where(x => !x.Equivalent).Select(x => "- " + x.Reason).Aggregate((x, y) => x + Environment.NewLine + y)
                : "No differences detected.");
        }
 public ComparisonXmlAttribute(XAttribute attribute, ComparisonXmlElement parentElement, ComparisonConfiguration parentDocument)
 {
     Attribute      = attribute;
     ParentElement  = parentElement;
     ParentDocument = parentDocument;
 }