VB.NET中的基本XML序列化

在VB.NET中读取XML非常简单。 创建一个XML文档对象,然后您可以加载XML并根据需要遍历所有节点。 您可以随便搜索节点,使用x路径。

另一方面,创建XML并不是那么简单。 本质上有两种方法。

  • 创建一个XML文档对象,并将每个Element和/或attribute节点设置为所需的值
  • 创建需要序列化的结构并将数据序列化为XML

我认为选择1是非选择。 尽管无需考虑序列化即可更轻松地创建结构,但是创建XML文档对象(这并不难)然后创建并设置每个Element和Attribute节点的过程很容易自杀! 它还将创建一个代码段,即使使用不复杂的XML,它也会因自身的重量而崩溃! 在学习序列化之前,我有一个项目,保存XML的过程大约需要3页代码,我再也听不懂了!

输入XML序列化

我不会详细介绍所有这些内容,而是创建了一个VS 2008项目,您可以下载并使用它。 在其中,您将看到以下内容:

  • 我设计了一些旨在创建数据结构的类,希望以XML形式创建并以XML形式读取。
  • 您可以根据需要命名XML节点的方法
  • 保持XML干净的一种方法(默认情况下,.NET会将各种名称空间垃圾加载到不需要的XML中)
  • 如何使用通用序列化功能将数据对象另存为XML
  • 如何使用通用序列化功能将XML读入数据对象
我认为涵盖了...

我将为员工创建一个简单的结构。 该结构将由四个基本数据点组成-其中一个将是具有三个数据点的嵌套结构。

雇员
名字

生日
职责范围
责任一
责任二
责任三

我们将需要能够创建这种结构的数组,因为我们将有多个员工。

我们将从在类中构建结构开始。 我想您可以用一个简单的结构来做-我可以稍后再尝试,但是今天我们将创建类。 我喜欢上课。 这些类都在我称为序列化的vb模块中。 这是一个愚蠢的名字-但它只是一个演示人员。


Public Module Serialize 
    Public EmploymentData As New Group 
    <XmlRoot("Employees")> _
    Public Class Group
        <XmlElement("IndividualEmployee")> _
        Public Employees() As Employee
    End Class 
    Public Class Employee
        Private vFirstName As String = ""
        Private vLastName As String = ""
        Private vBirthday As New Date 
        Private vPriorities As JobPriorities 
        Public Sub New()
        End Sub 
        Public Sub New(ByVal FirstName As String, ByVal LastName As String, ByVal Birthday As Date, ByVal Responsibilities As JobPriorities)
            Me.FirstName = FirstName
            Me.LastName = LastName
            Me.Birthday = Birthday
            Me.Priorities = Responsibilities
        End Sub 
        <XmlAttribute("firstname")> _
        Public Property FirstName() As String
            Get
                Return vFirstName
            End Get
            Set(ByVal value As String)
                vFirstName = value
            End Set
        End Property 
        <XmlAttribute("lastname")> _
        Public Property LastName() As String
            Get
                Return vLastName
            End Get
            Set(ByVal value As String)
                vLastName = value
            End Set
        End Property 
        <XmlAttribute("birthday")> _
        Public Property Birthday() As String
            Get
                Return vBirthday
            End Get
            Set(ByVal value As String)
                vBirthday = value
            End Set
        End Property 
        <XmlElement("Jobs")> _
        Public Property Priorities() As JobPriorities
            Get
                Return vPriorities
            End Get
            Set(ByVal value As JobPriorities)
                vPriorities = value
            End Set
        End Property 
    End Class 
    Partial Public Class JobPriorities 
        Private vResponsibilityOne As String = ""
        Private vResponsibilityTwo As String = ""
        Private vResponsibilityThree As String = "" 
        Public Sub New()
        End Sub 
        Public Sub New(ByVal ResponsibilityOne As String, Optional ByVal ResponsibilityTwo As String = "", Optional ByVal ResponsibilityThree As String = "")
            Me.ResponsibilityOne = ResponsibilityOne
            Me.ResponsibilityTwo = ResponsibilityTwo
            Me.ResponsibilityThree = ResponsibilityThree
        End Sub 
        <XmlElement("first_priority")> _
        Public Property ResponsibilityOne() As String
            Get
                Return vResponsibilityOne
            End Get
            Set(ByVal value As String)
                vResponsibilityOne = value
            End Set
        End Property 
        <XmlElement("Second_priority")> _
        Public Property ResponsibilityTwo() As String
            Get
                Return vResponsibilityTwo
            End Get
            Set(ByVal value As String)
                vResponsibilityTwo = value
            End Set
        End Property 
        <XmlElement("Third_priority")> _
        Public Property ResponsibilityThree() As String
            Get
                Return vResponsibilityThree
            End Get
            Set(ByVal value As String)
                vResponsibilityThree = value
            End Set
        End Property 
    End Class 
我正在创建三个课程。

雇员

工作优先

现在让我们忽略类装饰。 (装饰是每个类前面的<xmlRoot(“ Employees”)>>之类的东西。我稍后再解释。

Group类允许我创建一组员工,实际上是一个很小的类,但是必需的类。

Employee类包含三个基本元素和一个JobJoorities类的元素。

这些课程中确实没有什么特别的。 您可以看到我确实重载了New构造函数-主要是为了方便起见-因此用户将有一种方法来构造新对象并轻松设置属性。 这些是非常简单明了的类,带有适当的setter和getter。 它具有正确构造的私有变量和公共属性。

创建对象,设置属性并序列化为XML

请注意,在Serialize模块的开头,我创建了一个名为EmploymentData的全局对象。 这是在将输出序列化为XML之前要向其添加数据的对象。

在button_click事件中,我输入了以下代码


    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click 
        Dim MyPriorities As JobPriorities 
        ReDim Preserve EmploymentData.Employees(2) 
        MyPriorities = New JobPriorities("Secretary", "Eye Candy", "Mistress")
        EmploymentData.Employees(0) = New Employee("Melissa", "Ryan", "1/1/1970", MyPriorities) 
        MyPriorities = New JobPriorities("Janitor", "Cook", "Bottlewasher")
        EmploymentData.Employees(1) = New Employee("Amanda", "Terranova", "1/1/1980", MyPriorities) 
        MyPriorities = New JobPriorities("Boss", "Idiot", "Syncophant")
        EmploymentData.Employees(2) = New Employee("Harlan", "Butts", "1/1/1980", MyPriorities) 
        SaveXML(MyXMLFile, EmploymentData, GetType(Group)) 
    End Sub 
在这里,我要从JobPriorities类创建MyPriorities对象,并使用一堆硬编码值设置EmploymentData对象的属性。 我觉得在示例中显示一定程度的嵌套很重要-因为这对于刚起步的人(例如我)可能会造成混淆并且难以理解。 EmploymentData对象(在Serialize模块中全局声明)将有3名雇员-因此我需要将其重新设置为2(0、1、2)。
ReDim Preserve EmploymentData.Employees(2)
我现在有一个我可以填写的EmploymentData数组。 EmploymentData的属性之一将是JobPriorities类型,我为此创建了MyPriorities。
Dim MyPriorities As JobPriorities
现在我可以填写结构数组

        MyPriorities = New JobPriorities("Secretary", "Eye Candy", "Mistress")
        EmploymentData.Employees(0) = New Employee("Melissa", "Ryan", "1/1/1970", MyPriorities) 
        MyPriorities = New JobPriorities("Janitor", "Cook", "Bottlewasher")
        EmploymentData.Employees(1) = New Employee("Amanda", "Terranova", "1/1/1980", MyPriorities) 
        MyPriorities = New JobPriorities("Boss", "Idiot", "Syncophant")
        EmploymentData.Employees(2) = New Employee("Harlan", "Butts", "1/1/1980", MyPriorities) 
最后,我可以将其发送给我的通用序列化功能
        SaveXML(MyXMLFile, EmploymentData, GetType(Group))
这是繁重的工作发生的地方。 序列化整个结构的功能实际上只是几行代码。 我将其保留为基本和通用,以便实际上可以传递任何对象。 我通过让它接受从Object基类派生的任何内容(几乎是VB中的所有内容)并返回从Object类派生的任何内容来做到这一点。 当您保存XML时,将其粘贴到文件名,带有数据的对象,并且必须准确告诉它要发送的对象。 通用序列化代码

    Public Function SaveXML(ByVal FileName As String, ByVal DataToSerialize As Object, ByVal objType As Type) As Boolean 
        'set up a blank namespace to eliminate unnecessary junk from the xml
        Dim nsBlank As New XmlSerializerNamespaces
        nsBlank.Add("", "") 
        'create an object for the xml settings to control how the xml is written and appears
        Dim xSettings As New System.Xml.XmlWriterSettings
        With xSettings
            .Encoding = Encoding.UTF8
            .Indent = True
            .NewLineChars = Environment.NewLine
            .NewLineOnAttributes = False
            .ConformanceLevel = Xml.ConformanceLevel.Document
        End With 
        Try
            'create the xmlwriter object that will write the file out
            Dim xw As System.Xml.XmlWriter = Xml.XmlWriter.Create(FileName, xSettings) 
            'create the xmlserializer that will serialize the object to XML
            Dim writer As New XmlSerializer(objType) 
            'now write it out
            writer.Serialize(xw, DataToSerialize, nsBlank) 
            'be sure to close it or it will remain open
            xw.Close() 
            Return True 
        Catch ex As Exception 
            MsgBox(ex.Message)
            Return False 
        End Try  
    End Function 
这段代码是不言自明的。 一个不明显的元素是我创建一个新的XmlSerializerNamespaces对象。 我这样做是因为.NET默认情况下会在您的XML中放入一些名称空间声明。 我认为这没有必要,只会产生噪音。 因此,通过创建一个空白的命名空间并将其包含在我的序列化程序中,它将删除它。

一旦写出,XML如下所示:


<?xml version="1.0" encoding="utf-8"?>
<Employees>
  <IndividualEmployee firstname="Melissa" lastname="Ryan" birthday="1/1/1970">
    <Jobs>
      <first_priority>Secretary</first_priority>
      <Second_priority>Eye Candy</Second_priority>
      <Third_priority>Mistress</Third_priority>
    </Jobs>
  </IndividualEmployee>
  <IndividualEmployee firstname="Amanda" lastname="Terranova" birthday="1/1/1980">
    <Jobs>
      <first_priority>Janitor</first_priority>
      <Second_priority>Cook</Second_priority>
      <Third_priority>Bottlewasher</Third_priority>
    </Jobs>
  </IndividualEmployee>
  <IndividualEmployee firstname="Harlan" lastname="Butts" birthday="1/1/1980">
    <Jobs>
      <first_priority>Boss</first_priority>
      <Second_priority>Idiot</Second_priority>
      <Third_priority>Syncophant</Third_priority>
    </Jobs>
  </IndividualEmployee>
</Employees> 
这非常漂亮,因为我设置了我创建的XMLWriterSettings对象的属性(xSettings)以定义XML的外观。 将XML读取到EmploymentData对象中

将XML重新返回到EmploymentData对象同样简单。

在另一个Button_Click事件中,我放置以下代码:


    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click 
        Dim EmployeeData As New Group 
        EmployeeData = GetXML(MyXMLFile, GetType(Group)) 
        'the following is just so you can see the output from the EmploymentData object 
        Dim sData As Employee
        With TextBox1
            For Each sData In EmployeeData.Employees
                .SelectedText = "Employee: " & sData.FirstName & " " & sData.LastName & Environment.NewLine
                .SelectedText = "Birthday: " & sData.Birthday & Environment.NewLine
                .SelectedText = "Job Responsabilities: " & Environment.NewLine
                .SelectedText = "     " & sData.Priorities.ResponsibilityOne & Environment.NewLine
                .SelectedText = "     " & sData.Priorities.ResponsibilityTwo & Environment.NewLine
                .SelectedText = "     " & sData.Priorities.ResponsibilityThree & Environment.NewLine
                .SelectedText = "---------------" & Environment.NewLine
            Next
            .SelectedText = ""
        End With 
    End Sub 
我基于组创建一个新的EmployeeData对象。 这里我不需要创建数组,因为反序列化将为我创建数组。

还有一堆代码将结果放入文本框,以便您可以看到它实际上反序列化了XML并创建了数组。

与串行器一样,解串器也是通用的。 我遵循相同的规则,并在基本Object类中返回数据。 要使用通用反序列化器,只需告诉它XML文件在哪里,并告诉它您希望反序列化的对象类型。


    Public Function GetXML(ByVal sFileName As String, ByVal objType As Type) As Object 
        If My.Computer.FileSystem.FileExists(sFileName) Then
            Dim fs As FileStream = New FileStream(sFileName, FileMode.Open)
            Dim xs As XmlSerializer = New XmlSerializer(objType)
            Dim obj As Object = CType(xs.Deserialize(fs), Object)
            fs.Close()
            Return obj
        Else
            Return Nothing
        End If 
    End Function 
这样有效! XML装饰

默认情况下,XML将使用您的类名作为节点名。 这对您来说可能很好。 我想覆盖正在执行的另一个项目中的命名,因此需要弄清楚这一点。 这是过程。

在为组类创建类时,您可以告诉序列化程序为元素和属性使用不同的名称。 通过在每个类前面加上适当的修饰,您将覆盖序列化代码的默认行为(即使用类名)。

因为Group是我的根类,所以我用

<XmlRoot(“ Employees”)> _
请注意,在Group Class中,我创建了一个名为Employees的成员变量数组,我希望将其显示为XML Elements,因此我使用修饰符:
<XmlElement(“ IndividualEmployees:)> _
由于它将是一个数组,因此序列化程序将为每个Employee节点赋予标签名称“ IndividualEmployee”。 您可以随意调用该节点。

对于Employee类中的每个属性,我装饰了适当的名称,但也将它们声明为Attributes。 我通过以下装饰做到了这一点:

<XmlAttribute(“ firstname”)> _
我对Employee类的四个属性中的三个进行了此操作,以便在对Employee进行序列化时,它们将成为XML中的属性,而不是新标记。 如果愿意,可以将它们作为Elements放置,但是我喜欢Attributes读取此数据的方式。 我决定将Priorities属性称为“ Jobs”并将其设为一个元素(因为它将具有子元素)。 我在那里使用了以下装饰:
<XmlElement(“工作”)> _

在JobPriorities类中,我使用装饰来创建元素并适当地命名它们。

总而言之,我的一些重命名可能会使代码更加混乱,但是我觉得很重要的一点是,展示如何使用装饰来定义属性以属性或元素的形式出现,以及可以使它们出现在属性中。具有所需名称的XML。 因此,如果它令人困惑-我知道,但是它是作为学习工具进行的。

我已经包含了一个完整的VS2008 VB.NET项目,您可以使用它。 它是自包含的,包括本文引用的所有源。

希望我没有做任何愚蠢的事情-但是不要让我知道。

德斯

附加的文件
文件类型:zip TestSerialization.zip (76.1 KB,905视图)

From: https://bytes.com/topic/visual-basic-net/insights/882418-basic-xml-serialization-vb-net

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值