在c#中使用LINQ从XML中获取节点

本文关键字:XML 获取 节点 LINQ | 更新日期: 2023-09-27 18:13:59

我的代码如下:

XDocument xmlDoc = XDocument.Load("myXML.xml");
        var data = from items in xmlDoc.Root.Elements("category")
                   where items.Attribute("value").Value == "idxCategoryPlatformEngine"
                   select new
                   {
                       attribute = items.Element("attributes").Element("attribute").Element("name").Value,
                       trigger = items.Element("attributes").Element("attribute").Element("trigger").Value,
                       value = items.Element("attributes").Element("attribute").Element("value").Value,
                       minutes = items.Element("attributes").Element("attribute").Element("minutes").Value
                   };

我的XML如下:

<?xml version="1.0" encoding="utf-8"?>
<GMS>
    <category value="idxCategoryPlatformEngine">
        <attributes>
            <attribute>
                <name>CheckpointFileCorruptionAlarm.InAlarm</name>
                <trigger>EQ</trigger>
                 <value>TRUE</value>
                 <minutes>0</minutes>
            </attribute>
            <attribute>
                 <name>CPULoad</name>
                <trigger>GT</trigger>
                <value>60</value>
                <minutes>5</minutes>
            </attribute>
            <attribute>
                <name>Engine.Historian.InStoreForward</name>
                <trigger>EQ</trigger>
                <value>TRUE</value>
                <minutes>0</minutes>
            </attribute>
        </attributes>
    </category>
    <category value="idxCategoryApplicationEngine">
        <attributes>
            <attribute>
                <name>CheckpointFileCorruptionAlarm.InAlarm</name>
                <trigger>EQ</trigger>
                 <value>TRUE</value>
                 <minutes>0</minutes>
            </attribute>
            <attribute>
                 <name>CPULoad</name>
                <trigger>GT</trigger>
                <value>60</value>
                <minutes>5</minutes>
            </attribute>
            <attribute>
                <name>Engine.Historian.InStoreForward</name>
                <trigger>EQ</trigger>
                <value>TRUE</value>
                <minutes>0</minutes>
            </attribute>
        </attributes>
    </category>
</GMS>

现在,当我运行代码时,它确实执行查询,但它只返回我实际需要的所有属性的第一个属性。

我很感激任何帮助,因为它是驱使我疯了,我所做的每一个改变,试图解决这只会导致更多的问题!

在c#中使用LINQ从XML中获取节点

问题是,通过在select语句中向下选择属性元素,您只执行它一次。换句话说,您正在传入一个集合以进行选择,而选择正在运行诸如items.Element("attributes").Element("attribute").Element("name").Value这样的语句以获取单个值和单个匿名对象。它应该看起来更像这样(可以工作):

var data2 = doc.Root.Elements("category")
    .Where(x => x.Attribute("value").Value == "idxCategoryPlatformEngine")
    .Elements("attributes")
    .Elements("attribute")
    .Select(x => new
    {
        attribute = x.Element("name").Value,
        trigger = x.Element("trigger").Value,
        value = x.Element("value").Value,
        minutes = x.Element("minutes").Value
    });

我对Linq的扩展语法更熟悉,但这可以很容易地转换为其他语法。

您应该在select new { }中添加一个额外的select,现在您只返回第一个attribute的值:

var data = from item in xmlDoc.Root.Elements("category")
           where item.Attribute("value").Value == "idxCategoryPlatformEngine"
           select new
               {
                   category = item.Attribute("value").Value,
                   attributes = from attr in item.Element("attributes")
                                select new {
                                   attribute = attr.Element("name").Value,
                                   trigger = attr.Element("trigger").Value,
                                   ...
                                }
               };

首先您需要获得Attributes元素,然后迭代它下面的所有Attribute元素。

你可以这样做:

  XDocument xmlDoc = XDocument.Load("myXML.xml");
  var data = (from items in xmlDoc.Root.Elements("category")
              where items.Attribute("value").Value == "idxCategoryPlatformEngine"
              select new {attrs  = items.Element("attributes")})
              .SelectMany(a => a.attrs.Elements("attribute"))
              .Select(item => new {
                       attribute = item.Element("name").Value,
                       trigger = item.Element("trigger").Value,
                       value = item.Element("value").Value,
                       minutes = item.Element("minutes").Value
              });