簡體   English   中英

如何使用linq to xml在兩個不同的xml文件中查找匹配的節點

[英]How do you use linq to xml to find matching nodes in two different xml files

我只是在這里問了另一個問題,答案就在現場。

但這解決了本質上的語法問題。 現在,我需要有關實際解決方案的幫助。

這與之前的問題中的代碼相同(已修復並添加了內容)。

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。

我需要知道的是orders2的玩家節點中的訂單EXISTS中的玩家節點。 還是不存在? 理想情況下,我還可以為NOT EXISTS / EXISTS檢查選擇選擇標准。 (姓氏或名字&&姓氏,或僅ClientID等)

我沒有想法如何去做。 謝謝你的幫助。

  • 使用Enumerable.IntersectEnumerable.Except
  • 使用具體類型而不是匿名類型。
  • 為了能夠選擇選擇標准,您可以創建一個參數化的IEqualityComparer<Client>

     class Client { public string ClientID { get; set; } public string FirstName { get; set; } public string LastName { get; set; } } [Flags] enum Criteria { ClientID, FirstName, LastName } class ClientEqualityComparer : IEqualityComparer<Client> { private Criteria criteria; public ClientEqualityComparer(Criteria criteria) { this.criteria = criteria; } #region IEqualityComparer<Client> Membres public bool Equals(Client x, Client y) { if (criteria.HasFlag(Criteria.ClientID) && x.ClientID != y.ClientID) return false; if (criteria.HasFlag(Criteria.FirstName) && x.FirstName != y.FirstName) return false; if (criteria.HasFlag(Criteria.LastName) && x.LastName != y.LastName) return false; return true; } public int GetHashCode(Client obj) { int hash = 17; if (criteria.HasFlag(Criteria.ClientID)) hash = hash * 31 + obj.ClientID; if (criteria.HasFlag(Criteria.FirstName)) hash = hash * 31 + obj.FirstName; if (criteria.HasFlag(Criteria.LastName)) hash = hash * 31 + obj.LastName; } #endregion } static void Main(string[] args) { IEnumerable<Client> orders; IEnumerable<Client> orders2; //... var matchingIdFn = orders.Intersect(orders2, new ClientEqualityComparer(Criteria.ClientID | Criteria.FirstName)); var matchingIdFnLn = orders.Intersect(orders2, new ClientEqualityComparer(Criteria.ClientID | Criteria.FirstName | Criteria.LastName)); var different = orders.Except(orders2, new ClientEqualityComparer(Criteria.ClientID | Criteria.FirstName)); } 

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

我同意艾哈邁德·克萊姆(Ahmed KRAIEM)使用IntersectExcept的建議

這是另一個解決方案,可讓您使用任意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> ,但由於動態調用會導致速度變慢。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM