2

I am trying to do a mapping between C# and XML with LINQ. Currently, I have a class defined in C# that looks like this:

Item.cs

public class Item { public string DepartmentName { get; set; } public Dictionary<string, string> DepartmentNames { get; set; } public string Name { get; set; } public Dictionary<string, string> Names { get; set; } } 

My XML file looks like this:

departments.xml

<Departments> <Department Name="Sports" Title="Sports Department" Path="/sports" en-us="Sports" de-de="Sport"> <Item Name="Football" en-us="Football" de-de="Fußball" es-mx="" /> <Item Name="TennisBall" en-us="Tennis Ball" de-de="Tennisball" /> </Department> <Department Name="Automotive" Title="Automotive Department" Path="/autos" en-us="Automotive" de-de="kraftfahrtechnisch"> <Item Name="Oil" en-us="Oil" de-de="Öl" /> <Item Name="Tires" en-us="Tires" de-de="Bereifung" es-mx="Ruedas" /> </Department> </Departments> 

Basically, I have some values I want to load into a definite properties. Then, I have a list of attributes I know ("en-us", "de-de", "es-mx") that I want to load into Dictionaries. Currently, I have the following:

var items = XDocument.Parse(File.ReadAllText(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"App_Data\Items.xml"))) .Element("Departments") .Elements("Department") .Elements("Item") .Select(e => new Item { DepartmentName = ?, DepartmentNames = ?, Name = e.Attribute("Name").Value, Names = ? }).ToList(); 

I'm not sure how to load the properties from a) The parent elements b) Load the Dictionary object. Is this even possible with LINQ? Essentially, I'm trying to flatten out my data structure in-memory.

3
  • So you get the XML, and you are trying to populate the List<Item> items with that XML data, using LINQ? Commented Mar 24, 2015 at 15:09
  • You might be having namespace issues. Anyway you might be better served by Descendants here. Commented Mar 24, 2015 at 15:10
  • You can get properties from the parent object by just asking for the .Parent object. Commented Mar 24, 2015 at 15:12

2 Answers 2

3

In cases like this, where you need to access properties of outer elements in nested loops, I find the Linq from / select syntax to be more comfortable. Thus:

 var doc = XDocument.Load(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "InputData.xml")); var query = from department in doc.Element("Departments").Elements("Department") from item in department.Elements("Item") select new Item { DepartmentName = department.Attribute("Name").Value, DepartmentNames = department.Attributes().Where(a => a.Name != "Name").ToDictionary(a => a.Name.LocalName, a => a.Value), Name = item.Attribute("Name").Value, Names = item.Attributes().Where(a => a.Name != "Name").ToDictionary(a => a.Name.LocalName, a => a.Value), }; var items = query.ToList(); 

Here I am assuming you want every attribute placed in the dictionary other than the Name attribute, which has its own property.

Update

If you have a known list of attributes to put in the dictionary, you can do:

 var attributes = new HashSet<string>(new[] { "en-us", "de-de", "es-mx" }); // Possibly initialized in a static constructor. var query = from department in doc.Element("Departments").Elements("Department") from item in department.Elements("Item") select new Item { DepartmentName = department.Attribute("Name").Value, DepartmentNames = department.Attributes().Where(a => attributes.Contains(a.Name.LocalName)).ToDictionary(a => a.Name.LocalName, a => a.Value), Name = item.Attribute("Name").Value, Names = item.Attributes().Where(a => attributes.Contains(a.Name.LocalName)).ToDictionary(a => a.Name.LocalName, a => a.Value), }; var items = query.ToList(); 
Sign up to request clarification or add additional context in comments.

Comments

0

I think that the code below is what you want. I tested here and it worked, but I'm not sure if this is what you intent. I'm just filling the dictionaries with all values of languages.

 var items = XDocument.Parse( File.ReadAllText( Path.Combine( Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "InputData.xml"))) .Element("Departments") .Elements("Department") .Select( d => d.Elements("Item").Select(e => new Item { DepartmentName = d.Attribute("Name").Value, DepartmentNames = new Dictionary<string,string>() { { "en-us", d.Attribute("en-us").Value }, { "de-de", d.Attribute("de-de").Value} }, Name = e.Attribute("Name").Value, Names = new Dictionary<string,string>() { { "en-us", e.Attribute("en-us").Value}, { "de-de", e.Attribute("de-de").Value} } })).ToList(); 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.