C# LINQ到XML-根据与另一个XElement相比的节点值筛选XElement?

C# LINQ到XML-根据与另一个XElement相比的节点值筛选XElement?,c#,xml,linq,C#,Xml,Linq,我想从B中选择佣金元素,其中每个佣金元素的ID值不等于A佣金元素 以下是我完整的主要方法: static void Main(string[] args) { XElement A = XElement.Parse( @"<CONTRACT> <COMMISSION> <ID>1</ID>

我想从B中选择佣金元素,其中每个佣金元素的ID值不等于A佣金元素

以下是我完整的主要方法:

    static void Main(string[] args)
    {
        XElement A = XElement.Parse(
            @"<CONTRACT>
                <COMMISSION>
                    <ID>1</ID>
                    <PRODUCTS>
                        <PRODUCT>A</PRODUCT>
                        <PRODUCT>B</PRODUCT>
                    </PRODUCTS>
                </COMMISSION>
                <COMMISSION>
                    <ID>2</ID>
                    <PRODUCTS>
                        <PRODUCT>C</PRODUCT>
                        <PRODUCT>D</PRODUCT>
                    </PRODUCTS>
                </COMMISSION>
                <COMMISSION>
                    <ID>3</ID>
                    <PRODUCTS>
                        <PRODUCT>E</PRODUCT>
                        <PRODUCT>F</PRODUCT>
                    </PRODUCTS>
                </COMMISSION>
            </CONTRACT>");

        XElement B = XElement.Parse(
            @"<CONTRACT>
                <COMMISSION>
                    <ID>3</ID>
                    <PRODUCTS>
                        <PRODUCT>E</PRODUCT>
                        <PRODUCT>F</PRODUCT>
                    </PRODUCTS>
                </COMMISSION>
            </CONTRACT>");

        // This *should* only return COMMISSION elements from B.
        // Rather, it returns the same B COMMISSION twice: once for the COMMISSION
        // element (ID=3) in B, and once for the COMMISSION element (ID=3) in A. 
        var bOnly =
            from excluded in A.Descendants("COMMISSION")
            let included = 
                from b in B.Descendants("COMMISSION")
                where b.Element("ID").Value != excluded.Element("ID").Value
                select b
            select new XElement("CONTRACT", included);

        // Print results 
        foreach (var v in bOnly)            
        {
            Console.WriteLine(v);
        }

        Console.ReadLine();
    }
static void Main(字符串[]args)
{
XElement A=XElement.Parse(
@"
1.
A.
B
2.
C
D
3.
E
F
");
XElement B=XElement.Parse(
@"
3.
E
F
");
//此*应*仅从B返回佣金元素。
//相反,它两次返回相同的B佣金:一次用于佣金
//B中的元素(ID=3)和A中的佣金元素(ID=3)各一次。
骨变=
从A.A.中排除(“佣金”)
包括在内=
b.后代中的b(“佣金”)
其中b.Element(“ID”).Value!=排除的.Element(“ID”).Value
选择b
选择新合同(“合同”,包括在内);
//打印结果
foreach(骨中的v型变量)
{
控制台写入线(v);
}
Console.ReadLine();
}
正如我在代码中所述,不是获得所需的输出:

            <CONTRACT>
                <COMMISSION>
                    <ID>3</ID>
                    <PRODUCTS>
                        <PRODUCT>E</PRODUCT>
                        <PRODUCT>F</PRODUCT>
                    </PRODUCTS>
                </COMMISSION>
            </CONTRACT>

3.
E
F
我得到:

        <CONTRACT>
            <COMMISSION>
                <ID>3</ID>
                <PRODUCTS>
                    <PRODUCT>E</PRODUCT>
                    <PRODUCT>F</PRODUCT>
                </PRODUCTS>
            </COMMISSION>
        </CONTRACT>
        <CONTRACT>
            <COMMISSION>
                <ID>3</ID>
                <PRODUCTS>
                    <PRODUCT>E</PRODUCT>
                    <PRODUCT>F</PRODUCT>
                </PRODUCTS>
            </COMMISSION>
        </CONTRACT>
        <CONTRACT/>

3.
E
F
3.
E
F
我不知道为什么返回两次佣金w/ID=3。救命啊!非常感谢。请记住,ID是我要比较的唯一元素值。如果A的ID=3与B的ID=3有不同的产品,那么我希望我的结果不会显示任何东西

我的最终解决方案:

           // Question: How do I only get COMMISSIONs from B that aren't in A?
        // Requirement: I only want to compare ID between A and B COMMISSION sets, 
        //   so if A ID=3 has products that are different from B ID=3, the query treats the
        //   two COMMISSIONs as the same so long as their ID is the same.
        // Answer: (Steps 1 thru 3)        

        // Step 1) Get COMMISSIONs from B equalling COMMISSIONs from A on ID       
        var same =
            from a in A.Descendants("COMMISSION")
            join b in B.Descendants("COMMISSION")
            on a.Element("ID").Value equals b.Element("ID").Value
            select a;

        // Step 2) Get all COMMISSIONs from B
        var all = from b in B.Descendants("COMMISSION")
                    select b;

        // Step 3) Get COMMISSIONs that are only in B
        var different = all.Cast<XNode>().Except(same.Cast<XNode>(), new XNodeEqualityComparer());

        // Print results 
        foreach (var v in different)            
        {
            Console.WriteLine(v);
        }
//问题:如何仅从B获得不在A中的佣金?
//要求:我只想比较A和B佣金组之间的ID,
//因此,如果ID=3的产品与B ID=3的产品不同,则查询将处理
//只要他们的ID相同,两个佣金就相同。
//回答:(步骤1至3)
//步骤1)从B获得佣金等于从A获得ID上的佣金
变量相同=
从a.a.中的“佣金”
加入b.b.(“委员会”)
在a元素(“ID”)上,值等于b元素(“ID”)值
选择一个;
//步骤2)从B获得所有佣金
var all=来自b.b中的b(“佣金”)
选择b;
//步骤3)获得仅在B中的佣金
var different=all.Cast()。除了(相同的.Cast(),新的XNodeEqualityComparer());
//打印结果
foreach(不同类型的var v)
{
控制台写入线(v);
}

我已将您的LINQ查询更改为以下内容

var bOnly =
    from a in A.Descendants("COMMISSION")
    join b in B.Descendants("COMMISSION")
    on a.Element("ID").Value equals b.Element("ID").Value
    select a;
现在输出看起来不错,没有重复项:


3.
E
F
我还修复了您示例中的查询,它现在也可以正常工作:

var bOnly =
    from b in B.Descendants("COMMISSION")
    let same =
        from a in A.Descendants("COMMISSION")
        where a.Element("ID").Value == b.Element("ID").Value
        select b
    select new XElement("CONTRACT", same);

我相信你会得到两个结果,不是因为每个集合中都有一个COMMISSION元素,而是因为B中的单个元素与集合a中ID为{1,2}的元素不匹配。如果集合a中有100个不匹配的元素,那么应该将ID为3的元素打印100次。我认为这不太正确。如果你看我的结果,你会发现还有第三个(空的)合同。我实际上只想要唯一的佣金元素(只关注ID),而不是ID上加入的佣金元素。然而,我错打了我的问题不是你的错。你帮我解决了我的问题-谢谢!我将编辑我的问题,以包含我的完整答案。@DavidAlanCondit啊,是的,我现在明白了。不管怎样,我很高兴能帮上忙!