首页 > 解决方案 > 选择作为最后一个具有属性的子元素的元素

问题描述

<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" 的最后一个子节点的总线的最后一个端口元素。

它可以存在一个总线,该总线具有最后一个端口元素和最后一个子元素,其属性不同于“读取”,因此我需要选择正确的端口元素。

我尝试了很多尝试,最后一个是这个,但不起作用:

var modbusportSelected = Elements("bus").Elements("port")
.Where( x => x.Elements("req")
.Any(y => y.Attribute("mode").Value.Contains("read")))
.Last();

任何帮助将不胜感激; 另外,我对 LINQ to XML 完全陌生,我找不到一个网页来获取“任何”的确切含义,以及是否有其他运算符,如果有,它们是什么。

标签: c#linqlinq-to-xml

解决方案


您的 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但你的问题是最后一个这样的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();

推荐阅读