C# 在列表中递归读取XML树结构<;T>;有儿童名单<;T>;

C# 在列表中递归读取XML树结构<;T>;有儿童名单<;T>;,c#,recursion,tree,linq-to-xml,C#,Recursion,Tree,Linq To Xml,我有这样一个XML: Unit.Convert(XDocument.Parse(xml).Root.Elements()) 我有一个属性名为的成员类 如何使用最新的.NET技术将每个单元及其子单元读入多个泛型List,这些泛型List可以以递归方式再次具有子单元List <Root> <Units Name="Test1"> <Unit Name="Test11" /> <Unit Name="Test12"> &

我有这样一个XML:

Unit.Convert(XDocument.Parse(xml).Root.Elements())
我有一个属性名为的成员类

如何使用最新的.NET技术将每个单元及其子单元读入多个泛型
List
,这些泛型
List
可以以递归方式再次具有子单元
List

<Root>
  <Units Name="Test1">
    <Unit Name="Test11" />
    <Unit Name="Test12">
      <Unit Name="Test21" />
      <Unit Name="Test22" />
      <Unit Name="Test23">
        <Unit Name="Test31" />
        <Unit Name="Test32" />  
        <Unit Name="Test33" />
      </Unit>
      <Unit Name="Test24" />
    </Unit>
  </Units>
  <Units Name="Test2" />
    <!-- ... -->
  <Units Name="Test3" />
    <!-- ... -->
  <Units Name="Test4" />
</Root>

为什么不实现一个存储单元的树呢。这将比列表更简单、更自然

请查看使用LinkedList的良好实现

若您必须使用列表,那个么您可以使用递归来构建它。我假设您的单元有一个属性(IList Unit.ChildUnits)来保存所有子对象列表。若并没有,你们可能想把这个单元包装到另一个有这个功能的类中

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;
}
公共列表加载单元(XMLNode rootNode){
List allUnits=新列表();
foreach(rootNode.ChildNodes中的var childNode){
Add(LoadAllSubUnits(childNode));
}
归还冲积物;
}
私有单元LoadAllSubUnits(XMLNode节点){
Unit u=GetUnitFromCurrentNode(node);//将当前节点转换为Unit对象
if(root.HasChildNode){
foreach(node.ChildNodes中的var childNode){
u、 Add(LoadAllSubUnits(childNode));
}
}
返回u;
}

挑战在于将其编写为1个LINQ查询,但我无法理解。LINQ不容易/不适合递归

我会草拟一个解决方案,我不会写出来:

  • 将Xml读入XDocument(或XmlDocument)
  • 定义
    类单元{…;…列出子项;}
  • 如果需要,定义单位和根类。我将在这里展平该部分
  • 获取所有单位标记的平面列表,
    var units=doc.substands(“单位”);
  • 迭代这些元素,我假设父节点总是位于嵌套单元之前
  • var Lookup=newdictionary()中查找每个节点的父节点;
  • 如果找到父节点,请将当前节点(新单元)添加到其子节点
  • 否则,将其添加到顶级列表中
  • 将新单位和元素添加到字典中
  • 仅在创建列表时才需要查找字典

使用普通递归即可:

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();
    }
}
公共类单元
{
公共字符串名称{get;set;}
公共列表子项{get;set;}
}
班级计划
{
公共静态void Main()
{
XDocument doc=XDocument.Load(“test.xml”);
列表单位=装载单位(文件子体(“单位”)。元素(“单位”);
}
公共静态列表加载单元(IEnumerable units)
{
返回单位。选择(x=>newunit()
{Name=x.Attribute(“Name”).Value,
子项=荷载单位(x.Elements(“单位”))
}).ToList();
}
}

-我必须使用列表和…列表及其所有子列表必须作为分层数据读取到关系sql数据库中。在这种情况下,使用递归将所有子节点放入一个列表中。我将更新答案。我会认为这是一个尽可能简单的递归实现…@christoba遍历XDoc/XmlDoc有点笨拙。但这是可能的。我建议在回答中用字典替换它。很优雅,但我会将这些转换方法保留在类之外。@BrokenGlass如何从这个层次结构数据中获取顶级单位?
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();
    }
}