0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【C#】ツリー構造となるクラス群を作成するサンプルコード

Posted at

概要

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;
       }
    
    }
  • 上記SampleClassLoadTreeNode()を呼び出すと、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;
        }
    }

終わりに

個人的に意外とツリー構造のクラス群を作成する機会が多かったので、自分用としてサンプルコードを記載してみました。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?