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);
}
}
結果は期待されたものと期待されていないものです。このXMLをTreeViewに入れたいので、結果は次のようになります。
- 猫レベル1
- ChildCatレベル2
- ChildCat Level3_1
- ChildCat Level3_2
- ChildCatレベル2
しかし、結果は次のようになります。
- 猫レベル1
- ChildCatレベル2
- ChildCat Level3_1
- ChildCat Level3_2
- ChildCat Level3_1
- ChildCat Level3_2
- ChildCat Level3_1
- ChildCat Level3_2
- ChildCatレベル2
- ChildCatレベル2
- ChildCat Level3_1
- ChildCat Level3_2
- ChildCat Level3_1
- ChildCat Level3_2
デバッグの結果、これは再帰コードが子孫「Category」を検索しているためであることがわかりましたが、サブカテゴリノードの名前も「Category」です。したがって、要素「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);
}
}