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メソッドでさらに作業することにより、これを修正することができました。さらに調査した結果、次のリーダーが正しく機能するように、ReadXmlメソッドをreader.ReadEndElement()で終了することが非常に重要であることがわかりました。このソリューションが誰かを助けてくれることを願っています!

    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 に答える