<bus>
<port>
<req>
<item>
[...]
</item>
</req>
[...]
<req>
<item>
[...]
</item>
</req>
</port>
[...]
<port>
<req>
<item>
[...]
</item>
</req>
[...]
<req>
<item>
[...]
</item>
</req>
</port>
</bus>
<bus>
[...] (same as before)
</bus>
我有这个结构;所有结构都会重复。我需要选择总线的最后一个端口元素,该总线的最后一个孩子的属性为“ mode” ==“ read”。
可以存在这样的总线,该总线的最后一个端口元素的最后一个子元素的属性与“ read”不同,因此我需要选择正确的端口元素。
我尝试了很多次,最后一个是,但是不起作用:
var modbusportSelected = Elements("bus").Elements("port")
.Where( x => x.Elements("req")
.Any(y => y.Attribute("mode").Value.Contains("read")))
.Last();
任何帮助将不胜感激;另外,我对LINQ to XML还是陌生的,找不到一个网页可以确切地获得“任何”的含义,如果还有其他运算符,如果有的话,它们是什么。
答案 0 :(得分:2)
您的XML代码段需要一个顶级元素可能很重要。如果将上面的内容包装在外部标记中,则只要您从任何没有port
属性的mode
元素中捕获空引用,代码就可以正常工作。例如。
using System;
using System.Linq;
using System.Xml.Linq;
namespace ConsoleApp1
{
class Program
{
public static string xml = @"<topLevel><bus>
<port isCorrectNode='no'>
<req>
<item>
</item>
</req>
<req mode='read'>
<item>
</item>
</req>
</port>
<port isCorrectNode='yes'>
<req mode='read'>
<item>
</item>
</req>
<req>
<item>
</item>
</req>
</port>
</bus>
<bus>
</bus>
</topLevel>";
static void Main(string[] args)
{
XElement root = XElement.Parse(xml);
var found = root.Elements("bus").Elements("port")
.Where(x => x.Elements("req").Any(y => y.Attribute("mode") != null && y.Attribute("mode").Value.Contains("read")))
.Last();
var isThisTheCorrectNode = found.Attribute("isCorrectNode").Value;
Console.WriteLine(isThisTheCorrectNode);
}
}
}
将写出yes
编辑:我注意到您的代码正在寻找最后一个port
,它的子对象req
的任何模式均为'read'。但是您的问题要求提供 last 这样的req
。在这种情况下:
var wanted = root.Elements("bus").Elements("port")
.Where(x => x.Elements("req").Any() && // make sure there is a req element
x.Elements("req").Last().Attribute("mode") != null && // and it has the attribute
x.Elements("req").Last().Attribute("mode").Value.Contains("read")) // and it has the right value
.Last();