views:

646

answers:

3

Hello all

I have an XML file that is loaded into an XElement. I want to count the number of PollEvent children that both exist and that satisfy some conditions. I have got the code working to count the number of PollEvents in total but when I come to filter this list I do not seem to be able to call .Where, I believe this to is due to .Elements returning (extension) IEnumerable<XElements>.

Here is the code so far - I have placed what I want to happen next in comments.

    public PollDayPoint LoadData(DateTime date)
    {
        PollDayPoint newDayPoint = new PollDayPoint();
        newDayPoint.Date = date;

        String filename = AlertLogging.CreateFileName(date);

        XElement xmlDoc = XElement.Load(filename);

        IEnumerable<XElement> sdis = xmlDoc.Elements("SDI");
        IEnumerable<XElement> pollEvents = sdis.Elements("PollEvent");

        //This works
        int count = 0;
        using (IEnumerator<XElement> enumerator = pollEvents.GetEnumerator())
            while (enumerator.MoveNext())
                count++;

        newDayPoint.NumPolls = count;

        //Now we want to get all poll events that match certain conditions
        //Match those that have "Alert" children with attribute status="Sent"

        //IEnumerable<XElement> alertEvents = sdis.Elements("PollEvent");

        return newDayPoint;
    }

Some example XML below

<PollEvents>
  <SDI address="10.1.12.52">
    <PollEvent time="2009_4_11 13:51:49">
      <Alert errorCode="System.Net.WebException" errormessage="The remote server returned an error: (504) Gateway Timeout." status="Sent" handletime="2009_4_11 13:51:49" />
    </PollEvent>
    <PollEvent time="2009_4_11 14:06:47">
      <Alert errorCode="System.Net.WebException" errormessage="The remote server returned an error: (504) Gateway Timeout." status="Supressed" handletime="2009_4_11 14:06:47" />
    </PollEvent>
    <PollEvent time="2009_4_11 14:21:47">
      <Alert errorCode="System.Net.WebException" errormessage="The remote server returned an error: (504) Gateway Timeout." status="Supressed" handletime="2009_4_11 14:21:47" />
    </PollEvent>
  </SDI>
</PollEvents>
+3  A: 

For a start, your counting is simpler achieved as:

int count = pollEvents.Count();

However, you should be able to get Elements() to work via the extension method, and you should be able to call Where with no problems, like this:

var alertEvents = 
   sdis.Elements("PollEvent")
       .Where(x => x.Elements("Alert")
                    .Any(alert => (string) alert.Attribute("status") == "Sent")
             );

If that doesn't work, could you post the error you're getting?

Jon Skeet
Thanks - there was no error, Count just didnt exist as a method of IEnumerable<XElement> but I realised I was missing System.Linq as a reference! Doh!
Chris
A: 

Use linq query expressions to manipulate these :

var result = from el in XElement.Parse(data).Descendants("PollEvent")
             where el.Element("Alert").Attribute("status").Value == "Sent"
             select el;


newDayPoint.NumPolls = result.Count();
Yann Schwartz
+1  A: 

Extending Jon's answer, this would be the Extension method of his solution:

namespace MyExtensions
{
    public static class XElementsExtension
    {
        //Returns an IEnumerable of <PollEvent> having an "<Alert>" child element with attribute "status" == status
        public static IEnumerable<XElement> FindElementsByStatus(this IEnumerable<XElement> list, string status)
        {
            return list.Elements("PollEvent")
                       .Where(x => x.Elements("Alert")
                                    .Any(alert => (string)alert.Attribute("status") == status)
                             );
        }
    }
}
Alex Bagnolini
Ahh yes Extensions would be cool here, thanks
Chris