XMLDiff / XMLUnit - Ignore Child Order & use of wildcards

1.8k views Asked by At

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.

2

There are 2 answers

2
Liquid Core On

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.

0
M. Bartosh On

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);