根据字典筛选XElements列表

3

这是我的XML文件:

<items>
  <item code="1">
    <info1>LOREM</info1>
    <info2>IPSUM</info2>
    <info3>DOLOR</info3>
  </item>
  <item code="2">
    <info1>LOREM</info1>
    <info2>AMET</info2>
    <info3>CONSECTETUER</info3>
  </item>
  <item code="3">
    <info1>LOREM</info1>
    <info2>IPSUM</info2>
    <info3>CONSECTETUER</info3>
  </item>
</items>

我想根据存储在该字典中的条件提取一些项目代码:

{ "info1", "LOREM" }
{ "info2", "IPSUM" }

我写了这个 LINQ 查询:
var test =  from element in xml.Descendants("item").Elements()
        from param in dicoParams
        where param.Key == element.Name.ToString() && param.Value == element.Value
        select element.Parent.Attribute("code");

但是输出结果是:
code="1"
code="1"
code="2"
code="3"
code="3"

and what I expected is :

code="1"
code="3"

我们可以注意到该查询返回了满足至少一个条件的元素,但我希望它同时满足两个条件。
那么我应该如何编写这个查询?

1
为什么你不期望 2?它符合你的条件。 - Mathew Thompson
请检查您的数据。item code="1"匹配了两个条目。 - H H
如果你期望有2个答案,那么Linq查询应该基于字典而不是XML。 - H H
@mattytommo 第二项不满足字典中的所有条件。 - user1068352
@user1068352 我认为你可能是对的,我更新了我的答案并添加了这个选项。 - Mathew Thompson
是的,user1068352 是对的。我想要匹配所有条件的项目。抱歉我说错了。 - Harkonnen
3个回答

3

我认为你也期望看到数字2,因为2包含info1,而info1又包含LOREM

不管怎样,我认为这就是你要找的:

var test =  from element in xml.Descendants("item")
    from param in dicoParams
    where element.Elements()
        .Any(e => e.Name.ToString() == param.Key && e.Value == param.Value)
    select element.Attribute("code");

无论匹配的数量如何,都将输出一个代码。

实际上,正如@user1068352在评论中提到的那样,您似乎想要与字典中的所有项匹配的项。

如果是这种情况,请尝试以下方法:

var test = from element in xml.Descendants("item")
    where dicoParams.All(d => element.Elements
        .Any(e => e.Name.ToString() == d.Key && e.Value == d.Value))
    select element.Attribute("code");

你可能会比使用O(nm)循环遍历所有元素和字典中的所有项更有效率,但我认为第二个答案是原帖作者所期望的逻辑。 - Rawling
我执行了你的答案,但是没有返回结果。请检查。 - Smaug
你是我的男人!你的第二个解决方案正是我想要的。非常感谢,我为此苦苦挣扎了数小时。 - Harkonnen
@Harkonnen 我也尝试了同样的方法,但是我无法获取结果。它显示“错误17:无法在此范围内声明名为'e'的局部变量,因为它会给已经用于表示其他内容的'父级或当前'范围中的'e'赋予不同的含义”。 - Smaug
是的,终于找到解决办法了。在xml.Descendants("item")中使用from element语句, 其中dicoParams.All(d => element.Elements().Any(ee => ee.Name.ToString() == d.Key && ee.Value == d.Value))用于筛选出符合条件的元素, 然后通过select element.Attribute("code")来获取这些元素的"code"属性。将e替换为ee解决了这个问题。 - Smaug

0

这样做应该可以:

var test =
    from element in xml.Descendants("item")
    where element.Elements()
        .Any(x =>
            dicoParams.ContainsKey(x.Name.ToString())
            && dicoParams[x.Name.ToString()] == x.Value)
    select element.Attribute("code");

但是正如其他人指出的那样,元素“2”与您提供的数据相匹配。


0
 var test1 = (from element in elem.Descendants().Elements()
                         from item in val
                         where item.Key == element.Name.ToString() && item.Value == element.Value
                         select element.Parent.Attribute("code")).GroupBy(t => t.Parent.Attribute("code"));

你也可以只用 group by


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接