XML Serializer List-Probleme [VB .NET]

luigied

Mitglied
Hi,
ich arbeite seit knapp einer Woche mit VB .NET und versuche jetzt einen Teil meiner Klassenstruktur in XML abzubilden.

Dazu wollte ich den XMLSerializer benutzen.

ICh habe eine Klasse A, die als Attribute einen String, eine List von Typ B und und eine List vom Typ C enthält. B und C sind Objekte mit eigenen Attributen,

Als Ergebniss wollte ich soetwas:

Code:
<A name="blubb">
<Bs>
   <B foo="bar" />
   <B foo="bar2" />
</Bs>
<Cs>
   <C bar="foo"/>
   <C bar="foo2" />
</Cs>

A, B und C implementieren das Interface IXMLSerializable. Allerdings versteh ich nicht ganz, wie ich einen SchemaType Elemente hinzufügen kann. (Attribute versteh ich)

Code:
Public Shared Function CreateASchema(ByVal schemaSet As XmlSchemaSet) As XmlQualifiedName
		Dim schema As XmlSchema = New XmlSchema()
		schema.Id = "ASchema"
		schema.TargetNamespace = "urn: types-ade-test"
		Dim Type As XmlSchemaComplexType = New XmlSchemaComplexType
		Type.Name = "ARoot"

		Dim NameAttr As XmlSchemaAttribute = New XmlSchemaAttribute()
		NameAttr.Name = "Name"
		Type.Attributes.Add(NameAttr)

                'Hier sollten dann die Lists angefügt werden

                ...

Könnt ihr mir bitte erklären, wie ich das realisiere? ICh finde in der Literatur nix Passendes.

Danke schonmal.

Mfg LuigiEd
 
Hey, ich habe das Problem jetzt gelöst.

So sieht es bei mir aus:

Die Klassen B und C sehen dann vom Prinzip her so aus:

Code:
<XmlSchemaProvider("CreateCSchema")>
Public Class C
    Implements IXmlSerializable

    Private foo As String

    Public Sub WriteXml(ByVal writer As XmlWriter) _
       Implements IXmlSerializable.WriteXml
        writer.WriteAttributeString("foo", foo)
    End Sub

    Public Sub ReadXml(ByVal reader As XmlReader) _
       Implements IXmlSerializable.ReadXml
        foo = reader.GetAttribute(0)
    End Sub
... hinzukommen natürlich noch Konstruktoren, Getter, Setter, etc. ;)

Die Klasse A sieht wie folgt aus:
Code:
<XmlSchemaProvider("CreateTransformationSchema")>
Public Class Transformation
    Implements IXmlSerializable

    Private mName As String
    Private mBs As New List(Of B)
    Private mCs As New List(Of C)

    Public Sub WriteXml(ByVal writer As XmlWriter) _
    Implements IXmlSerializable.WriteXml
        writer.WriteAttributeString("Name", mName)   '(1)
        writer.WriteStartElement("Bs", "")
        Dim bSerializer As XmlSerializer = New             '(2) System.Xml.Serialization.XmlSerializer(mBs.Item(0).GetType)
        For Each b As B In mBs
            bSerializer.Serialize(writer, b)     '(3)
        Next (b)
        writer.WriteEndElement()
        writer.WriteStartElement("Cs", "")
        Dim cSerializer As XmlSerializer = New System.Xml.Serialization.XmlSerializer(mCs.Item(0).GetType)
        For Each c As C In mCs
            cSerializer.Serialize(writer, c)      
        Next (c)
        writer.WriteEndElement()
    End Sub

    Public Sub ReadXml(ByVal reader As XmlReader) _
     Implements IXmlSerializable.ReadXml

        mName = reader.GetAttribute(0)
        Console.WriteLine(mName)

        reader.ReadStartElement()           '(4)
        Dim bs As String = reader.ReadOuterXml()      '(5)
        
        Dim bReader As New XmlSerializer(GetType(B))
        Dim bReader2 As TextReader = New StringReader(bs)
        Dim bReader3 As XmlReader = New XmlTextReader(bReader2)
        srcReader3.ReadToDescendant("b")          '(6)
        While Not (bReader3.NodeType = System.Xml.XmlNodeType.None)    '(7)
            Dim obj As Object = bReader.Deserialize(bReader3)       '(8)
            If (obj Is Nothing) Then
                Exit While
            End If
            Dim b As B = CType(obj, B)
            mBs.Add(b)
            bReader3.ReadToNextSibling("b")                   '(9)
        End While
        bReader2.Close()
        bReader3.Close()
        ...

    End Sub

Als erstes schreiben wir das Name-Attribute raus. (1) Nachdem der Bereich für die Bs geöffnet wurde, legen wir einen neuen Serializer an, der sich um unsere B-Klasse kümmert (2). Jetzt serialisieren wir jedes Objekt in unserer Liste (3). Das Ganze erledigen wir dann noch für unsere 2. Liste und stellen abschließend sicher, dass wir alle Tags wieder geschlossen haben. Fertsch

Das Deserialisieren ist eine Nummer für sich. :)
Als erstes Lesen wir unser RootElement (Hier: A) (4). Dann Holen wir uns den gesammten <Bs>-Block (5). Wenn wir einen neuen XMLReader erzeugt haben, gehen wir als erstes eine Stufe in unserem Baum tiefer zu unserem ersten b-Element. (6) Und solange das aktuelle Element im Reader nicht leer ist (7) können wir es deserialisieren (8) und dann zum nächsten b-Element springen (9).

Das Ganze zelebrieren wir anschließend noch für unsere Cs und drücken die Daumen, dass wir valide XML-Dateien nutzen. ;)

Ich hoffe, dass ich damit jemandem helfen konnte.

In diesem Sinne

Mfg LuigiEd
 
Zurück