LINQ to XML:使用具有 XName 和 Value 的 XElement.Attributes() 集合过滤查询

发布于 2024-08-15 01:43:08 字数 2456 浏览 4 评论 0原文

使用 LINQ to XML、XElements 和 XAttributes 我想使用 XElement 的 Attributes() XName/Value 对的 IEnumerable 集合与提供的 XName/Value 对的 IEnumerable Attributes 集合的精确匹配来过滤查询。

<container>
   <!-- logical group of settings -->
   <group name="group-one">
      <!-- setting with multiple key-value key options to return value -->
      <setting>
         <key app="a" command="go" />
         <key app="a" type="z" command="go" />
         <key app="a" type="z" flag="1" command="go" />
         <key app="a" type="z" target="OU812"/>
         <value>group-one item value A</value>
      </setting>
      <setting>
         <key app="a" />
         <key app="a" type="z" />
         <key app="a" type="z" flag="1" />
         <key app="c" type="z" command="go" />
         <value>group-one item value B</value>
      </setting>      
      ...
      ...
   </group>
   <group name="group-two">
      ...
      ...
   </group>
</container>

我怀疑使用 Attributes().SequenceEqual() 和自定义 IEqualityComparer 来比较 XAttribute.XName 和 XAttribute.Value 是可行的方法,但序列永远不会匹配,因为 XElement("key").Attributes() 返回一个集合给定元素中所有元素的所有属性。我尝试过类似于以下代码片段的任何数字 linq 查询,包括嵌套查询和使用“let”语句,但我似乎无法正确执行。

var myAttributes = new List<XAttribute> {
                                        new XAttribute("app", "a"), 
                                        new XAttribute("type", "z")
                                        };

var xGroup = doc.Elements("group").First(g=>g.Attribute("name").Value==groupName);
var xSetting = (from s in xGroup.Elements("setting")
               // AttributesComparer() compares both the XAttribute.XName and XAttribute.Value properties to determine equality
               where s.Elements("key").Attributes().SequenceEqual(myAttributes, new AttributesComparer())
               select s).FirstOrDefault();

var xValue = xSetting.Element("value");

它应该返回一个表示 group-one item value B 的 XElement

现在,我决定使用 XPathSelectElement() —— 传递根据名称/值构建的 XPath 字符串在提供的 XAttributes() 集合中。在这种情况下,生成的字符串将是:

group[@name='group-one']/setting[key[@app='n' and @type='z' and count(@*)=2]]/value

但是,我通常不愿意循环遍历集合以在应用程序中构建字符串。我已经为此努力了一段时间,不幸的是,我对如何使用现有方法使用紧凑的 linq 查询(或一系列查询)来实现更“优雅”的解决方案感到困惑。

任何反馈和/或建议将不胜感激!

Using LINQ to XML, XElements and XAttributes I'd like to filter a query using an exact match on an XElement's Attributes() IEnumerable collection of XName/Value pairs, against a provided IEnumerable Attributes collection of XName/Value pairs.

<container>
   <!-- logical group of settings -->
   <group name="group-one">
      <!-- setting with multiple key-value key options to return value -->
      <setting>
         <key app="a" command="go" />
         <key app="a" type="z" command="go" />
         <key app="a" type="z" flag="1" command="go" />
         <key app="a" type="z" target="OU812"/>
         <value>group-one item value A</value>
      </setting>
      <setting>
         <key app="a" />
         <key app="a" type="z" />
         <key app="a" type="z" flag="1" />
         <key app="c" type="z" command="go" />
         <value>group-one item value B</value>
      </setting>      
      ...
      ...
   </group>
   <group name="group-two">
      ...
      ...
   </group>
</container>

I suspect using Attributes().SequenceEqual() with a custom IEqualityComparer to compare both XAttribute.XName and XAttribute.Value is the way to go, but the sequence never matches because XElement("key").Attributes() returns a collection of all attributes for all elements in a given element. I have tried any number linq queries similar to following code snippet, including nested queries and using the "let" statement, but I can't seem to get it right.

var myAttributes = new List<XAttribute> {
                                        new XAttribute("app", "a"), 
                                        new XAttribute("type", "z")
                                        };

var xGroup = doc.Elements("group").First(g=>g.Attribute("name").Value==groupName);
var xSetting = (from s in xGroup.Elements("setting")
               // AttributesComparer() compares both the XAttribute.XName and XAttribute.Value properties to determine equality
               where s.Elements("key").Attributes().SequenceEqual(myAttributes, new AttributesComparer())
               select s).FirstOrDefault();

var xValue = xSetting.Element("value");

It should return an XElement representing <value>group-one item value B</value>

For now, I have settled on using XPathSelectElement() -- passing an XPath string built from the name/values in the provided XAttributes() collection. In this case, the generated string would be:

group[@name='group-one']/setting[key[@app='n' and @type='z' and count(@*)=2]]/value

But, I'm generally resistant to looping through collections to build strings in an application. I have been hammering away at this for a while now, and unfortunately, I am stumped as to how to impliment a more "elegant" solution using a compact linq query (or series of queries) with existing methods.

Any feedback and/or suggestions would be greatly appreciated!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

演出会有结束 2024-08-22 01:43:08

您需要找到一个 any 键匹配的设置,因此请使用 Any 扩展方法。只需要一个小小的改变:

    var xSetting = (from s in xGroup.Elements("setting")
                    // AttributesComparer() compares both the XAttribute.XName and XAttribute.Value properties to determine equality
                    where s.Elements("key").Any(key => key.Attributes().SequenceEqual(myAttributes, new AttributesComparer()))
                    select s).FirstOrDefault();

You need to find a setting where any key matches so use the Any extension method. Only a small change is required:

    var xSetting = (from s in xGroup.Elements("setting")
                    // AttributesComparer() compares both the XAttribute.XName and XAttribute.Value properties to determine equality
                    where s.Elements("key").Any(key => key.Attributes().SequenceEqual(myAttributes, new AttributesComparer()))
                    select s).FirstOrDefault();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文