Reputation: 1094
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}
}
};
Upvotes: 1
Views: 630
Reputation: 203824
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)
Upvotes: 1
Reputation: 116138
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"];
Upvotes: 1
Reputation: 426
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;
});
Upvotes: 2
Reputation: 14086
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)
Upvotes: 5