I have an XML like this:
And I have a Member class with property Name.
How can I read every Unit and its children Units into multiple generic List
The challenge would be to write it as 1 LINQ query, but that's beyond me. LINQ isn't easy/suitable for recursion.
I'll sketch a solution, I'm not going to write it out :
class Unit { ... ; ... List<Unit> Children; }
var units = doc.Descendants("Unit");
var Lookup = new Dictionary<XNode, Unit> ();
Why don't you implement a Tree for storing units. That would be much easier and natural than Lists.
Have a look at this comment for a good implementation using LinkedList.
See
If you HAVE to use List, then you may use recursion to build it. I'm assuming your Unit has a property (IList Unit.ChildUnits) to hold all children List. If not you may want to wrap Unit into another class that has this.
public List<Unit> LoadAllUnits(XMLNode rootNode){
List<Unit> allUnits = new List<Unit>();
foreach(var childNode in rootNode.ChildNodes){
allUnits.Add(LoadAllSubUnits(childNode);
}
return allUnits;
}
private Unit LoadAllSubUnits(XMLNode node){
Unit u = GetUnitFromCurrentNode(node); // Converts current node into Unit object
if(root.HasChildNode){
foreach(var childNode in node.ChildNodes){
u.ChildUnits.Add(LoadAllSubUnits(childNode);
}
}
return u;
}
class Unit
{
public string Name;
public List<Unit> Children;
public Unit(string name, List<Unit> children)
{
Name = name;
Children = children;
}
public static Unit Convert(XElement elem)
{
return new Unit(elem.Attribute("Name").Value, Convert(elem.Elements()));
}
public static List<Unit> Convert(IEnumerable<XElement> elems)
{
return elems.Select(Unit.Convert).ToList();
}
}
You can use it like this:
Unit.Convert(XDocument.Parse(xml).Root.Elements())
This would do it, using plain recursion:
public class Unit
{
public string Name { get; set; }
public List<Unit> Children { get; set; }
}
class Program
{
public static void Main()
{
XDocument doc = XDocument.Load("test.xml");
List<Unit> units = LoadUnits(doc.Descendants("Units").Elements("Unit"));
}
public static List<Unit> LoadUnits(IEnumerable<XElement> units)
{
return units.Select( x=> new Unit()
{ Name = x.Attribute("Name").Value,
Children = LoadUnits(x.Elements("Unit"))
}).ToList();
}
}