tnblog
首页
视频
资源
登录

开发winform xml文件生成C#类文件工具

6778人阅读 2020/5/25 12:38 总访问:114083 评论:1 收藏:1 手机
分类: C#

最近项目中用到了博通PLC采集图像数据保存的业务,需要解析软件返回的xml文件,然后保存到数据库。

为了方便就自己整了一个xml转换为对应实体类的一个工具,减少去对应xml一个个创建实体类的繁琐工作量。


先来个操作演示。

实体类:

原理:其实xml转换实体类就是xml节点对应实体类,规则如下:

  1. xml节点对应类;

  2. xml节点里面的属性,对应实体类的属性;

  3. xml子节点为xml父节点的属性;

  4. 如果一个节点的子节点数量不同,则已最多的一个为准进行创建类,如<result><label>Pass</label></result> 和 <result><label>Pass</label><id>0</id></result> 则以后面包含id的这个为准;

  5. 如果一个子节点在同一节点出现多次,则此节点在父节点上属性类型为List,反之一般为string(注意这里不能为IList,否则解析的时候会出问题,原因:List<T>是想创建一个List<T>的实例并且需要使用到List<T>的功能,进行相关操作;而IList<T>只是想创建一个基于接口IList<T>的对象的实例,只是这个接口是由List<T>实现的。所以它只是希望使用到IList<T>接口规定的功能而已。);

  6. 如果一个节点下面没有子节点也没有属性,则此节点只为父节点的属性,不用创建类。

  7. 类上标记[XmlRoot]特性,属性上标记[XmlAttribute],子节点上标记[XmlElement]。


一、创建一个Winform 工程,设计页面如下:

其中命名空间为生成实体类的命名空间。

窗体代码如下:

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml.Linq;
using System.Xml.Serialization;

namespace XmlFormApp
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        /// <summary>
        /// 选择xml文件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void iconTargetFilePath_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog1 = new OpenFileDialog();
            openFileDialog1.InitialDirectory = "c:\\";
            openFileDialog1.Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*";
            openFileDialog1.FilterIndex = 2;
            openFileDialog1.RestoreDirectory = true;

            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                this.TargetFilePath.Text = openFileDialog1.FileName;
                this.richTextBox.Text = File.ReadAllText(openFileDialog1.FileName);
                this.iconButtonCreate.Enabled = true;
                this.iconButtonView.Enabled = true;
            }
        }

        private void CreateClass(string path)
        {
            StringBuilder builder = new StringBuilder();
            string classPath = "../../ClassFile.txt";
            builder.Append(File.ReadAllText(classPath));
            builder.Replace("{namespace}", textBoxClass.Text);
            StringBuilder classTxt = new StringBuilder();

            classTxt.Append($"\r\n\t/// <summary>\r\n\t///实体类\r\n\t/// </summary>");

            try
            {
                XElement element = XElement.Load(path);
                //子节点类集合
                List<string> classList = new List<string>();

                Dictionary<string, int> classAttrCountDic = new Dictionary<string, int>();

                foreach (var item in element.DescendantsAndSelf())
                {
                    Dictionary<string, StringBuilder> itemDics = new Dictionary<string, StringBuilder>();

                    var _calss = classList.Where(o => o == item.Name.ToString()).FirstOrDefault();
                    var _classAttr = classAttrCountDic.Where(o => o.Key == item.Name.ToString() && o.Value != item.Elements().Count()).FirstOrDefault();

                    StringBuilder classTxt1 = new StringBuilder();
                    if (item.Elements().Count() == 0)
                    {
                        classList.Add(item.Name.ToString());

                        if (_calss != null)
                        {
                            continue;
                        }

                        //如果此节点下没有属性则直接跳过
                        if (item.Attributes().Count() == 0)
                        {
                            StringBuilder childTxt = new StringBuilder();
                            childTxt.Append("\r\n\t\t[XmlElement(").Append($@"""{item.Name.ToString()}"")]");
                            childTxt.Append($"\r\n\t\tpublic string {item.Name.ToString()}");
                            childTxt.Append(" { get; set; }");
                            classTxt1.Append("\r\n\t\t{").Append(item.Name.ToString()).Append("}");
                            itemDics.Add(item.Name.ToString(), childTxt);
                            continue;
                        }

                        //没有子节点了
                        classTxt1.Append("\r\n\t[XmlRoot(").Append($@"""{item.Name.ToString()}"")]");
                        classTxt1.Append($"\r\n\tpublic class {item.Name.ToString()}");
                        classTxt1.Append("\r\n\t{");
                        //classList.Add(item.Name.ToString());

                        //创建该节点对应的属性
                        if (item.Attributes().Count() > 0)
                        {
                            foreach (var itemAttr in item.Attributes())
                            {
                                classTxt1.Append("\r\n\t\t[XmlAttribute(").Append($@"""{itemAttr.Name.ToString()}"")]");
                                classTxt1.Append($"\r\n\t\tpublic string {itemAttr.Name}");
                                classTxt1.Append(" { get; set; }");
                            }
                        }
                        classTxt1.Append("\r\n\t}");
                    }
                    else
                    {
                        if (_calss != null)
                        {
                            if (_classAttr.Key != null)
                            {
                                //返回先前创建类在字符串中的位置
                                int indexStr = classTxt.ToString().IndexOf($@"[XmlRoot(""{item.Name.ToString()}"")]");
                                StringBuilder itemStr = new StringBuilder();
                                itemStr.Append("\r\n\t");
                                itemStr.Append($@"[XmlRoot(""{item.Name.ToString()}"")]");
                                int i = 0;
                                while (true)
                                {
                                    string lenStr = classTxt.ToString(indexStr + ($@"[XmlRoot(""{item.Name.ToString()}"")]").Length + i, 1);
                                    i = i + 1;
                                    itemStr.Append(lenStr);
                                    if (itemStr.ToString().Contains("\r\n\t}"))
                                    {
                                        break;
                                    }
                                }
                                classTxt.Replace(itemStr.ToString(), null);
                                classList.Remove(item.Name.ToString());
                                classAttrCountDic.Remove(item.Name.ToString());
                            }
                            else
                            {
                                continue;
                            }
                        }
                        classList.Add(item.Name.ToString());
                        classAttrCountDic.Add(item.Name.ToString(), item.Elements().Count());

                        //创建该节点对应的类
                        classTxt1.Append("\r\n\t[XmlRoot(").Append($@"""{item.Name.ToString()}"")]");
                        classTxt1.Append($"\r\n\tpublic class {item.Name.ToString()}");
                        classTxt1.Append("\r\n\t{");

                        //创建该节点子节点对应的类
                        foreach (var itemElement in item.Elements())
                        {
                            StringBuilder childTxt = new StringBuilder();

                            var itemElementDic = itemDics.Where(o => o.Key == itemElement.Name.ToString());
                            if (itemElementDic.Count() > 0)
                            {
                                childTxt.Append("\r\n\t\t[XmlElement(").Append($@"""{itemElement.Name.ToString()}"")]");
                                childTxt.Append($"\r\n\t\tpublic List<{itemElement.Name.ToString()}> {itemElement.Name.ToString()}");
                                childTxt.Append(" { get; set; }");
                                itemDics.Remove(itemElement.Name.ToString());
                                itemDics.Add(itemElement.Name.ToString(), childTxt);
                            }
                            else
                            {
                                if (itemElement.Elements().Count() == 0)
                                {
                                    childTxt.Append("\r\n\t\t[XmlElement(").Append($@"""{itemElement.Name.ToString()}"")]");
                                    childTxt.Append($"\r\n\t\tpublic string {itemElement.Name.ToString()}");
                                    childTxt.Append(" { get; set; }");
                                    classTxt1.Append("\r\n\t\t{").Append(itemElement.Name.ToString()).Append("}");
                                    itemDics.Add(itemElement.Name.ToString(), childTxt);
                                }
                                else
                                {
                                    childTxt.Append("\r\n\t\t[XmlElement(").Append($@"""{itemElement.Name.ToString()}"")]");
                                    childTxt.Append($"\r\n\t\tpublic {itemElement.Name.ToString()} {itemElement.Name.ToString()}");
                                    childTxt.Append(" { get; set; }");
                                    classTxt1.Append("\r\n\t\t{").Append(itemElement.Name.ToString()).Append("}");
                                    itemDics.Add(itemElement.Name.ToString(), childTxt);
                                }
                            }
                        }

                        if (item.Name == "result")
                        {

                        }

                        //创建该节点对应的属性
                        if (item.Attributes().Count() > 0)
                        {
                            foreach (var itemAttr in item.Attributes())
                            {
                                classTxt1.Append("\r\n\t\t[XmlAttribute(").Append($@"""{itemAttr.Name.ToString()}"")]");
                                classTxt1.Append($"\r\n\t\tpublic string {itemAttr.Name}");
                                classTxt1.Append(" { get; set; }");
                            }
                        }

                        classTxt1.Append("\r\n\t}");
                    }

                    classTxt.Append(classTxt1);

                    foreach (var itemDic in itemDics)
                    {
                        classTxt.Replace("{" + itemDic.Key + "}", itemDic.Value.ToString());
                    }
                }

                //foreach (var itemDic in itemDics)
                //{
                //    classTxt.Replace("{" + itemDic.Key + "}", itemDic.Value.ToString());
                //}

                builder.Replace("{classTxt}", classTxt.ToString());

                this.richTextBox1.Text = builder.ToString();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        /// <summary>
        /// 预览
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void iconButtonView_Click(object sender, EventArgs e)
        {
            string path = this.TargetFilePath.Text;
            if (string.IsNullOrEmpty(textBoxClass.Text))
            {
                MessageBox.Show("请输入命名空间", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            CreateClass(path);
            iconButtonCheck.Enabled = true;
        }

        /// <summary>
        /// 生成
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void iconButtonCreate_Click(object sender, EventArgs e)
        {
            try
            {
                SaveFileDialog sfd = new SaveFileDialog();
                //设置文件类型 
                sfd.Filter = "类|*.cs";
                //设置默认文件类型显示顺序 
                sfd.FilterIndex = 1;
                //保存对话框是否记忆上次打开的目录 
                sfd.RestoreDirectory = true;

                //点了保存按钮进入
                if (sfd.ShowDialog() == DialogResult.OK)
                {
                    string localFilePath = sfd.FileName.ToString(); //获得文件路径 
                    string fileNameExt = localFilePath.Substring(localFilePath.LastIndexOf("\\") + 1); //获取文件名,不带路径
                                                                                                       //创建写入文件
                    FileStream fs1 = new FileStream(localFilePath, FileMode.Create, FileAccess.Write);
                    StreamWriter sw = new StreamWriter(fs1);
                    sw.WriteLine(this.richTextBox1.Text);//开始写入值
                    sw.Close();
                    fs1.Close();
                    MessageBox.Show("生成成功", "成功", MessageBoxButtons.OK, MessageBoxIcon.None);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("生成失败" + ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        /// <summary>
        /// 效验
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void iconButton1_Click(object sender, EventArgs e)
        {
            try
            {
                var a = DeserializeToObject<root>(this.richTextBox.Text);
                string json = JsonConvert.SerializeObject(a);
                MessageBox.Show("效验成功", "成功", MessageBoxButtons.OK, MessageBoxIcon.None);
            }
            catch (Exception ex)
            {
                MessageBox.Show("效验失败" + ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        /// <summary>
        /// 将XML字符串反序列化为对象
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="xml">XML字符</param>
        /// <returns></returns>
        public T DeserializeToObject<T>(string xml)
        {
            T myObject;
            XmlSerializer serializer = new XmlSerializer(typeof(T));
            StringReader reader = new StringReader(xml);
            myObject = (T)serializer.Deserialize(reader);
            reader.Close();
            return myObject;
        }

        private void Form1_Resize(object sender, EventArgs e)
        {
            this.panel.Width = (this.panelCenter.Width - 20) / 2;
            this.panel2.Width = (this.panelCenter.Width - 20) / 2;
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            this.panel.Width = (this.panelCenter.Width - 20) / 2;
            this.panel2.Width = (this.panelCenter.Width - 20) / 2;
        }
    }
}


源代码地址:https://download.tnblog.net/resource/index/43db1228dbed4eb9904a4099f4e56e42


评价
Decorating heart
排名
6
文章
6
粉丝
16
评论
8
{{item.articleTitle}}
{{item.blogName}} : {{item.content}}
ICP备案 :渝ICP备18016597号-1
网站信息:2018-2024TNBLOG.NET
技术交流:群号656732739
联系我们:contact@tnblog.net
欢迎加群交流技术