一、XML序列化
序列化的目的:就是为了存储或传输。
通俗地说:序列化就是把一个完整的东西,拆成(精简)成一堆小的东西。
反序列化就是把一堆小东西,又复原成原来的东西。
下例,把一个实例对象序列化,拆成一个XML。
XML序列化要用到System.Xml.Serialization名称空间中的类和接口。
要把对象序列化到文档或流中时,可以使用Xmlserializer类。
注意下面定义时,VS出错时,可以用:
Dim myserializer As New Xml.Serialization.XmlSerializer(GetType(FilmOrder))
运行,可以看到实例就变成了XML(注意黄框部分)
- Imports System.Xml.Serialization '用于将对象序列化为 XML 格式文档或流的类
- Module Module1
- Sub Main()
- Dim serialize As XmlSerializer = New XmlSerializer(GetType(FilmOrder)) '指定序列化类型
- Dim myfileorder As FilmOrder = New FilmOrder("Grease",101,10) '指定类型的一个实例
- serialize.Serialize(Console.Out,myfileorder) '把实例序列化到流上(console.Out)
- Console.WriteLine() '显示序列化的结果
- Console.Read()
- End Sub
- End Module
- Public Class FilmOrder
- Public Name As String
- Public FileId As Integer
- Public Quantity As Integer
- Public Sub New()
- End Sub
- Public Sub New(ByVal name As String,ByVal fileid As Integer,ByVal quantity As Integer)
- Me.Name = name
- Me.FileId = fileid
- Me.Quantity = quantity
- End Sub
- End Class
注意: 1、最后序列化生成的XML文档,其根节点与类名相同,都是FilmOrder
2、类的每个数据成员都是XML元素。如:Name,FileId,Quantity。
3、节点后的是架构,描述文档数据。
上面只是序列化到标准流中,还要序列化到指定的Stream,TextWriter或XmlWriter中。
二、XML的反序列化
与序列化相对应的是反序列化。
前面是把对象序列化成一个XML文档。反序列化就是把XML文档来生成对象。
先准备一个XML文档:Filmorama.xml
- <?xml version="1.0" encoding="utf-8" ?>
- <FilmOrderList xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:xsd="http://www.w3.org/2001/XMLSchema">
- <FilmOrders>
- <FilmOrder>
- <Name>Grease</Name>
- <FilmId>101</FilmId>
- <Quantity>10</Quantity>
- </FilmOrder>
- <FilmOrder>
- <Name>Lawrence of Arabia</Name>
- <FilmId>102</FilmId>
- <Quantity>10</Quantity>
- </FilmOrder>
- <FilmOrder>
- <Name>Star Wars</Name>
- <FilmId>103</FilmId>
- <Quantity>10</Quantity>
- </FilmOrder>
- </FilmOrders>
- </FilmOrderList>
这个文档可以在解决方案中添加项,来把文档加入其中,把属性设置成如果较新则复制
由于上面FilmOrder是多个,因此,我们再设计一个类,来组装FilmOrderList,实际就是前面的类的数组形式。
- Imports System.Xml
- Imports System.Xml.Serialization
- Imports System.IO
- Module Module1
- Sub Main()
- Dim dehydrated As New FileStream("Filmorama.xml",FileMode.Open)
- Dim serialize As New XmlSerializer(GetType(FilmOrderList)) '类型应明确
- Dim myfileorder As New FilmOrderList
- myfileorder = serialize.Deserialize(dehydrated)
- Dim singleorder As FilmOrder
- For Each singleorder In myfileorder.FilmOrders
- Console.Out.WriteLine("{0},{1},{2}",singleorder.Name,singleorder.FilmId,singleorder.Quantity)
- Next
- Console.Read()
- End Sub
- End Module
- Public Class FilmOrder
- Public Name As String
- Public FilmId As Integer
- Public Quantity As Integer
- Public Sub New()
- End Sub
- Public Sub New(ByVal name As String,ByVal filmid As Integer,ByVal quantity As Integer)
- Me.Name = name
- Me.FilmId = filmid
- Me.Quantity = quantity
- End Sub
- End Class
- Public Class FilmOrderList
- Public FilmOrders() As FilmOrder
- Public Sub New()
- End Sub
- Public Sub New(ByVal orders() As FilmOrder)
- Me.FilmOrders = orders
- End Sub
- End Class
如果我们生成的XML包含属性(Attibute)时,什么办?
可以用<XMLAttribute("XXX")> 来指明对象中的数据为属性。
如果我们生成 的XML元素,要更改对象中的数据名怎么办?
可以用<XMLElement("XXX")> 来指明对应的数据名更名为XXX
- Imports System.Xml
- Imports System.Xml.Serialization
- Imports System.IO
- Module Module1
- Sub Main()
- Dim serializer As New XmlSerializer(GetType(FilmOrder))
- Dim fi As New FilmOrder("OK",100,100)
- serializer.Serialize(Console.Out,fi)
- Console.Out.WriteLine()
- Console.Read()
- End Sub
- End Module
- Public Class FilmOrder
- <XmlElement("Title")> Public Name As String '序列化生成XML时,Name元素将变成Title元素
- <XmlElement("Id")> Public FilmId As Integer
- <XmlElement("Qty")> Public Quantity As Integer
- Public Sub New()
- End Sub
- Public Sub New(ByVal name As String,ByVal quantity As Integer)
- Me.Name = name
- Me.FilmId = filmid
- Me.Quantity = quantity
- End Sub
- End Class
- <?xml version="1.0" encoding="utf-8" ?>
- <MovieOrderDump>
- <FilmOrderList>
- <multiFilmOrders>
- <FilmOrder filmId="101">
- <name>Grease</name>
- <quantity>10</quantity>
- </FilmOrder>
- <FilmOrder filmId="102">
- <name>Lawrence of Arabia</name>
- <quantity>10</quantity>
- </FilmOrder>
- <FilmOrder filmId="103">
- <name>Star Wars</name>
- <quantity>10</quantity>
- </FilmOrder>
- </multiFilmOrders>
- </FilmOrderList>
- <PreOrder>
- <FilmOrder filmId="104">
- <name>Shrek III - Shrek Becomes a Programmer</name>
- <quantity>10</quantity>
- </FilmOrder>
- </PreOrder>
- <Returns>
- <FilmOrder filmId="103">
- <name>Star Wars</name>
- <quantity>2</quantity>
- </FilmOrder>
- </Returns>
- </MovieOrderDump>
- '遍历读整个XML
- Imports System.Xml
- Imports System.Xml.Serialization
- Imports System.IO
- Public Class Form1
- Private Sub Button1_Click(sender As Object,e As EventArgs) Handles Button1.Click
- Dim myXmlSettings As New XmlReaderSettings
- Using readMoveInfo As XmlReader = XmlReader.Create("D:\2.xml",myXmlSettings)
- While readMoveInfo.Read() '读节点
- ShowXmlNode(readMoveInfo)
- While readMoveInfo.MoveToNextAttribute '逐个读该节点中的属性
- ShowXmlNode(readMoveInfo)
- End While
- End While
- End Using
- End Sub
- Private Sub ShowXmlNode(ByVal reader As XmlReader) '显示
- If reader.Depth > 0 Then
- For depthCount As Integer = 0 To reader.Depth '按节点深度增加缩进
- TextBox1.AppendText(" ")
- Next
- End If
- If reader.NodeType = XmlNodeType.Whitespace Then
- TextBox1.AppendText("Type:" & reader.NodeType.ToString & vbCrLf)
- ElseIf reader.NodeType = XmlNodeType.Text Then
- TextBox1.AppendText("Type:" & reader.NodeType.ToString & " Value:" & reader.Value & vbCrLf)
- Else
- TextBox1.AppendText("Name:" & reader.Name & " Type:" & reader.NodeType.ToString &
- " AttibuteCount:" & reader.AttributeCount & " Value:" & reader.Value & vbCrLf)
- End If
- End Sub
- End Class
- Dim myXmlSettings As New XmlReaderSettings
- myXmlSettings.IgnoreComments = True '忽略注释
- myXmlSettings.IgnoreWhitespace = True '忽略空白(因空白也会当作节点)
- Private Sub Button2_Click(sender As Object,e As EventArgs) Handles Button2.Click
- '对已知XML遍历
- Dim myXmlSettings As New XmlReaderSettings() '读取功能(方式)设置
- Dim movieName As String
- Dim movieId As String
- Dim quantity As String
- Using readMovieInfo As XmlReader = XmlReader.Create("D:\2.xml",myXmlSettings) '创建仅向前、非缓存的读取器实例
- readMovieInfo.Read() '当第一次创建和初始化 XmlReader 时,没有可用的信息。 必须调用 Read 读取第一个节点
- readMovieInfo.ReadStartElement("MovieOrderDump") '检查当前节点是否为元素,并将读取器推进到下一个节点
- Do While (True)
- readMovieInfo.ReadStartElement("FilmOrderList") '检查当前内容节点是否为具有给定 Name 的元素并将读取器推进到下一个节点
- readMovieInfo.ReadStartElement("multiFilmOrders")
- Do While (True)
- readMovieInfo.MoveToContent() '检查当前节点是否是内容节点。否,则向前跳至下一个内容节点或文件结尾。
- movieId = readMovieInfo.GetAttribute("filmId")
- readMovieInfo.ReadStartElement("FilmOrder")
- movieName = readMovieInfo.ReadElementString
- quantity = readMovieInfo.ReadElementString()
- readMovieInfo.ReadEndElement() '读取结束标志</FilmOrder>
- TextBox1.AppendText(movieId & " " & movieName & " " & quantity & vbCrLf)
- readMovieInfo.Read() '下个FilmOrder节点
- If (readMovieInfo.Name <> "FilmOrder") Then '否则退出
- Exit Do
- End If
- Loop
- readMovieInfo.ReadEndElement() '读结束标志</multiFilmOrders>,并进入下一个节点
- readMovieInfo.ReadEndElement() '读结束标志</FilmOrderList>,并进入下一个节点
- readMovieInfo.Read() '下个FilmOrderList节点
- If readMovieInfo.Name <> "FilmOrderList" Then '不是则退出
- Exit Do
- End If
- Loop
- readMovieInfo.ReadStartElement() '</MovieOrderDump>
- End Using
- End Sub