允许对某些类型的字段进行自定义 Xml 序列化/反序列化的问题

发布于 2024-08-30 09:00:11 字数 5640 浏览 11 评论 0原文

我一直在 .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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

多情出卖 2024-09-06 09:00:11

设法通过在 ReadXml 方法上进行更多工作来解决此问题。经过更多研究,我发现用 reader.ReadEndElement() 结束 ReadXml 方法非常重要,以便下一个读取器正常工作。希望这个解决方案可以帮助别人!

    Private Sub ReadXml(ByVal reader As System.Xml.XmlReader) Implements IXmlSerializable.ReadXml
        If reader.IsEmptyElement OrElse reader.Read() = False Then
            Exit Sub
        End If
        While reader.NodeType <> System.Xml.XmlNodeType.EndElement
            _src = reader.ReadOuterXml
        End While
        reader.ReadEndElement()
    End Sub

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!

    Private Sub ReadXml(ByVal reader As System.Xml.XmlReader) Implements IXmlSerializable.ReadXml
        If reader.IsEmptyElement OrElse reader.Read() = False Then
            Exit Sub
        End If
        While reader.NodeType <> System.Xml.XmlNodeType.EndElement
            _src = reader.ReadOuterXml
        End While
        reader.ReadEndElement()
    End Sub
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文