Issue allowing custom Xml Serialization/Deserialization on certain types of field
- by sw1sh
I've been working with Xml Serialization/Deserialization in .net and wanted a method where the serialization/deserialization process would only be applied to certain parts of an Xml fragment. This is so I can keep certain parts of the fragment in Xml after the deserialization process.
To do this I thought it would be best to create a new class (XmlLiteral) that implemented IXmlSerializable and then wrote specific code for handling the IXmlSerializable.ReadXml and IXmlSerializable.WriteXml methods.
In my example below this works for Serializing, however during the Deserialization process it fails to run for multiple uses of my XmlLiteral class. In my example below sTest1 gets populated correctly, but sTest2 and sTest3 are empty.
I'm guessing I must be going wrong with the following lines but can't figure out why.. Any ideas at all?
Private Sub ReadXml(ByVal reader As System.Xml.XmlReader) Implements IXmlSerializable.ReadXml
Dim StringType As String = ""
If reader.IsEmptyElement OrElse reader.Read() = False Then
Exit Sub
End If
_src = reader.ReadOuterXml()
End Sub
Full listing:
Imports System
Imports System.Xml.Serialization
Imports System.Xml
Imports System.IO
Imports System.Text
Public Class XmlLiteralExample
Inherits System.Web.UI.Page
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim MyObjectInstance As New MyObject
MyObjectInstance.aProperty = "MyValue"
MyObjectInstance.XmlLiteral1 = New XmlLiteral("<test1>Some Value</test1>")
MyObjectInstance.XmlLiteral2 = New XmlLiteral("<test2>Some Value</test2>")
MyObjectInstance.XmlLiteral3 = New XmlLiteral("<test3>Some Value</test3>")
' quickly serialize the object to Xml
Dim sw As New StringWriter(New StringBuilder())
Dim s As New XmlSerializer(MyObjectInstance.[GetType]()), xmlnsEmpty As New XmlSerializerNamespaces
xmlnsEmpty.Add("", "")
s.Serialize(sw, MyObjectInstance, xmlnsEmpty)
Dim XElement As XElement = XElement.Parse(sw.ToString())
' XElement reads as the following, so serialization works OK
'<MyObject>
' <aProperty>MyValue</aProperty>
' <XmlLiteral1>
' <test1>Some Value</test1>
' </XmlLiteral1>
' <XmlLiteral2>
' <test2>Some Value</test2>
' </XmlLiteral2>
' <XmlLiteral3>
' <test3>Some Value</test3>
' </XmlLiteral3>
'</MyObject>
' quickly deserialize the object back to an instance of MyObjectInstance2
Dim MyObjectInstance2 As New MyObject
Dim xmlReader As XmlReader, x As XmlSerializer
xmlReader = XElement.CreateReader
x = New XmlSerializer(MyObjectInstance2.GetType())
MyObjectInstance2 = x.Deserialize(xmlReader)
Dim sProperty As String = MyObjectInstance2.aProperty ' equal to "MyValue"
Dim sTest1 As String = MyObjectInstance2.XmlLiteral1.Text ' contains <test1>Some Value</test1>
Dim sTest2 As String = MyObjectInstance2.XmlLiteral2.Text ' is empty
Dim sTest3 As String = MyObjectInstance2.XmlLiteral3.Text ' is empty
' sTest3 and sTest3 should be populated but are not?
xmlReader = Nothing
End Sub
Public Class MyObject
Private _aProperty As String
Private _XmlLiteral1 As XmlLiteral
Private _XmlLiteral2 As XmlLiteral
Private _XmlLiteral3 As XmlLiteral
Public Property aProperty As String
Get
Return _aProperty
End Get
Set(ByVal value As String)
_aProperty = value
End Set
End Property
Public Property XmlLiteral1 As XmlLiteral
Get
Return _XmlLiteral1
End Get
Set(ByVal value As XmlLiteral)
_XmlLiteral1 = value
End Set
End Property
Public Property XmlLiteral2 As XmlLiteral
Get
Return _XmlLiteral2
End Get
Set(ByVal value As XmlLiteral)
_XmlLiteral2 = value
End Set
End Property
Public Property XmlLiteral3 As XmlLiteral
Get
Return _XmlLiteral3
End Get
Set(ByVal value As XmlLiteral)
_XmlLiteral3 = value
End Set
End Property
Public Sub New()
_XmlLiteral1 = New XmlLiteral
_XmlLiteral2 = New XmlLiteral
_XmlLiteral3 = New XmlLiteral
End Sub
End Class
<System.Xml.Serialization.XmlRootAttribute(Namespace:="", IsNullable:=False)> _
Public Class XmlLiteral
Implements IXmlSerializable
Private _src As String
Public Property Text() As String
Get
Return _src
End Get
Set(ByVal value As String)
_src = value
End Set
End Property
Public Sub New()
_src = ""
End Sub
Public Sub New(ByVal Text As String)
_src = Text
End Sub
#Region "IXmlSerializable Members"
Private Function GetSchema() As System.Xml.Schema.XmlSchema Implements IXmlSerializable.GetSchema
Return Nothing
End Function
Private Sub ReadXml(ByVal reader As System.Xml.XmlReader) Implements IXmlSerializable.ReadXml
Dim StringType As String = ""
If reader.IsEmptyElement OrElse reader.Read() = False Then
Exit Sub
End If
_src = reader.ReadOuterXml()
End Sub
Private Sub WriteXml(ByVal writer As System.Xml.XmlWriter) Implements IXmlSerializable.WriteXml
writer.WriteRaw(_src)
End Sub
#End Region
End Class
End Class