首页 > 解决方案 > LINQ to XML 复杂查询过滤

问题描述

我有这个基于微软文档的代码。

https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/linq/how-to-write-queries-with-complex-filtering

string xml =
  "<products>" +
    "<product name=\"p1\">" +
      "<market name=\"m1\">" +
        "<areacode>12345</areacode>" +
        "<areacode>12346</areacode>" +
      "</market>" +
      "<market name=\"m2\">" +
        "<areacode>12345</areacode>" +
        "<areacode>13346</areacode>" +
      "</market>" +
      "<market name=\"m3\">" +
        "<areacode>12346</areacode>" +
        "<areacode>13346</areacode>" +
      "</market>" +
    "</product>" +
    "<product name=\"p2\">" +
      "<market name=\"m1\">" +
        "<areacode>12340</areacode>" +
        "<areacode>12346</areacode>" +
      "</market>" +
      "<market name=\"m2\">" +
        "<areacode>12340</areacode>" +
        "<areacode>13346</areacode>" +
      "</market>" +
      "<market name=\"m3\">" +
        "<areacode>12346</areacode>" +
        "<areacode>13346</areacode>" +
      "</market>" +
    "</product>" +
  "</products>";
XElement prods = XElement.Parse(xml);
IEnumerable<XElement> els =
  from e1 in prods.Elements("product")
  where
    (string)e1.Attribute("name") == "p1" &&
    (
      from e2 in e1.Elements("market")
      where
        (
          from e3 in e2.Elements("areacode")
          where e3.Value == "12345"
          select e3
        ).Any()
      select e2
    ).Any()
  select e1;
foreach (XElement el in els)
  Console.WriteLine(el);

输出是

<product name="p1">
  <market name="m1">
    <areacode>12345</areacode>
    <areacode>12346</areacode>
  </market>
  <market name="m2">
    <areacode>12345</areacode>
    <areacode>13346</areacode>
  </market>
  <market name="m3">
    <areacode>12346</areacode>
    <areacode>13346</areacode>
  </market>
</product>

如何从输出中排除没有指定区号的市场?如果符合条件,其余代码都需要产品名称、市场名称和地区代码。

标签: c#linq-to-xml

解决方案


没有简单的方法来创建一个拥有你想要的新树,因为你不能直接过滤孩子。但是,您可以修改您的树:

prods.Descendants("market").Where(m => m.Descendants("areacode").All(a => a.Value != "13346")).Remove();
prods.Descendants("product").Where(p => !p.Descendants("market").Any()).Remove();

推荐阅读