zoukankan      html  css  js  c++  java
  • XML 2 Class [xml 转化为 序列化代码工具]


        我经常要编写一些可序列化的类,用于存储配置,通过XML的属性标记可以很容易完成这些工作。但是大量的工作任务让我没有多少时间经常编写些‘体力代码’,于是就考虑如何简化这个工作。

        那么XML文件是最终的结构,那么能否从XML结构通过某种工具还原为原始的序列化类代码呢?答案是肯定的。

    例如:
    一个简单的XML 的描述:

    <Test x="100.01" y="199.202" />

    它对应的序列化代码为:

    [Serializable]
    public class Test
    {
     
    protected double _x;
     
    protected double _y;
     [XmlAttribute()]
     
    public double X
     
    {
      
    get {return this._x;}
      
    set {this._x=value;}
     }

     [XmlAttribute()]
     
    public double Y
     
    {
      
    get {return this._y;}
      
    set {this._y=value;}
     }

    }

    一个带集合的XML代码:

    <Object Name="MyObject">
     
    <Fields>
      
    <Field Name="Title">
       
    <Values>
        
    <Value Name="ID" PrimaryKey="true"/>
        
    <Value Name="FirstName" Unique="false"/>
        
    <Value Name="LastName" Unique="false" Indexed="true"/>
       
    </Values>
      
    </Field>
     
    </Fields>
     
    <Methods>
      
    <Method Name="Add">
       
    <Params>
        
    <Param Name="X" value="1"/>
        
    <Param Name="Y" value="2"/>
       
    </Params>
      
    </Method>
     
    </Methods>
    </Object>

    它对应的序列化代码为:

    [Serializable]
    public class Param
    {
     
    protected int _value;
     
    protected string _name;
     [XmlAttribute()]
     
    public int Value
     
    {
      
    get {return this._value;}
      
    set {this._value=value;}
     }

     [XmlAttribute()]
     
    public string Name
     
    {
      
    get {return this._name;}
      
    set {this._name=value;}
     }

    }


    [Serializable]
    public class Object
    {
     
    protected string _name;
     
    protected ArrayList _fields;
     
    protected ArrayList _methods;
     [XmlAttribute()]
     
    public string Name
     
    {
      
    get {return this._name;}
      
    set {this._name=value;}
     }

     [XmlArray()]
     [XmlArrayItem(
    typeof(Field))]
     
    public ArrayList Fields
     
    {
      
    get {return this._fields;}
     }

     [XmlArray()]
     [XmlArrayItem(
    typeof(Method))]
     
    public ArrayList Methods
     
    {
      
    get {return this._methods;}
     }

     
    public Object()
     
    {
      
    this._fields=new ArrayList();
      
    this._methods=new ArrayList();
     }

    }


    [Serializable]
    public class Field
    {
     
    protected string _name;
     
    protected ArrayList _values;
     [XmlAttribute()]
     
    public string Name
     
    {
      
    get {return this._name;}
      
    set {this._name=value;}
     }

     [XmlArray()]
     [XmlArrayItem(
    typeof(Value))]
     
    public ArrayList Values
     
    {
      
    get {return this._values;}
     }

     
    public Field()
     
    {
      
    this._values=new ArrayList();
     }

    }


    [Serializable]
    public class Value
    {
     
    protected string _name;
     
    protected bool _unique;
     
    protected bool _primaryKey;
     
    protected bool _indexed;
     [XmlAttribute()]
     
    public string Name
     
    {
      
    get {return this._name;}
      
    set {this._name=value;}
     }

     [XmlAttribute()]
     
    public bool Unique
     
    {
      
    get {return this._unique;}
      
    set {this._unique=value;}
     }

     [XmlAttribute()]
     
    public bool PrimaryKey
     
    {
      
    get {return this._primaryKey;}
      
    set {this._primaryKey=value;}
     }

     [XmlAttribute()]
     
    public bool Indexed
     
    {
      
    get {return this._indexed;}
      
    set {this._indexed=value;}
     }

    }


    [Serializable]
    public class Method
    {
     
    protected string _name;
     
    protected ArrayList _params;
     [XmlAttribute()]
     
    public string Name
     
    {
      
    get {return this._name;}
      
    set {this._name=value;}
     }

     [XmlArray()]
     [XmlArrayItem(
    typeof(Param))]
     
    public ArrayList Params
     
    {
      
    get {return this._params;}
     }

     
    public Method()
     
    {
      
    this._params=new ArrayList();
     }

    }

    可以看到,比较复杂的XML代码的序列化类编码工作量是比较麻烦而且单调的。

    那么如何才能将XML生成这样的逆向代码呢?

    1、 递归遍历XML Node
    2、 登记实体类的名称,类似“public class Method”
    3、 登记所有属性的信息,解析属性类型,类似“protected string _name;”

    // 检查是否为 boolean
    if ((val == "true"|| (val == "false"))
    {
        ptype 
    = "bool";
    }


    // 检查是否为 int ,如果带小数,则表示为 double
    if (Char.IsDigit(val, 0))
    {
        ptype 
    = "int";
        
    if (val.IndexOf("."!= -1)
        
    {
            ptype 
    = "double";
        }

    }


    4、 登记集合类的名称,用于创建类似“[XmlArrayItem(typeof(Param))]”的代码
    5、 输出代码

    实现这些步骤的代码:

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Collections;
    using System.Xml;
    using System.Windows.Forms;

    namespace Infotech.Config.Tools.Xml2Class
    {
        
    public sealed class ClassInfo
        
    {
            
    public string name;
            
    public Hashtable properties; //保存属性
            public ArrayList collections; //保存集合名
            public Hashtable collectionTypes; //保存集合对应类型

            
    public ClassInfo(string name)
            
    {
                
    this.name = name;
                properties 
    = new Hashtable();
                collections 
    = new ArrayList();
                collectionTypes 
    = new Hashtable();
            }

        }


        
    /// <summary>
        
    /// XML 转 Class 
        
    /// </summary>
        
    /// <example>
        
    /// <code escape="true">
        
    /// Example 1:
        
    /// <Database Name="MyDB">
        
    ///  <Tables>
        
    ///   <Table Name="Person">
        
    ///    <Fields>
        
    ///     <Field Name="ID" PrimaryKey="true"/>
        
    ///     <Field Name="FirstName" Unique="false"/>
        
    ///     <Field Name="LastName" Unique="false" Indexed="true"/>
        
    ///    </Fields>
        
    ///   </Table>
        
    ///  </Tables>
        
    /// </Database>
        
    /// Example 2:
        
    /// <ComplexNumber Real="12.34" Imaginary="45.67"/>
        
    /// </code>
        
    /// </example>

        public class ClassGenerator
        
    {
            
    protected Hashtable classInfoList;

            
    public ClassGenerator()
            
    {
                classInfoList 
    = new Hashtable();
            }


            
    public string Generate(string src)
            
    {
                classInfoList.Clear();
                
    string dest = "";

                XmlDocument doc 
    = new XmlDocument();
                
    try
                
    {
                    doc.LoadXml(src);
                }

                
    catch (Exception ex)
                
    {
                    MessageBox.Show(ex.Message);
                    
    return "";
                }

                XmlNode root 
    = doc.DocumentElement;
                ProcessClass(root);
                dest 
    = EmitCode();

                
    return dest;
            }


            
    protected void ProcessClass(XmlNode node)
            
    {
                
    string className = node.Name;
                ClassInfo ci;

                
    if (classInfoList.Contains(className))
                
    {
                    ci 
    = (ClassInfo)classInfoList[className];
                }

                
    else
                
    {
                    ci 
    = new ClassInfo(className);
                    classInfoList[className] 
    = ci;
                }


                
    foreach (XmlAttribute attr in node.Attributes)
                
    {
                    
    string name = attr.Name;
                    
    string val = attr.Value.ToLower();

                    
    string ptype = "string";

                    
    // 检查属性是否存在
                    if (!ci.properties.Contains(name))
                    
    {
                        
    // 检查是否为 boolean
                        if ((val == "true"|| (val == "false"))
                        
    {
                            ptype 
    = "bool";
                        }


                        
    // 检查是否为 int ,如果带小数则表示为 double
                        if (Char.IsDigit(val, 0))
                        
    {
                            ptype 
    = "int";
                            
    if (val.IndexOf("."!= -1)
                            
    {
                                ptype 
    = "double";
                            }

                        }

                        ci.properties[name] 
    = ptype;
                    }


                    
    foreach (XmlNode childNode in node.ChildNodes)
                    
    {
                        
    if (!ci.collections.Contains(childNode.Name))
                        
    {
                            ci.collections.Add(childNode.Name);
                            
    foreach (XmlNode grandchildNode in childNode.ChildNodes)
                            
    {
                                
    //增加集合类型
                                if (!ci.collectionTypes.Contains(childNode.Name))
                                
    {
                                    ci.collectionTypes[childNode.Name] 
    = grandchildNode.Name;
                                }

    //递归调用
                                ProcessClass(grandchildNode);
                            }

                        }

                    }

                }

            }


            
    protected string EmitCode()
            
    {
                StringBuilder sb 
    = new StringBuilder();

                
    foreach (DictionaryEntry entry in classInfoList)
                
    {
                    ClassInfo ci 
    = (ClassInfo)entry.Value;
                    
    string cname = ci.name.ToUpper()[0+ ci.name.Substring(1);
                    sb.Append(
    "//由 xml2Class 工具生成");
                    sb.Append(
    "[Serializable]\r\n");
                    sb.Append(
    "public class " + cname + "\r\n");
                    sb.Append(
    "{\r\n");

                    
    //创建属性变量
                    foreach (DictionaryEntry prop in ci.properties)
                    
    {
                        
    string pname = (string)prop.Key;
                        
    string ptype = (string)prop.Value;
                        pname 
    = pname.ToLower()[0+ pname.Substring(1);
                        sb.Append(
    "\tprotected " + ptype + " _" + pname + ";\r\n");
                    }

                    
    //创建集合变量
                    foreach (string collName in ci.collections)
                    
    {
                        
    string name = collName.ToLower()[0+ collName.Substring(1);
                        sb.Append(
    "\tprotected ArrayList _" + name + ";\r\n");
                    }


                    
    //创建属性
                    foreach (DictionaryEntry prop in ci.properties)
                    
    {
                        
    string pname = (string)prop.Key;
                        
    string ptype = (string)prop.Value;
                        pname 
    = pname.ToLower()[0+ pname.Substring(1);
                        
    string sname = pname.ToUpper()[0+ pname.Substring(1);
                        sb.Append(
    "\t[XmlAttribute()]\r\n");
                        sb.Append(
    "\tpublic " + ptype + " " + sname + "\r\n");
                        sb.Append(
    "\t{\r\n");
                        sb.Append(
    "\t\tget {return this._" + pname + ";}\r\n");
                        sb.Append(
    "\t\tset {this._" + pname + "=value;}\r\n");
                        sb.Append(
    "\t}\r\n");
                    }


                    
    //创建集合
                    foreach (string collName in ci.collections)
                    
    {
                        
    string name = collName.ToUpper()[0+ collName.Substring(1);
                        
    string collNameSmall = collName.ToLower()[0+ collName.Substring(1);
                        sb.Append(
    "\t[XmlArray()]\r\n\t[XmlArrayItem(typeof(" + ci.collectionTypes[name] + "))]\r\n");
                        sb.Append(
    "\tpublic ArrayList " + name + "\r\n");
                        sb.Append(
    "\t{\r\n");
                        sb.Append(
    "\t\tget {return this._" + collNameSmall + ";}\r\n");
                        sb.Append(
    "\t}\r\n");
                    }


                    
    // 创建构造函数,当有子集合才需要
                    if (ci.collections.Count > 0)
                    
    {
                        sb.Append(
    "\tpublic " + cname + "()\r\n");
                        sb.Append(
    "\t{\r\n");
                        
    foreach (string collName in ci.collections)
                        
    {
                            
    string name = collName.ToLower()[0+ collName.Substring(1);
                            sb.Append(
    "\t\tthis._" + name + "=new ArrayList();\r\n");
                        }

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

                    sb.Append(
    "}\r\n\r\n");
                }

                
    return sb.ToString();
            }

        }

    }


    有些人喜欢看代码,了解思路;而有些人则喜欢直接使用工具,所以我希望这个工具对大家有所帮助,并提供了代码和执行程序的下载。

    下载地址:

    /Files/Chinasf/Xml2Class.rar

  • 相关阅读:
    NOIP2016-2020 复盘
    「笔记」线段树合并/分裂
    「笔记」线性基
    20210628模拟赛解题报告
    「笔记」左偏树
    题解 CF718C Sasha and Array
    一些杂碎的知识点
    20210614 模拟赛
    洛谷 P4249 [WC2007]剪刀石头布
    CF132E Bits of merry old England
  • 原文地址:https://www.cnblogs.com/adam/p/662236.html
Copyright © 2011-2022 走看看