LINQ to XML 选择类似于 SQL IN 子句的元素

LINQ to XML selecting elements similar to SQL IN clause

我有一些 XML 包含付款信息,包括应用付款的发票的详细信息。例如,我想使用 LINQ to XML 仅收集应用于某些发票 (111,222,333) 的付款。如果是 SQL 我可以使用 IN (111,222,333) 关键字,但我不确定如何在 LINQ 中执行相同的操作。

<Payment>
    <PaymentId>1</PaymentId>
    <Total>50</Total>
    <Invoice>
        <Id>111</Id>
        <Amount>20</Amount>
    </Invoice>
    <Invoice>
        <Id>555</Id>
        <Amount>30</Amount>
    </Invoice>
</Payment>
<Payment>
    <PaymentId>2</PaymentId>
    <Total>20</Total>
    <Invoice>
        <Id>222</Id>
        <Amount>20</Amount>
    </Invoice>
</Payment>
<Payment>
    <PaymentId>3</PaymentId>
    <Total>80</Total>
    <Invoice>
        <Id>888</Id>
        <Amount>80</Amount>
    </Invoice>
</Payment>

LINQ

var result = xml.Select(x => x.Element("Payment"))
               Where(x => x.Element("Id").Value.Contains("111","222","333"))

在这个例子中,我想 select "PaymentId 1" 和 "PaymentId 2" 因为它们适用于 ID 匹配 111、222 或 333 的发票。

您可以对这些众所周知的 Is 的列表进行 match/intersect。

List<string> ids = new List<string> { "111", "222", "333" };

var result = xml
    .Elements("Payment")
    .Where(p => {
        var invoiceIds = p.Elements("Invoice").Elements("Id").Select(o => o.Value);
        return ids.Intersect(invoiceIds).Any();
    }
);

完整代码和NetFiddle


const string XML = @"
    <root>
        <Payment>
            <PaymentId>1</PaymentId>
            <Total>50</Total>        
            <Invoice>
                <Id>555</Id>
                <Amount>30</Amount>
            </Invoice>
            <Invoice>
                <Id>111</Id>
                <Amount>30</Amount>
            </Invoice>
        </Payment>
        <Payment>
            <PaymentId>2</PaymentId>
            <Total>20</Total>
            <Invoice>
                <Id>222</Id>
                <Amount>20</Amount>
            </Invoice>
        </Payment>
        <Payment>
            <PaymentId>3</PaymentId>
            <Total>80</Total>
            <Invoice>
                <Id>888</Id>
                <Amount>80</Amount>
            </Invoice>
        </Payment>
    </root>
    ";

XElement xml = XElement.Parse(XML);
List<string> ids = new List<string> { "111", "222", "333" };

var result = xml
    .Elements("Payment")
    .Where(p => {
        var invoiceIds = p.Elements("Invoice").Elements("Id").Select(o => o.Value);
        return ids.Intersect(invoiceIds).Any();
        }
    );

foreach (var item in result)
{
    Console.WriteLine("PaymentId: {0}", (string)item.Element("PaymentId"));
}