使用LINQ to XML,XElements和XAttributes我想使用XElement的Attributes()IEnumerable XName / Value对集合上的精确匹配,针对提供的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");
它应该返回一个代表<value>group-one item value B</value>
现在,我已经决定使用XPathSelectElement() - 传递从提供的XAttributes()集合中的名称/值构建的XPath字符串。在这种情况下,生成的字符串将是:
group[@name='group-one']/setting[key[@app='n' and @type='z' and count(@*)=2]]/value
但是,我通常不会在集合中循环来在应用程序中构建字符串。我现在已经对此进行了一段时间的讨论,不幸的是,我很难理解如何使用现有方法使用紧凑的linq查询(或一系列查询)来实现更“优雅”的解决方案。
非常感谢任何反馈和/或建议!
答案 0 :(得分:2)
您需要找到任何键匹配的设置,因此请使用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();