在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项目,您可以使用它。 它是自包含的,包括本文引用的所有源。
希望我没有做任何愚蠢的事情-但是不要让我知道。
德斯
From: https://bytes.com/topic/visual-basic-net/insights/882418-basic-xml-serialization-vb-net