选择一个元素作为拥有属性的最后一个孩子

时间:2019-06-17 14:56:34

标签: c# linq linq-to-xml

<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还是陌生的,找不到一个网页可以确切地获得“任何”的含义,如果还有其他运算符,如果有的话,它们是什么。

1 个答案:

答案 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();