Search code examples
c#xmllinqxelement

How to compare two XElement enumerables?


I have two equal sized lists of XElements:

var documentDatabase = XDocument.Parse(xmlDatabase);
var rootElementDatabase = documentDatabase.Root;
var segmentsDatabase = rootElementDatabase.Descendants("Segment");

var documentSlave = XDocument.Parse(xmlSlave);
var rootElementSlave = documentSlave.Root;
var segmentsSlave = rootElementSlave.Descendants("Segment");

Basically list of Segment elements, like below:

        <Segment>
            <IdRef>1</IdRef>
            <Start>
                <Master>0</Master>
                <Slave>0</Slave>
                <PntType>4</PntType>
            </Start>
            <End>
                <Master>10.059000</Master>
                <Slave>29.450302</Slave>
                <PntType>4</PntType>
            </End>
            <Symmetry>0.5</Symmetry>
            <FunctionType>1</FunctionType>
        </Segment>

What I want is to compare whether they equal by comparing values in <Master> and <Slave> tags, ignoring the rest. How can I achieve it?


Solution

  • If you want to compare the Master and Slave tags in both the Start and the End, you can use this method:

    bool CompareXmls(XElement first, XElement second)
    {
            var firstStart = first.Element("Start");
            var firstEnd = first.Element("End");
            var firstStartMaster = firstStart.Element("Master").Value;
            var firstStartSlave = firstStart.Element("Slave").Value;
            var firstEndMaster = firstEnd.Element("Master").Value;
            var firstEndSlave = firstEnd.Element("Slave").Value;
    
            var secondStart = second.Element("Start");
            var secondEnd = second.Element("End");
            var secondStartMaster = secondStart.Element("Master").Value;
            var secondStartSlave = secondStart.Element("Slave").Value;
            var secondEndMaster = secondEnd.Element("Master").Value;
            var secondEndSlave = secondEnd.Element("Slave").Value;
    
            bool areEqual = firstStartMaster == secondStartMaster
                && firstStartSlave == secondStartSlave
                && firstEndMaster == secondEndMaster
                && firstEndSlave == secondEndSlave;
    
            return areEqual;
        }
    

    EDIT: Wanting to compare lists which are already sorted and you can compare first item from one list with first item from other list and so on, you can use LINQ .Zip method to group the XElements into one anonymous object and then using LINQ .All cycle through the items and compare:

    var res = firstList.Zip(secondList, (a, b) => new { First = a, Second = b }).All(x=>CompareXmls(x.First,x.Second));
    

    Personally, I would probably use a for loop to iterate over the two lists and compare each item, but if you want to use a one-liner LINQ, you can use the said methods.