1

我一直在 .net 中使用 Xml 序列化/反序列化,并且想要一种方法,其中序列化/反序列化过程仅适用于 Xml 片段的某些部分。这样我就可以在反序列化过程之后将片段的某些部分保留在 Xml 中。

为此,我认为最好创建一个实现 IXmlSerializable 的新类 (XmlLiteral),然后编写特定代码来处理 IXmlSerializable.ReadXml 和 IXmlSerializable.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
4

1 回答 1

1

设法通过对 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
于 2010-04-29T15:05:21.813 回答