概要
C#で、ツリー構造となるクラス群を作成するサンプルコードを記載しました。
説明
こちらのような構造のxmlファイルがあるとします。
また、Node
という名前のクラスを用意して、このクラス一つがxmlデータの一つの層 (Node
) を表すとします。
このxmlファイルの内容を読み込み、各Node
クラスにxmlの内容を書き出し、xmlと同じツリー構造にするサンプルコードを記載しました。
コード
xml
第一階層から第四階層まであり、第四階層のみText
要素という付加情報の要素がある構成です。
TreeNode.xml
<?xml version="1.0" encoding="Shift-JIS"?>
<Data>
<Layer1 NodeID="01_01">最上層ノード
<Layer2 NodeID="02_01">第二階層ノード①
<Layer3 NodeID="03_01">第三階層ノード①
<Layer4 NodeID="04_01">最下層ノード①
<Text TextID="A">テキスト①</Text>
</Layer4>
<Layer4 NodeID="04_02">最下層ノード②
<Text TextID="B">テキスト②</Text>
<Text TextID="C">テキスト③</Text>
</Layer4>
</Layer3>
<Layer3 NodeID="03_02">第三階層ノード②
<Layer4 NodeID="04_03">最下層ノード③
<Text TextID="D">テキスト④</Text>
<Text TextID="E">テキスト⑤</Text>
</Layer4>
<Layer4 NodeID="04_04">最下層ノード④
<Text TextID="F">テキスト⑥</Text>
</Layer4>
</Layer3>
</Layer2>
<Layer2 NodeID="02_02">第二階層ノード②
<Layer3 NodeID="03_03">第三階層ノード③
<Layer4 NodeID="04_05" >最下層ノード⑤
<Text TextID="G">テキスト⑦</Text>
<Text TextID="H">テキスト⑧</Text>
<Text TextID="I">テキスト⑨</Text>
<Text TextID="J">テキスト⑩</Text>
</Layer4>
</Layer3>
</Layer2>
</Layer1>
</Data>
C#
ノードクラスです。
このクラス一つがxmlの一つの層を表しています。
Node.cs
public class Node
{
/// <summary>
/// 階層
/// </summary>
public string Layer { get; set; }
/// <summary>
/// ノードごとに一意になるID
/// </summary>
public string NodeID { get; set; }
/// <summary>
/// ノードの名称 (xmlのLayer要素のコンテンツ部分)
/// </summary>
public string Name { get; set; }
/// <summary>
/// 最下層ノードの付加情報
/// </summary>
public List<Text> Text { get; set; } = new List<Text>();
/// <summary>
/// 子ノード群
/// </summary>
public List<Node> Children { get; } = new List<Node>();
/// <summary>
/// 自身とすべての子ノードを列挙
/// </summary>
public IEnumerable<Node> SelfAndDescendants
{
get
{
yield return this;
foreach (var child in Children)
{
foreach (var descendant in child.SelfAndDescendants)
{
yield return descendant;
}
}
}
}
}
xmlの第四階層の子要素で定義されているText要素一つ分のクラスです。
Text.cs
public class Text
{
/// <summary>
/// 付加ごとに一意になるID
/// </summary>
public string TextID { get; set; }
/// <summary>
/// 付加情報の名称 (xmlのText要素のコンテンツ部分)
/// </summary>
public string Name { get; set; }
}
xmlを読み込み、ツリー構造となるクラス群を作成するコードを記載したクラスです。
名前は仮にSampleClass
としています。
SampleClass.cs
Public class SampleClass
{
/// <summary>
/// ツリーのルートノード (第一階層)
/// </summary>
public Node Root { get; set; }
/// <summary>
/// TreeNode.xmlを読み込みツリーを作成する
/// </summary>
public void LoadTreeNode()
{
var path = (TreeNode.xmlまでのパス);
var xml = XElement.Load(path);
Root = CreateNode(xml.Element("Layer1"));
}
/// <summary>
/// ノードを作成する
/// </summary>
private Node CreateNode(XElement element)
{
var node = new Node()
{
NodeID = element.Attribute("NodeID")?.Value ?? "",
Layer = element.Name.LocalName,
Name = element.FirstNode.ToString().Replace("\n", "").Replace("\r", "").Trim()
};
foreach (var childElement in element.Elements())
{
if (childElement.Name.LocalName.Contains("Text"))
{
var text = new Text(node)
{
TextID = childElement.Attribute("TextID")?.Value ?? "",
Name = childElement.FirstNode.ToString().Replace("\n", "").Replace("\r", "").Trim()
};
node.Text.Add(text);
}
else
{
// 子ノードを読み込む
node.Children.Add(CreateNode(node, childElement));
}
}
return node;
}
}
- 上記
SampleClass
のLoadTreeNode()
を呼び出すと、xmlから全てのノードの情報を読み込んで各ノードクラスに格納していき、第一階層のノードがRoot
プロパティに入ります。 - 各
Node
クラスのChildren
プロパティを使用して、そのノードの子ノードをみることができます。 -
CreateNode()
メソッドで再起処理を使用してノードを作成していっています。 - 下記のように
Node
クラスのSelfAndDescendants
プロパティを呼び出すと、そのノードと子ノードを全て列挙したコレクションが帰ってきます。
SampleClass.cs
Public class SampleClass
{
/// <summary>
/// ツリーのルートノード (第一階層)
/// </summary>
public Node Root { get; set; }
private void DoSomething()
{
// 第一階層含む、全てのノードをコレクションで列挙
var nodes = Root.SelfAndDescendants;
// NodeIDが"02_02"の第二階層と子ノードをコレクションで列挙
nodes = Root.Children.First(x => x.NodeID == "02_02").SelfAndDescendants;
}
}
終わりに
個人的に意外とツリー構造のクラス群を作成する機会が多かったので、自分用としてサンプルコードを記載してみました。