分类:
C#
最近项目中用到了博通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
50010702506256