0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

C# - XMLをTreeViewに表示する (XElementクラスで探索して力技でTreeNodeに登録)

Posted at

まえがき

arxmlを解析してなにかする便利ツールをつくろうと思ったが、XMLが大きすぎてノード関係性がサッパリわからないので、見やすくする&検索できるようにしたかった。

画面キャプチャ

image.png

入力サンプルデータ

Sample.xml

<?xml version="1.0" encoding="utf-8"?>
<SampleClass xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <SampleFieldPoint>
    <X>10</X>
    <Y>20</Y>
  </SampleFieldPoint>
  <SampleFieldSize>
    <Width>30</Width>
    <Height>40</Height>
  </SampleFieldSize>
</SampleClass>

ソースコード

XmlTreeView.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using System.Drawing;
using System.Windows.Forms;


class XmlTreeView : Form
{
    TextBox txtTreePath;
    TextBox txtSearchKeyword;
    ListView lsv;
    TreeView trv;

    XmlTreeView(string path)
    {
        ClientSize = new Size(1200,500);
        
        XElement xml = XElement.Load(path);
        
        SplitContainer spl1;
        SplitContainer spl2;
        Controls.Add(spl1 = new SplitContainer(){
            Dock = DockStyle.Fill,
            Orientation = Orientation.Horizontal,
            FixedPanel = FixedPanel.Panel1,
            Panel1MinSize = 50,
            Panel2MinSize = 50,
        });
        spl1.Panel2.Controls.Add(spl2 = new SplitContainer(){
            Dock = DockStyle.Fill,
            Orientation = Orientation.Horizontal,
            // FixedPanel = FixedPanel.Panel1,
            Panel1MinSize = 50,
            Panel2MinSize = 50,
        });
        
        Load += (s,e)=>{
            spl1.SplitterDistance =  45;
            spl2.SplitterDistance =  150;
        };

        spl1.Panel1.Controls.Add( txtTreePath = new TextBox(){
            Location = new Point(0, 0),
            Width = 1000,
            ReadOnly = true,
        });

        Button btnSearch;
        spl1.Panel1.Controls.Add( btnSearch = new Button(){
            Location = new Point(0, 22),
            Width = 70,
            Text = "Search",
        });
        btnSearch.Click += (s,e)=>{SearchNode();};
        
        spl1.Panel1.Controls.Add( txtSearchKeyword = new TextBox(){
            Location = new Point(80, 25),
            Width = 620,
        });
        txtSearchKeyword.KeyDown += (s,e)=>{
            if ( e.KeyData == Keys.Enter ) { SearchNode(); }
        };


        spl2.Panel1.Controls.Add(lsv = new ListView(){
            Dock = DockStyle.Fill,
			View = View.Details,
			MultiSelect = false,
			HideSelection = false,
			FullRowSelect = true,
			GridLines = true,
        });
        lsv.Columns.AddRange(new ColumnHeader[]{
            new ColumnHeader(){Name="Type"     , Text="Type"         , Width=  70, TextAlign=HorizontalAlignment.Left},
            new ColumnHeader(){Name="Name"     , Text="Name or Value", Width=  70, TextAlign=HorizontalAlignment.Left},
            new ColumnHeader(){Name="Location" , Text="Location"     , Width=1000, TextAlign=HorizontalAlignment.Left},
        });
        lsv.DoubleClick += (s,e)=>{Lsv_DoubleClick();};

        spl2.Panel2.Controls.Add( trv = new TreeView(){
            Dock = DockStyle.Fill,
            HideSelection = false,
        });
        trv.AfterSelect += Trv_AfterSelect;


        var rootNode = new TreeNode(xml.Name.LocalName);
        rootNode.Name = rootNode.Text;
        trv.Nodes.Add(rootNode);
        XmlAddNodes(rootNode, xml);
    }
    // elemの子をnodeに追加する
    void XmlAddNodes(TreeNode node, XElement elem)
    {
        var t = elem.Elements(); // 直下の子ノードたち
        bool hasChild=false;
        foreach ( XElement elemChild in t)
        {
            hasChild=true;
            string s = elemChild.Name.LocalName;
            var nodeChild = new TreeNode(s);
            nodeChild.Name = s;
            node.Nodes.Add(nodeChild);
            XmlAddNodes(nodeChild, elemChild);
        }
        if(!hasChild){
            node.Text += " = " + elem.Value;
            node.Tag   = elem.Value;
        }
    }
    

    void Trv_AfterSelect(object sender, TreeViewEventArgs e)
    {
        txtTreePath.Text = GetLocationText(e.Node);
    }
    
    string GetLocationText(TreeNode node)
    {
        string s = node.Text;
        
        while(node.Parent!=null){
            node = node.Parent;
            s = node.Text + " > " + s;
        }
        
        return s;
    }


    void SearchNode()
    {
        string key = txtSearchKeyword.Text;
        
        if(key==""){return;}
        
        lsv.Items.Clear();
        lsv.BeginUpdate();
        
        var nodes = trv.Nodes.Find(key, true);
        foreach( var node in nodes ) {
            var item = new ListViewItem(new string[]{"TagName", node.Text, GetLocationText(node)});
            item.Tag = node;
            lsv.Items.Add(item);
            
        }
        
        lsv.EndUpdate();
    }
    
    void Lsv_DoubleClick()
    {
        if (lsv.SelectedItems.Count!=1){
            return;
        }
        
        var node = (TreeNode)lsv.SelectedItems[0].Tag;
        node.EnsureVisible();
        trv.SelectedNode = node;
    }
    
    [STAThread]
    static void Main(string[] args)
    {
        //Application.Run(new XmlTreeView(@"hogehoge.xml"));
        if (args.Length==1){
            Application.Run(new XmlTreeView(args[0]));
        }
    }
}
0
0
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
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?