zoukankan      html  css  js  c++  java
  • (转)C# Xml进行序列化与反序列化

    ---------------------------------------------------------------文章1---------------------------------------------------------------

    使用XmlSerializer进行串行化
        关于格式化器还有一个问题,假设我们需要XML,有两中方案:要么编写一个实现IFormatter接口的类,采用的方式类似于SoapFormatter类,但是没有你不需要的信息;要么使用库类XmlSerializer,这个类不使用Serializable属性,但是它提供了类似的功能。
        如果我们不想使用主流的串行化机制,而想使用XmlSeralizer进行串行化我们需要做一下修改:
        a.添加System.Xml.Serialization命名空间。
        b.Serializable和NoSerialized属性将被忽略,而是使用XmlIgnore属性,它的行为与NoSerialized类似。
        c.XmlSeralizer要求类有个默认的构造器,这个条件可能已经满足了。


    序列化:

    XmlSerializer xs = new XmlSerializer(typeof(List<Peoson>));
    xs.Serialize(fs, listPers);


    反序列化:

    XmlSerializer xs = new XmlSerializer(typeof(List<Peoson>));
    List<Peoson> list = xs.Deserialize(fs) as List<Peoson>;

    using UnityEngine;
    using System;
    using System.Collections;
    using System.IO;
    using System.Xml.Serialization;
    using System.Xml;
    using System.Collections.Generic;
    
    [Serializable]      // 表示该类可以被序列化
    [XmlRoot("AAA")]    // 设置为XML中的根元素名称
    public class Person
    {
    	private string name;
    	private int age;
    
    //	[XmlElement("abc")]
    	public int abc = 1000; // 类的public属性字段都可以被序列化
    
    	//	[XmlAttribute("Name")]  设置作为xml中的属性
    	public string Name
    	{
    		get { return name;}
    		set { name = value;}
    	}
    	//	[XmlElement("Age")]  设置作为XML中的元素(默认状态)
    	public int Age
    	{
    		get { return age;}
    		set { age = value;}
    	}
    	public Person() { }
    	public Person(string name, int age)
    	{
    		this.name = name;
    		this.age = age;
    	}
    	public void SayHi()
    	{
    		Debug.LogFormat ("我是{0}, 今年{1}岁", name, age);
    	}
    }
    
    public class XmlSerialize : MonoBehaviour {
    
    	string filePath = Directory.GetCurrentDirectory() + "/XmlFile.txt";
    	string filePath2 = Directory.GetCurrentDirectory() + "/XmlClassFile.txt";
    
    	// Use this for initialization
    	void Start () {
    		List<Person> listPers = new List<Person> ();
    		Person per1 = new Person ("张三", 18);
    		Person per2 = new Person ("李四", 20);
    		listPers.Add (per1);
    		listPers.Add (per2);
    		SerializeMethod (listPers);  // 序列化
    		DeserializeMethod();  // 反序列化
    
    //		SerializeClassMethod (per1);
    //		DeserializeClassMethod ();
    		Debug.Log("Done ! ");
    	}
    
    	void DeserializeClassMethod()     // Xml实体类反序列化
    	{
    		FileStream fs = new FileStream (filePath, FileMode.Open);
    		XmlSerializer xs = new XmlSerializer(typeof(Person));
    		Person p = xs.Deserialize (fs) as Person;
    		if (p != null) 
    		{
    			p.SayHi ();
    		}
    		fs.Close ();
    	}
    
    	void SerializeClassMethod(Person p)   // Xml实体类序列化
    	{
    		FileStream fs = new FileStream (filePath2, FileMode.Create);
    		XmlSerializer xs = new XmlSerializer(typeof(Person));
    		xs.Serialize(fs, p);
    		fs.Close ();
    	}
    
    	void DeserializeMethod()     // Xml列表反序列化
    	{
    		FileStream fs = new FileStream (filePath, FileMode.Open);
    		XmlSerializer xs = new XmlSerializer(typeof(List<Person>));
    		List<Person> listPers = xs.Deserialize (fs) as List<Person>;
    		if (listPers != null) 
    		{
    			for (int i = 0; i < listPers.Count; i++)
    			{
    				listPers [i].SayHi ();
    			}
    		}
    		fs.Close ();
    	}
    
    	void SerializeMethod(List<Person> listPers)   // Xml列表序列化
    	{
    		FileStream fs = new FileStream (filePath, FileMode.Create);
    		XmlSerializer xs = new XmlSerializer(typeof(List<Person>));
    		xs.Serialize(fs, listPers);
    		fs.Close ();
    	}
    	
    	// Update is called once per frame
    	void Update () {
    	
    	}
    }
    


    Xml列表序列化的内容:

    Xml实体类序列化的内容:

    ---------------------------------------------------------------文章2---------------------------------------------------------------

    .Net Framework提供了对应的System.Xml.Seriazliation.XmlSerializer负责把对象序列化到XML,和从XML中反序列化为对象。Serializer的使用比较直观,需要多注意的是XML序列化相关的Attribute,怎么把这些attribute应用到我们的对象,以及对象公共属性上面去,生成满足预期格式的XML。
    本文列出了最常用的方法和特性,涵盖日常大部分的转换工作,希望大家在工作中快速上手。为了给大家直观的印象,这里给出具体的使用代码,为了节省篇幅,代码异常处理没有添加,各位同学使用的时候酌情添加。

    1. Serializer方法

    下面的方法封装了XmlSerializer的调用,这里列出了参数最全的一个版本,具体使用的时候需适当添加重载:

        public static class XmlSerializer
        {
            public static void SaveToXml(string filePath, object sourceObj, Type type, string xmlRootName)
            {
                if (!string.IsNullOrWhiteSpace(filePath) && sourceObj != null)
                {
                    type = type != null ? type : sourceObj.GetType();
    
                    using (StreamWriter writer = new StreamWriter(filePath))
                    {
                        System.Xml.Serialization.XmlSerializer xmlSerializer = string.IsNullOrWhiteSpace(xmlRootName) ?
                            new System.Xml.Serialization.XmlSerializer(type) :
                            new System.Xml.Serialization.XmlSerializer(type, new XmlRootAttribute(xmlRootName));
                        xmlSerializer.Serialize(writer, sourceObj);
                    }
                }
            }
    
            public static object LoadFromXml(string filePath, Type type)
            {
                object result = null;
    
                if (File.Exists(filePath))
                {
                    using (StreamReader reader = new StreamReader(filePath))
                    {
                        System.Xml.Serialization.XmlSerializer xmlSerializer = new System.Xml.Serialization.XmlSerializer(type);
                        result = xmlSerializer.Deserialize(reader);
                    }
                }
    
                return result;
            }
        }


    2. 序列化常用Attribute讲解说明:

    [XmlRootAttribute("MyCity", Namespace="abc.abc", IsNullable=false)]     // 当该类为Xml根节点时,以此为根节点名称。
    public class City

    [XmlAttribute("AreaName")]    // 表现为Xml节点属性。<... AreaName="..."/>
    public string Name

    [XmlElementAttribute("AreaId", IsNullable = false)]    // 表现为Xml节点。<AreaId>...</AreaId>
    public string Id

    [XmlArrayAttribute("Areas")]    // 表现为Xml层次结构,根为Areas,其所属的每个该集合节点元素名为类名。<Areas><Area ... /><Area ... /></Areas>
    public Area[] Areas

    [XmlElementAttribute("Area", IsNullable = false)]    // 表现为水平结构的Xml节点。<Area ... /><Area ... />...
    public Area[] Areas

    [XmlIgnoreAttribute]    // 忽略该元素的序列化。

    3. 详细举例说明

    这里用简单的城市,区域和街区作为例子,具体示范一下上面的规则。

        [XmlRootAttribute("MyCity", Namespace = "abc.abc", IsNullable = false)]
        public class City
        {
            [XmlAttribute("CityName")] 
            public string Name
            {
                get;
                set;
            }
    
            [XmlAttribute("CityId")] 
            public string Id
            {
                get;
                set;
            }
    
            [XmlArrayAttribute("Areas")]
            public Area[] Areas
            {
                get;
                set;
            }
        }
    
        [XmlRootAttribute("MyArea")]
        public class Area
        {
            [XmlAttribute("AreaName")] 
            public string Name
            {
                get;
                set;
            }
    
            [XmlElementAttribute("AreaId", IsNullable = false)]
            public string Id
            {
                get;
                set;
            }
    
            [XmlElementAttribute("Street", IsNullable = false)]
            public string[] Streets
            {
                get;
                set;
            }
        }

    根据以上类型,我们mock一些数据,然后用步骤1给出的Util方法输出:

        static void Main(string[] args)
        {
            Area area1 = new Area();
            area1.Name = "Pudong";
            area1.Id = "PD001";
            area1.Streets = new string [] { "street 001", "street 002" };
            Area area2 = new Area();
            area2.Name = "Xuhui";
            area2.Id = "XH002";
            area2.Streets = new string [] { "street 003", "street 004" };
    
            City city1 = new City();
            city1.Name = "Shanghai";
            city1.Id = "SH001";
            city1.Areas = new Area[] { area1, area2 };
    
            XmlSerializer.SaveToXml(@"C:	empXMLoutput003.xml", city1);
        }

    最终输出的XML为:

    <?xml version="1.0" encoding="utf-8"?>
    <MyCity xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            CityName="Shanghai" CityId="SH001" xmlns="abc.abc">
      <Areas>
        <Area AreaName="Pudong">
          <AreaId>PD001</AreaId>
          <Street>street 001</Street>
          <Street>street 002</Street>
        </Area>
        <Area AreaName="Xuhui">
          <AreaId>XH002</AreaId>
          <Street>street 003</Street>
          <Street>street 004</Street>
        </Area>
      </Areas>
    </MyCity>

    下面我们开始具体分析结果,其中包含一些很有用的结论和注意事项:
    1. xml的版本,编码,以及命名空间xmlns:xsi,xmlns:xsd为Framework自动添加。

    2. 因为我们用City对象作为根节点,所以根节点名称为我们定义的"MyCity"。
        但是,注意!这里指的是用City自身直接做根节点,如果是City集合比如City[],此时,该名称失效,系统会自动生成名称ArrayOfCity作为根节点名称(ArrayOf+类名),或者我们手动指定名称,这个就是在给大家的SaveToXml()方法中,参数xmlRootName的作用。

    3. 如果以City为根节点并在XmlRootAttribute特性中给定名称,同时也手动指定了xmlRootName,系统会以手动指定的名称为准。

    4. AreaName,AreaId,同为Area类的公共属性,一个被解释成属性,一个被解释成子节点。
        Areas集合被解释成了层次结构,Streets集合被解释成了水平结构。
        这两组区别最能体现不同序列化Attribute的用法

    文章分别转载自:https://blog.csdn.net/e295166319/article/details/52791279、https://blog.csdn.net/zzy7075/article/details/50770062

  • 相关阅读:
    MySQL数据库初识
    Python中面向对象初识到进阶
    python 函数进阶
    Python 函数的初识
    Python的发展与应用
    什么是产品经理 以及职责
    I/O----复制文本文件
    获取次日日期(主要两种方法)
    vector以及array和数组
    编辑软件注释快捷键
  • 原文地址:https://www.cnblogs.com/yeshenmeng/p/9455062.html
Copyright © 2011-2022 走看看