【问题标题】:How to compare two XElement enumerables?如何比较两个 XElement 枚举?
【发布时间】:2016-09-09 13:47:20
【问题描述】:

我有两个大小相等的 XElement 列表:

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

Segment 元素的基本列表,如下所示:

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

我想要的是通过比较 &lt;Master&gt;&lt;Slave&gt; 标签中的值来比较它们是否相等,忽略其余部分。我怎样才能实现它?

【问题讨论】:

  • 你想比较segmentsDatabase[i]和segmentsSlave[i]还是比较segmentsDatabase[i]和segmentsSlave的所有segments?
  • segmentsDatabase[i] with segmentsSlave[i]
  • 开始、结束还是两者兼而有之?
  • 其实两者都有..
  • 数据库和从站的段数是否相同?

标签: c# xml linq xelement


【解决方案1】:

如果您有多个段,请创建一个比较它们的方法

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

然后像这样迭代 XML

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

用这个测试过

    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>

【讨论】:

    【解决方案2】:

    如果想比较Start和End中的Master和Slave标签,可以使用这种方法:

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

    编辑:想要比较已经排序的列表,您可以将一个列表中的第一项与另一个列表中的第一项进行比较,依此类推,您可以使用 LINQ .Zip 方法将 XElements 分组到一个匿名对象中,然后使用LINQ .All 循环遍历项目并进行比较:

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

    就个人而言,我可能会使用 for 循环遍历两个列表并比较每个项目,但如果您想使用单行 LINQ,则可以使用上述方法。

    【讨论】:

    • 我有两个 XElements 列表
    • 我猜列表没有排序?
    • 假设它们的顺序相同,所以我只需要将一个列表中的元素 0 与其他列表中的元素 0 进行比较,等等。我认为可能有一些涉及 LINQ 的方法,它会给我元素从每个列表中,然后我可以使用 .Element(...) 进行比较。
    • Zip 不可用,因为我仅限于 .NET 3.5。你的意思是只使用while循环,例如MoveNext?我认为这可能看起来很难看...现在我正在尝试使用自定义比较器查看 SequenceEqual 是否可以完成这项工作。
    • 是的,您可以在两个集合的迭代器上使用 MoveNext 来完成。您也可以使用 SequenceEqual 来做到这一点,但是正如您所说,您必须创建自己的比较器。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-22
    • 1970-01-01
    • 2012-05-04
    相关资源
    最近更新 更多