1

I have some code like this:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;

class Program
{
    static void Main(string[] args)
    {
        string xml = @"<Root>
  <Report1>
    <Row>
      <Field1>data1-1</Field1>
      <Field2>data1-2</Field2>
      <!-- many more fields -->
    </Row>
    <Row>
      <Field1>data2-1</Field1>
      <Field2>data2-2</Field2>
      <!-- many more fields -->
    </Row>
  </Report1>
</Root>";

        XDocument doc = XDocument.Parse(xml);

        var report1 = from report in doc.Root.Elements("Report1").Elements("Row")
                      select new Dictionary<string, string>()
                          {
                              {"Field1", report.Elements("Field1").First().Value},
                              {"Field2", report.Elements("Field2").First().Value}
                          };

        var i = 1;
        foreach (Dictionary<string, string> dict in report1)
        {
            Console.WriteLine(String.Format("Row{0}: ", i));
            Console.WriteLine("  Field1: {0}", dict["Field1"]);
            Console.WriteLine("  Field2: {0}", dict["Field2"]);
            i++;
        }

        Console.ReadLine();
    }
}

Would it be possible to define a string array or some other data structure that I could use to declare these dictionary objects? Here is some silly pseudo code help show my idea:

EDIT The variable fieldNames in the pseudo code below would be an array of names I expect, not based on the xml source field names. I will be ignoring any field names within the xml source that are not explicitly set in the fieldNames array.

var report1 = from report in doc.Root.Elements("Report1").Elements("Row")
              select new Dictionary<string, string>()
           {
              foreach (var fieldName in fieldNames)
              {
                  {fieldName, report.Elements(fieldName).First().Value}
              }
           };
2
  • even after the edit it still isn't entirely obvious whether the set of fields you want in the report is based on the xml contents or not. Commented Nov 8, 2012 at 19:57
  • @Tar, thanks I made an edit. The fields I want to import are not based on the xml source, it would be what is explicitly set in the array or list. Commented Nov 8, 2012 at 20:08

4 Answers 4

5

Use Enumerable.ToDictionary:

var report1 = 
    from report in doc.Root.Elements("Report1").Elements("Row")
    select new[] {"Field1", "Field2", "Field3"}
        .ToDictionary(x => x, x => report.Elements(x).First().Value)
Sign up to request clarification or add additional context in comments.

1 Comment

The OP's code is creating an IEnumerable<Dictionary<string,string>>, your's is creating a single dictionary.
2

The pseudocode is actually pretty close to what you really can do. I assume there's a separate fieldNames collection that you have ready there.

IEnumerable<string> fieldNames = ...;
XDocument doc = ...;
var report1 = doc.Root.Elements("Report1").Elements("Row")
    .Select(report =>
    {
        var d = new Dictionary<string, string>();
        foreach (var fieldName in fieldNames)
        {
            d.Add(fieldName, report.Elements(fieldName).First().Value);
        }
        return d;
    });

1 Comment

+1 because this answer also worked, it's just that Thom Smith was just a min faster at posting his answer.
1

This will give you a list of type List<Dictionary<string,string>>

var rows = doc.Descendants("Row")
           .Select(r => r.Elements()
                         .ToDictionary(x => x.Name.LocalName, x => x.Value))
           .ToList();

..

var data = rows[i]["Field1"];

Comments

1

Don't try to do everything in a single collection initializer.

For something like this I'd create a separate method:

public static Dictionary<string, string> MapReport(XElement report)
{
    var output = new Dictionary<string, string>();
    foreach(var field in report.Elements())
    {
        output.Add(field.Name, ...);
    }
}

Then the query would be something much simpler:

var report1 = from report in doc.Root.Elements("Report1").Elements("Row")
              select MapReport(report)

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.