1

I am currently struggling with an issue when comparing 2 xmls - original and reference for differences. The trouble is when I try to apply wildcards for comparison with different child order - additionaly those childs may have different number of attributes in a node so the comparison is even harder.

I tried to implement a solution using XMLUnit & XMLDiff libraries for .NET but without any success.

using System;
using Org.XmlUnit.Builder;
using Org.XmlUnit.Diff;
using System.IO;

static void Main(string[] args)
    {
        string orgFilePath = @"C:\Temp\original.xml";
        string refFilePath = @"C:\Temp\reference.xml";

        StreamReader orgStreamReader = new StreamReader(orgFilePath);
        StreamReader refStreamReader = new StreamReader(refFilePath);

        String orgFile = XDocument.Load(orgStreamReader).ToString();
        String refFile = XDocument.Load(refStreamReader).ToString();

        var diff = DiffBuilder
            .Compare(Input.FromString(orgFile))
            .WithTest(Input.FromString(refFile))
            .CheckForSimilar()
            .Build();

        foreach (var d in )
        {
            Console.WriteLine(d.Comparison);
            Console.WriteLine();
        }
        Console.WriteLine(diff.Differences);

        Console.ReadLine();
    }

ref file:

<deviceOrders>
    <deviceOrder>
      <operation>New</operation>
      <moduleId>*</moduleId>
      <net>TST</net>
      <sort>VT</sort>
      <moduleNr>220</moduleNr>
      <deviceNr>0</deviceNr>
    </deviceOrder>
    <deviceOrder>
      <operation>New</operation>
      <moduleId>*</moduleId>
      <net>79ST</net>
      <sort>UP</sort>
      <deviceNr>0</deviceNr>
    </deviceOrder>
</deviceOrders>

org file:

<deviceOrders>
    <deviceOrder>
      <operation>New</operation>
      <moduleId>1235</moduleId>
      <net>79ST</net>
      <sort>UP</sort>
      <deviceNr>0</deviceNr>
    </deviceOrder>
    <deviceOrder>
      <operation>New</operation>
      <moduleId>1234</moduleId>
      <net>TST</net>
      <sort>VT</sort>
      <moduleNr>220</moduleNr>
      <deviceNr>0</deviceNr>
    </deviceOrder>
</deviceOrders>

I didn't find solution yet so please help me with that.

Paul Williams
  • 1,554
  • 7
  • 40
  • 75
codi89
  • 11
  • 2
  • Just a wild idea but maybe it works: You could define a class that mirrors all possible children and attributes, have optional ones nullable, then deserialize both XMLs and serialize them again. You should then have two XMLs with identical structure. – LocEngineer Sep 15 '17 at 12:29

2 Answers2

1

I think it will help you

Diff d = DiffBuilder.Compare(Input.FromFile("doc1.xml"))
                    .WithTest(Input.FromFile("doc2.xml")).WithNodeFilter(x=>!x.Name.Equals("NodeName")).Build();
Assert.IsFalse(d.HasDifferences());

or

ISource control = Input.FromFile("doc1.xml").Build();
ISource test = Input.FromFile("doc2.xml").Build();
IDifferenceEngine diff = new DOMDifferenceEngine();
diff.NodeFilter = x => !x.Name.Equals("NodeName");
diff.DifferenceListener += (comparison, outcome) => {
   Assert.Fail("found a difference: {0}", comparison);
};
diff.Compare(control, test);
M. Bartosh
  • 11
  • 4
0

Try to run this:

using System;
using System.Reflection;
using System.Linq;
using System.Xml.Linq;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            string xml1 = "<?xml version=\"1.0\" encoding=\"UTF - 8\"?> <note> <to>Tove</to> <from>Jani</from> <heading>Reminder</heading> <body>Don't forget me this weekend!</body> </note>";
            string xml2 = "<?xml version=\"1.0\" encoding=\"UTF - 8\"?> <note> <to>dd22</to> <from>Jani</from> <heading>4fewfewe</heading> <body>Don't forget me this weekend!</body> </note>";

            XDocument doc1 = XDocument.Parse(xml1);
            XDocument doc2 = XDocument.Parse(xml2);
            Console.WriteLine("Elements in document 1");
            foreach (string Different in doc1.Elements().Elements().Select(x => x.Value))
            {
                Console.WriteLine("1----"+Different);
            }
            Console.Read();

            Console.WriteLine("Elements in document 2");
            foreach (string Different in doc2.Elements().Elements().Select(x => x.Value))
            {
                Console.WriteLine("2----" + Different);
            }

            Console.Read();

            Console.WriteLine("These are the equal elements, I will discard different ones");
            foreach (string Different in doc1.Elements().Elements().Select(x => x.Value).Intersect(doc2.Elements().Elements().Select(x => x.Value)))
            {
                Console.WriteLine(Different);
            }
            Console.Read();
        }
    }
}

It will retrieve only the equal elements. Modify LINQ in the foreach to obtain what you need.

It does the intersection of the node values at the level of the element operating on its descendants. You can do the same to your xml.

Liquid Core
  • 1
  • 6
  • 27
  • 52
  • This doesn't really solve the issue there. In Your scenario when You launch the intersection this checks only the values which can be the same even in different attributes. The solution must keep the hierarchical character of the XML nodes. But thanks for Your contribution anyway. – codi89 Sep 15 '17 at 13:05
  • @codi89 Maybe you are not aware of the spirit of this community. It's not just hey I wrote this solve pl0x. You can easily keep hierarchical tree and naming with Reflection or XElement name properties and work up the solution easily from the code I wrote for you. It's not hard and you can compare node names and position or retrieve different elements easily given my code – Liquid Core Sep 19 '17 at 07:32