允许对某些类型的字段进行自定义 Xml 序列化/反序列化的问题
我一直在 .net 中使用 Xml 序列化/反序列化,并且想要一种方法,其中序列化/反序列化过程仅应用于 Xml 片段的某些部分。这样我就可以在反序列化过程之后将片段的某些部分保留在 Xml 中。
为此,我认为最好创建一个新类 (XmlLiteral) 来实现 IXmlSerializes,然后编写用于处理 IXmlSerializes.ReadXml 和 IXmlSerializes.WriteXml 方法的特定代码。
在下面的示例中,这适用于序列化,但是在反序列化过程中,它无法运行以多次使用我的 XmlLiteral 类。在下面的示例中,sTest1 已正确填充,但 sTest2 和 sTest3 为空。
我猜我一定在下面的几行中出错了,但无法弄清楚为什么..有什么想法吗?
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
完整清单:
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
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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
设法通过在 ReadXml 方法上进行更多工作来解决此问题。经过更多研究,我发现用 reader.ReadEndElement() 结束 ReadXml 方法非常重要,以便下一个读取器正常工作。希望这个解决方案可以帮助别人!
Managed to fix this by working some more on the ReadXml method. After more research I found out that it is very important to end the ReadXml method with reader.ReadEndElement() so that the next reader works correctly. Hope this solutions helps somebody out!