如何使用linq to xml在两个不同的xml文件中查找匹配的节点 [英] How do you use linq to xml to find matching nodes in two different xml files

查看:80
本文介绍了如何使用linq to xml在两个不同的xml文件中查找匹配的节点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚刚问了另一个问题

I just asked another question here and the answer was spot on.

但这解决了本质上的语法问题.现在,我需要有关实际解决方案的帮助.

But that addressed what was essentially a syntax problem. Now I need help with an actual resolution.

这与上一个问题中的代码相同(已修复并添加了东西).

This is the same code from the previou question (fixed up and with stuff added).

XElement FILE1 = XElement.Load (@"..\FILE1.XML");
XElement FILE2 = XElement.Load (@"..\FILE2.XML");

var orders = from file1 in FILE1.Descendants("Players").Elements("Player")
                        select new {
                            name=new {
                                clientID=ulm.Element("ClientID").Value,
                                firstName=file1.Element("FirstName").Value,
                                lastName=file1.Element("LastName").Value
                            }                           
                        };

var orders2 = 
             from file2 in FILE2.Descendants("Players").Elements("Player")
                        select new {
                            name=new {
                                clientID=ulm.Element("ClientID").Value,
                                firstName=file2.Element("FirstName").Value,
                                lastName=file2.Element("LastName").Value
                            }                           
                        };

var matchingResults = from i in orders from j in orders2 where (i.name.firstName==j.name.firstName && i.name.lastName==j.name.lastName)
                            select i;
matchingResults.Dump()     

为了使它有趣,我在尝试将它们匹配之前,已向每个序列结果添加了一个ClientID.

To make it interesting I have added a ClientID to each sequence result before trying to match them up.

我需要知道的是来自orders EXISTS的Player节点是否来自orders2的player节点.还是不存在?理想情况下,我还可以为NOT EXISTS/EXISTS检查选择选择标准. (姓氏或名字和姓氏,或仅ClientID等)

What I need is to know does a Player node from order EXISTS in a player node from orders2. Or does it NOT EXIST? Ideally I would also be able to CHOOSE the selection criteria for the NOT EXISTS/EXISTS check. (LastName, or FirstName && LastName, or ClientID only, etc.)

我不知道如何进行此操作.谢谢你的帮助.

I have NO IDEA how to go about this. Thanks for your help.

推荐答案

我第二个Ahmed KRAIEM建议使用IntersectExcept

I second Ahmed KRAIEM's suggestion to use Intersect or Except

这是另一种解决方案,可让您使用任意的lambda进行比较:

Here's another solution that lets you compare using any arbitrary lambda:

void Main()
{
XElement FILE1 = XElement.Parse(
@"<Root>
    <Players>
        <Player><ClientId>1</ClientId><FirstName>Bob</FirstName><LastName>Smith</LastName></Player>
        <Player><ClientId>2</ClientId><FirstName>John</FirstName><LastName>Smith</LastName></Player>
    </Players>
</Root>");
    XElement FILE2 = XElement.Parse(
@"<Root>
    <Players>
        <Player><ClientId>2</ClientId><FirstName>Bob</FirstName><LastName>Smith</LastName></Player>
        <Player><ClientId>3</ClientId><FirstName>Mike</FirstName><LastName>Smith</LastName></Player>
    </Players>
</Root>");

var orders = from file1 in FILE1.Descendants("Players").Elements("Player")
                    select new Player(Int32.Parse(file1.Element("ClientId").Value), file1.Element("FirstName").Value, file1.Element("LastName").Value);

var orders2 = from file2 in FILE2.Descendants("Players").Elements("Player")
                    select new Player(Int32.Parse(file2.Element("ClientId").Value), file2.Element("FirstName").Value, file2.Element("LastName").Value);

//orders.Dump();
//orders2.Dump();

var exists = orders2.Intersect(orders, new LambdaEqualityComparer<Player>((i, j) => i.FirstName == j.FirstName && i.LastName == j.LastName));
// or
//var exists = orders2.Intersect(orders, new LambdaEqualityComparer<Player>((i, j) => i.ClientId == j.ClientId));
exists.Dump();

var notExists = orders2.Except(orders, new LambdaEqualityComparer<Player>((i, j) => i.FirstName == j.FirstName && i.LastName == j.LastName));
// or
//var notExists = orders2.Except(orders, new LambdaEqualityComparer<Player>((i, j) => i.ClientId == j.ClientId));
notExists.Dump();
}

public class Player
{
public int ClientId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }

public Player(int clientId, string firstName, string lastName)
{
    ClientId = clientId;
    FirstName = firstName;
    LastName = lastName;
}
}

public class LambdaEqualityComparer<T> : IEqualityComparer<T>
{
private Func<T, T, bool> EqualityComparer { get; set; }

public LambdaEqualityComparer(Func<T, T, bool> equalityComparer)
{
    EqualityComparer = equalityComparer;
}

public bool Equals(T x, T y)
{
    return EqualityComparer(x, y);
}

public int GetHashCode(T obj)
{
    // If the hash codes are different, then Equals never gets called. Make sure Equals is always called by making sure the hash codes are always the same.
    // (Underneath, the .NET code is using a set and the not (!) of a Find method to determine if the set doesn't already contain the item and should be added.
    // Find is not bothering to call Equals unless it finds a hash code that matches.)
    //return obj.GetHashCode();
    return 0;
}
}

请注意,如果您不想创建Player对象,则可以将其完全删除,像以前一样在ordersorders2中填充匿名对象,并创建new LambdaEqualityComparer<dynamic>而不是new LambdaEqualityComparer<Player>,尽管它会由于动态调用而变慢.

Note that if you don't want to create a Player object, you can remove it completely, populate your anonymous objects in orders and orders2 just like you were doing before, and create a new LambdaEqualityComparer<dynamic> instead of new LambdaEqualityComparer<Player>, though it will be slower due to reflection calls on dynamic.

这篇关于如何使用linq to xml在两个不同的xml文件中查找匹配的节点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆