
最近项目中用到了博通PLC采集图像数据保存的业务,需要解析软件返回的xml文件,然后保存到数据库。
为了方便就自己整了一个xml转换为对应实体类的一个工具,减少去对应xml一个个创建实体类的繁琐工作量。
先来个操作演示。
实体类:
原理:其实xml转换实体类就是xml节点对应实体类,规则如下:
xml节点对应类;
xml节点里面的属性,对应实体类的属性;
xml子节点为xml父节点的属性;
如果一个节点的子节点数量不同,则已最多的一个为准进行创建类,如<result><label>Pass</label></result> 和 <result><label>Pass</label><id>0</id></result> 则以后面包含id的这个为准;
如果一个子节点在同一节点出现多次,则此节点在父节点上属性类型为List,反之一般为string(注意这里不能为IList,否则解析的时候会出问题,原因:List<T>是想创建一个List<T>的实例,并且需要使用到List<T>的功能,进行相关操作;而IList<T>只是想创建一个基于接口IList<T>的对象的实例,只是这个接口是由List<T>实现的。所以它只是希望使用到IList<T>接口规定的功能而已。);
如果一个节点下面没有子节点也没有属性,则此节点只为父节点的属性,不用创建类。
类上标记[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


剑轩
这种工具有点nice,![[嘻嘻]](https://www.tnblog.net/layui/images/face/1.gif)
感觉可以搞到web中来用,我下载来试试