VB.NET XmlSerializer实现带属性元素与序号化元素序列化
嘿,刚好我之前处理过类似的XML序列化需求,给你一步步解决这两个问题:
需求1:实现带属性的Block元素(同时包含文本和id_Block属性)
原来的Block是简单的字符串类型,没法同时包含属性和文本值,我们需要把它改成一个自定义类,用XmlAttribute标记属性,XmlText标记文本内容:
Public Class Block <XmlAttribute("id_Block")> Public Property IdBlock As Integer <XmlText> Public Property Text As String End Class
然后修改Xyz类里的Block属性类型:
Public Class Xyz ' 保留其他原有属性... <XmlElement("Block")> Public Property Block As Block Public Sub New() test = New List(Of Test) End Sub End Class
赋值的时候直接实例化Block类即可:
xyz.Block = New Block() With {.IdBlock = 5, .Text = "Abc"}
这样序列化后就能得到<Block id_Block=5>Abc</Block>的结构。
需求2:生成带序号后缀的Test_0、Test_1元素
默认的XmlSerializer处理列表时只会生成同名元素,没法动态添加序号后缀,这时候需要让Xyz类实现IXmlSerializable接口,手动控制序列化过程:
修改后的完整Xyz类(包含两个需求的实现):
Imports System.Xml Imports System.Xml.Serialization Public Class Xyz <XmlAttribute> Public Property id As Integer <XmlElement> Public Property name As String <XmlElement> Public Property comment As String <XmlElement("Block")> Public Property Block As Block ' 保留Test列表用于存储数据 Public Property test As List(Of Test) Public Sub New() test = New List(Of Test) End Sub ' 实现IXmlSerializable接口 Public Function GetSchema() As XmlSchema Implements IXmlSerializable.GetSchema Return Nothing End Function Public Sub ReadXml(reader As XmlReader) Implements IXmlSerializable.ReadXml ' 反序列化逻辑(如果需要导入XML的话) id = Integer.Parse(reader.GetAttribute("id")) reader.ReadStartElement() While reader.NodeType <> XmlNodeType.EndElement Select Case reader.LocalName Case "name" name = reader.ReadElementContentAsString() Case "comment" comment = reader.ReadElementContentAsString() Case "Block" Dim block = New Block() block.IdBlock = Integer.Parse(reader.GetAttribute("id_Block")) block.Text = reader.ReadElementContentAsString() Me.Block = block Case Else ' 解析带序号的Test_*元素 If reader.LocalName.StartsWith("Test_") Then Dim testObj = New Test() reader.ReadStartElement() testObj.name = reader.ReadElementContentAsString() reader.ReadEndElement() test.Add(testObj) Else reader.Skip() End If End Select End While reader.ReadEndElement() End Sub Public Sub WriteXml(writer As XmlWriter) Implements IXmlSerializable.WriteXml ' 手动序列化id属性 writer.WriteAttributeString("id", id.ToString()) ' 序列化name、comment元素 If Not String.IsNullOrEmpty(name) Then writer.WriteElementString("name", name) End If If Not String.IsNullOrEmpty(comment) Then writer.WriteElementString("comment", comment) End If ' 序列化Block元素 If Block IsNot Nothing Then writer.WriteStartElement("Block") writer.WriteAttributeString("id_Block", Block.IdBlock.ToString()) writer.WriteString(Block.Text) writer.WriteEndElement() End If ' 生成带序号的Test元素 For i = 0 To test.Count - 1 writer.WriteStartElement($"Test_{i}") ' 序列化单个Test对象 Dim testSerializer = New XmlSerializer(GetType(Test)) testSerializer.Serialize(writer, test(i)) writer.WriteEndElement() Next End Sub End Class Public Class Test <XmlElement> Public Property name As String End Class Public Class Block <XmlAttribute("id_Block")> Public Property IdBlock As Integer <XmlText> Public Property Text As String End Class
关键说明:
- 在
WriteXml方法里,我们遍历test列表,动态创建Test_0、Test_1这样的元素名,然后用子序列化器把每个Test对象写入对应元素。 - 如果需要支持反序列化(也就是导入XML到对象),
ReadXml方法里的逻辑已经帮你处理了解析带序号的Test元素,直接用即可。
测试序列化代码:
Dim xyz = New Xyz() With { .id = 0, .name = "Abc", .comment = "Abc", .Block = New Block() With {.IdBlock = 5, .Text = "Abc"} } xyz.test.Add(New Test() With {.name = "Abc"}) xyz.test.Add(New Test() With {.name = "Def"}) xyz.test.Add(New Test() With {.name = "Ghi"}) Dim serializer = New XmlSerializer(GetType(Xyz)) Using writer = New StreamWriter("output.xml") serializer.Serialize(writer, xyz) End Using
运行后生成的XML完全符合你要的目标结构。
内容的提问来源于stack exchange,提问作者Cit
相关产品推荐
相关产品推荐

