简体   繁体   中英

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?

If you have multiple segments create a method to compare them

Private Function ChkSeg(segment As XElement) As Boolean
    If segment.<Start>.<Master>.Value = segment.<End>.<Master>.Value AndAlso
         segment.<Start>.<Slave>.Value = segment.<End>.<Slave>.Value Then
        Return True
    Else
        Return False
    End If
End Function

then iterate the XML like this

    For Each el As XElement In xe.Elements
        If ChkSeg(el) Then
            Stop
        Else
            Stop
        End If
    Next

Tested using this

    Dim xe As XElement

    xe = <segments>
             <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>
             <Segment>
                 <IdRef>1</IdRef>
                 <Start>
                     <Master>0</Master>
                     <Slave>0</Slave>
                     <PntType>4</PntType>
                 </Start>
                 <End>
                     <Master>0</Master>
                     <Slave>0</Slave>
                     <PntType>4</PntType>
                 </End>
                 <Symmetry>0.5</Symmetry>
                 <FunctionType>1</FunctionType>
             </Segment>
         </segments>

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM