获得使用LINQ从XML节点C#

问题描述:

我的代码如下:获得使用LINQ从XML节点C#

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> 

现在,当我运行的代码,它执行查询然而它只返回我实际上想要所有属性的第一个属性。

我会很感激任何帮助,因为它让我疯狂,每次改变我尝试修复这只会导致更多的问题!

+3

元素不是封闭的 - 我假设粘贴到这个问题时,并做好充分形成实际的XML文件只是一个监督? – daveaglick

+0

正确!当我发现它时,我自己编辑了这个文件:) –

+0

您可以随时在Internet Explorer中打开您的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的扩展语法,但是这可以很容易地转换成其他的语法。

+0

Spot on - 像梦一样工作,非常感谢! –

您应该添加一个额外的selectselect new { },你现在只返回第一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 
       });