1

My code is as follows:

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
                   };

The XML I have is as follows:

<?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>

Now when I run the code it does perform the query however it only returns the first attribute where I actually want all attributes.

I'd appreciate any help on this as it is driving me crazy, each change I make to try fix this only results in more issues!

3
  • 3
    The <attributes> elements aren't closed - I'm assuming that's just an oversight when pasting into the question and the actual XML file is well-formed? Commented May 17, 2013 at 12:47
  • correct! Literally just edited this myself when I spotted it :) Commented May 17, 2013 at 12:48
  • You can always open your XML file in Internet Explorer to validate it. If any error is there then it will prompt at the beginning. Commented May 17, 2013 at 12:56

3 Answers 3

2

The problem is that by down selecting to the attribute element inside the select statement, you're only executing it once. In other words, you're passing in a collection to select, and the select is running statements like items.Element("attributes").Element("attribute").Element("name").Value to get a single value and a single anonymous object. It should look more like this (which works):

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
    });

I'm more comfortable with the extension syntax for Linq, but this can easily be converted to the other syntax.

Sign up to request clarification or add additional context in comments.

Comments

0

You should add one additional select into select new { }, now you are only returning values of the first 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,
                                   ...
                                }
               };

Comments

0

First you need to get at the Attributes element and then iterate all the Attribute elements under it.

You can do it like this:

  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
              });

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.