使用相同的节点值循环遍历XML

时间:2012-10-25 20:27:47

标签: c# xml loops recursion linq-to-xml

我在循环遍历XML文件并将其表示在例如TreeView中时遇到了困难。我的XML结构如下所示:

<Categories>
  <Category Name="Cat Level1">
    <Categories>
      <Category Name="ChildCat Level 2">
        <Categories>
          <Category Name="ChildCat Level3_1" />
          <Category Name="ChildCat Level3_2" />
        </Categories>
      </Category>
    </Categories>
  </Category>
</Categories>

我写了一个递归函数来遍历这个XML,这里是:

private void CreateTreeStructure(XDocument xDoc)
{
    foreach(var element in xDoc.Descendants("Category"))
    {
        var node = new TreeNode(element.Attribute("Name").Value);
        treeView1.Nodes.Add(node);
        ReadChildren(element.Descendants("Categories"), node);
    }
}

private void ReadChildren(IEnumerable<XElement> element, TreeNode node)
{
    foreach (var child in element.Descendants("Category"))
    {
        var childNode = new TreeNode(child.Attribute("Name").Value);
        node.Nodes.Add(childNode);
        ReadChildren(child.Descendants("Categories"), childNode);
    }
}

结果是预期的和非预期的。我想在TreeView中使用这个XML,因此结果应该类似于:

  • 猫等级1
    • ChildCat Level2
      • ChildCat Level3_1
      • ChildCat Level3_2

但结果如下:

  • 猫等级1
    • ChildCat Level2
      • ChildCat Level3_1
      • ChildCat Level3_2
    • ChildCat Level3_1
    • ChildCat Level3_2
    • ChildCat Level3_1
    • ChildCat Level3_2
  • ChildCat Level2
    • ChildCat Level3_1
    • ChildCat Level3_2
  • ChildCat Level3_1
  • ChildCat Level3_2

经过一些调试后我发现这是因为我的递归代码正在寻找后代“类别”,但子类别节点也被命名为“类别”。因此,第一个应该只找到“Cat Level 1”元素的函数也会循环遍历名为Category的其他节点。现在我有点坚持这个,我无法改变XML的结构。

那么,有没有人知道如何在不每次读取所有子节点的情况下循环这个XML?提前谢谢!

更新

感谢“davisoa”的回答,我设法解决了这个问题。下面是我使用的代码,如果有人有同样的问题,这里是答案:

private void CreateTreeStructure(XDocument xDoc)
{
    foreach (var element in xDoc.Root.Elements("Category"))
    {
        var node = new TreeNode(element.Attribute("Name").Value);
        treeView1.Nodes.Add(node);
        if (element.HasElements) 
            ReadChildren(element.Element("Categories"), node);
    }
}

private void ReadChildren(XElement element, TreeNode node)
{
    foreach (var child in element.Elements("Category"))
    {
        var childNode = new TreeNode(child.Attribute("Name").Value);
        node.Nodes.Add(childNode);
        if(child.HasElements)
            ReadChildren(child.Element("Categories"), childNode);
    }
}

1 个答案:

答案 0 :(得分:1)

如果您使用Elements方法而不是Descendants,则只返回直接子项。这应该可以解决问题。

Elements文档为here