• XML序列化和反序列化


    在谈XML序列化之前,我们先来说说序列化。

    为什么要做序列化和反序列化?

    .Net程序执行时,对象都驻留在内存中;内存中的对象如果需要传递给其他系统使用;或者在关机时需要保存下来以便下次再次启动程序使用就需要序列化和反序列化。

    序列化名词解释:序列化是将对象状态转换为可保持或传输的格式的过程。

    与序列化相对的是反序列化,它将流转换为对象。这两个过程结合起来,可以轻松地存储和传输数据。这就是序列化的意义所在。

    我们可以把对象序列化为不同的格式,比如说,Json序列化、XML序列化、二进制序列化、SOAP序列化等,以上这些不同的格式也都是为了适应具体的业务需求。

    在本篇文章中,我们就来分析一下XML的序列化和反序列化。我们先来看一个XML文件:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    <?xml version="1.0" encoding="utf-8" ?>
    <BaseInfo>
      <Person>
        <Name>小明</Name>
        <Age>16</Age>
        <Books>
          <Book>
            <ISBN>123</ISBN>
            <Title>借的书1</Title>
          </Book>
        </Books>
      </Person>
      <Person>
        <Name>小红</Name>
        <Age>18</Age>
        <Books>
          <Book>
            <ISBN>456</ISBN>
            <Title>借的书2</Title>
          </Book>
          <Book>
            <ISBN>789</ISBN>
            <Title>借的书3</Title>
          </Book>
        </Books>
      </Person>
    </BaseInfo>

    在这个文件中BaseInfo为该XML的跟节点,它的里面由多个Person节点组成,在Person节点中又包括Name、Age、Books节点,Books节点中又由多个Book组成,在Book中又包括ISBN和Title。

    下面首先我们要做的是创建与该XML相对应的对象,然后把对象转换为上述XML(序列化),或者把上述XML转换为对象(反序列化)。下面的例子中只是把XML存到本地,再从本地读取出来,如果需要在网络中传输,应该添加Serializable属性,我们先来创建对象。

    using System.Xml.Serialization;
    public class BaseInfo
    {
       List<Person> perList = new List<Person>();
    
       [XmlElement(ElementName="Person")]
        public List<Person> PerList
        {
           get { return perList; }
           set { perList = value; }
        }
    }
    

    使用XML序列化需要引入命名空间System.Xml.Serialization。我们创建的类名称为BaseInfo,这里与XML的跟节点需要对应,当然我们也可以指定该类转换为XML时映射成的名称,这里可以使用XmlRoot中的ElementName来指定它的名称,就像该类中的属性PerList那样应用,当然你也可以使用比较省事的方法,类的名称和XML节点的名称相同即可,就像该例子中一样。在BaseInfo类中,我们维护了一个PerList它是一个Person对象的集合,当然这个属性的名称并不与XML文件中的对应,所以要更改它的名称为Person。

    好,接下来我们看看Person类:

    using System.Xml.Serialization;
    public class Person
    {
         string name;
         int age;
         List<Books> bookList=new List<Books>();
    
         /// <summary>
         /// 必须有默认的构造函数
         /// </summary>
         public Person()
         { }
    
         public Person(string name, int age)
         {
             this.name = name;
             this.age = age;
         }
    
         public string Name
         {
             get { return name; }
             set { name = value; }
         }
    
         public int Age
         {
             get { return age; }
             set { age = value; }
         }
    
         [XmlElement(ElementName = "Books")]
         public List<Books> BookList
         {
             get { return bookList; }
             set { bookList = value; }
         }
     }
    

    在该类中有Name和Age,还有维护了一个Books对象。

    我们再来看看Books:

    using System.Xml.Serialization;
    public class Books
    {
        List<Book> bookList = new List<Book>();
    
        [XmlElement(ElementName = "Book")]
        public List<Book> BookList
        {
            get { return bookList; }
            set { bookList = value; }
        }
    }
    

    Books的作用就像是一个过渡的类,只为了与XML中的节点Books对应,在该类中维护了Book类的对象集合。

    那么,最后我们来看Book类:

    using System.Xml.Serialization;
    public class Book
    {
        string isbn;
        string title;
    
        public Book() { }
    
        public Book(string isbn, string title)
        {
            this.isbn = isbn;
            this.title = title;
        }
    
        public string ISBN
        {
            get { return isbn; }
            set { isbn = value; }
        }
     
        public string Title
        {
            get { return title; }
            set { title = value; }
        }   
    }
    

    好了,这样我们需要的类也就都创建完了,虽说创建类的过程有些繁杂,但是有了这些类,我们也就不用一个一个处理XML的节点了。我们创建一个简单的控制台程序,在里面添加两个处理方法,第一个是序列化方法:

    public static void xmlSerialize()
    {
        Book b1 = new Book("111","书1");
        Book b2 = new Book("222","书2");
        Book b3 = new Book("333","书3");
        Books bs1 = new Books();
        Books bs2 = new Books();
        bs1.BookList.Add(b1);
        bs1.BookList.Add(b2);
        bs2.BookList.Add(b3);
        Person p1 = new Person("张三", 11);
        Person p2 = new Person("李四", 22);
        p1.BookList.Add(bs1);
        p2.BookList.Add(bs2);
        BaseInfo baseInfo = new BaseInfo();
        baseInfo.PerList.Add(p1);
        baseInfo.PerList.Add(p2);
    
        StringWriter sw = new StringWriter();
        //创建XML命名空间
        XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
        ns.Add("","");
        XmlSerializer serializer = new XmlSerializer(typeof(BaseInfo));
        serializer.Serialize(sw, baseInfo, ns);
        sw.Close();
    
        Console.Write(sw.ToString());
    }
    

    调用该方法运行效果:

    1

    第二个是反序列化方法:

    public static void xmlDeserialize()
    {
        //xml来源可能是外部文件,也可能是从其他系统获得
        FileStream file = new FileStream(@"http://www.cnblogs.com/info.xml", FileMode.Open, FileAccess.Read);
        XmlSerializer xmlSearializer = new XmlSerializer(typeof(BaseInfo));
        BaseInfo info = (BaseInfo)xmlSearializer.Deserialize(file);
        file.Close();
        foreach (Person per in info.PerList)
        {
            Console.WriteLine("人员:");
            Console.WriteLine(" 姓名:" + per.Name);
            Console.WriteLine(" 年龄:" + per.Age);
            foreach (Books b1 in per.BookList)
            {
                foreach (Book b in b1.BookList)
                {
                    Console.WriteLine(" 书:");
                    Console.WriteLine("     ISBN:" + b.ISBN);
                    Console.WriteLine("     书名:" + b.Title);
                }
            }
        }
    }
    

    调用该方法运行效果:

    2

  • 相关阅读:
    「LibreOJ NOI Round #2」不等关系
    Atcoder Grand Contest 036 D
    「CTS2019」氪金手游
    「CTS2019」珍珠
    「APIO2016」烟花表演
    「PKUWC2018/PKUSC2018」试题选做
    「PKUWC2018」猎人杀
    「WC 2019」数树
    CodeForces 794 G.Replace All
    「BZOJ 4228」Tibbar的后花园
  • 原文地址:https://www.cnblogs.com/sjqq/p/6933017.html
Copyright © 2020-2023  润新知