none
Wie parse ich vernünftig XML Node für Node? RRS feed

  • Frage

  • Hallo,

    so langsam zweifel ich an meinen Programmier"künsten"! ;) Ich habe folgendes Problem (ich nutze VS2017Community mit VB):

    ich habe eine XML-Datei erstellt, die folgendermaßen aussieht:

    <?xml version="1.0" encoding="utf-8" ?>
    
    <Klassen>
    
      <Klasse id="1">
        <Name>Dieb</Name>
        <Attribute>
          <Mut>1W8+3</Mut>
          <Klugheit>1W6+8</Klugheit>
          <Intuition>1W8+7</Intuition>
          <Charisma>1W8+5</Charisma>
          <Fingerfertigkeit>1W8+9</Fingerfertigkeit>
          <Geschicklichkeit>1W8+8</Geschicklichkeit>
          <Konstitution>2W4+4</Konstitution>
          <Körperkraft>1W10+5</Körperkraft>      
        </Attribute>
      </Klasse>
      <Klasse id="2">
        <Name>Händler</Name>
        <Attribute>
          <Mut>1W8+2</Mut>
          <Klugheit>1W8+8</Klugheit>
          <Intuition>1W10+7</Intuition>
          <Charisma>1W10+5</Charisma>
          <Fingerfertigkeit>1W6+6</Fingerfertigkeit>
          <Geschicklichkeit>1W4+8</Geschicklichkeit>
          <Konstitution>2W4+4</Konstitution>
          <Körperkraft>1W8+6</Körperkraft>
        </Attribute>
      </Klasse>
    </Klassen>

    Nun möchte ich die einzelnen Werte abrufen und zwar nur für eine "Klasse" (sagen wir "Dieb"). Ich habe jetzt in den MSDN-Hilfen alles Mögliche zu XML (und auch LINQ) gelesen, aber ich komme nicht wirklich weiter.

    Zunächst dachte ich, dass ich mit XElement 1 Unterknoten von Klassen zurück kriegen würde, aber das war wohl ein Fehler; es liefert ja ALLE einzelnen "Klasse"-Elemente innerhalb <Klassen>.

    Nun die Gretchenfrage, die ich mir immer noch nicht beantworten kann:

    wie kann ich alle Werte der einzelnen Nodes aus einer bestimmten Klasse auslesen und entsprechenden Variablen zuweisen?

    Also quasi: Var_Mut = Wert von <Mut> der Klasse mit der id=1

    Ich hoffe, ich habe mich hinreichend verständlich ausgedrückt. ;)

    Mittlerweile weiß ich (wieder), warum ich das Programmieren nicht mehr beruflich mache... ;)

    Danke jedenfalls für jeden hilfreichen Hinweis.

    Gruß

    WarFred

    Sonntag, 15. Juli 2018 13:44

Antworten

  • Hi Fred,
    in VB.NET gibt es eine sehr gute Unterstützung für XML. Es reicht, den XML-Stream (Datei o.ä.) in ein XElement einzulesen. Da wird im Hintergrund der Parser ausgeführt, der im XElement die Struktur der XML-Daten abgelegt. Den Umweg über XDocument brauchst Du nicht zu machen. Mit LinQ to XML kannst Du dann direkt auf die Knoten zugreifen. Diese Unterstützung ist in VB.NET viel eleganter als in C#.NET. Deine Methode Fuelle sieht nach der Umstellung auf XElement und LinQ so aus:

        Public Function Fuelle(id As Integer) As XElement
          Return (From xe1 In xe0.Descendants Where CType(xe1.@id, Integer) = id).FirstOrDefault
        End Function

    Deine Codeschnispel habe ich mal als Demo erstellt. Ich habe lediglich den Dateinamen geändert und zur Erzeugung des Pfades die Path-Klasse genutzt.

    Imports System.IO
    
    Public Class Form1
      Private WithEvents BtnStart As New Button With {.Text = "Start"}
      Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Me.Controls.AddRange(New Control() {BtnStart})
      End Sub
    
      Private Sub BtnStart_Click(sender As Object, e As EventArgs) Handles BtnStart.Click
        Dim Var_Klasse As XElement
        Dim Var_Test As New Test()
        Dim Var_Node As XElement
        Dim id = 3
        Var_Node = Var_Test.Fuelle(id)
        Var_Klasse = Var_Node
    
      End Sub
    
      Public Class Test
        Private xe0 As XElement
    
        Public Sub New()
          Dim Pfad As String = My.Application.Info.DirectoryPath
          xe0 = XElement.Load(Path.Combine(Pfad, "Form45XMLFile1.xml"))
        End Sub
    
        Public Function Fuelle(id As Integer) As XElement
          Return (From xe1 In xe0.Descendants Where CType(xe1.@id, Integer) = id).FirstOrDefault
        End Function
    
      End Class
    End Class


    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP)
    Meine Homepage mit Tipps und Tricks


    • Bearbeitet Peter Fleischer Montag, 16. Juli 2018 07:22
    • Als Antwort markiert WarFred Dienstag, 17. Juli 2018 09:00
    Montag, 16. Juli 2018 07:09
  • Hi Michael,
    mit dem XElement ist ganz leicht, Knoten für Knoten zu verarbeiten. Wenn mit JSon gearbeitet wird, dann kann man direkt aus dem JSon eigene Objekte erstellen. Eine direkte Umwandlung in .NET-Objekte mit eigener Struktur ist aus dem XElement ist nicht so einfach möglich wie aus JSon. Die Syntax in VB.NET in LinQtoXML ist aber sehr elegant, was das problemlose Extrahieren von Untermengen ermöglicht (einfacher als in C#.NET). Aus diesem Grund ist es wichtig, ob im Projekt mit Objekten eigener Struktur (Klassen) oder nur mit Inhalten aus dem XML zu arbeiten ist. Auch ist wichtig, ob Änderungen der Werte dann in XML zurückzuschreiben sind. Wenn es wenige Klassen sind, dann kann sich der Aufwand lohnen, selbst etwas zu programmieren, z.B. so:

    Imports System.IO
    
    Public Class Form45
      Private WithEvents BtnStart As New Button With {.Text = "Start", .Dock = DockStyle.Top}
      Private lb As New ListBox With {.Dock = DockStyle.Fill}
      Private Sub Form45_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Me.Controls.AddRange(New Control() {lb, BtnStart})
      End Sub
    
      Private Sub BtnStart_Click(sender As Object, e As EventArgs) Handles BtnStart.Click
        Dim Var_Test As New Test()
        lb.DataSource = Var_Test.Fuelle
      End Sub
    
      Public Class Test
        Private xe0 As XElement
    
        Public Sub New()
          Dim Pfad As String = My.Application.Info.DirectoryPath
          xe0 = XElement.Load(Path.Combine(Pfad, "Form45XMLFile1.xml"))
        End Sub
    
        Public Function Fuelle() As List(Of Klasse)
          Return (From xe1 In xe0...<Klasse> Select New Klasse(xe1)).ToList
        End Function
    
      End Class
    
      Public Class Klasse
        Public Sub New(xe2 As XElement)
          Name = xe2...<Name>.Value
          Mut = xe2...<Attribute>.<Mut>.Value
          Klugheit = xe2...<Attribute>.<Klugheit>.Value
          ' usw.
        End Sub
        Public Property Name As String
        Public Property Mut As String
        Public Property Klugheit As String
        ' usw.
    
        ''' <summary>
        ''' Objekt als XML-String zurückgeben
        ''' </summary>
        ''' <returns></returns>
        Public Function SaveKlasse() As String
          Dim xe4 As New XElement("Klasse")
          xe4.Add(New XElement("Name") With {.Value = Name})
          Dim xe5 As New XElement("Attribute")
          xe4.Add(xe5)
          xe5.Add(New XElement("Mut") With {.Value = Mut})
          xe5.Add(New XElement("Klugheit") With {.Value = Klugheit})
          ' usw.
    
          Return xe4.ToString
        End Function
    
        ''' <summary>
        ''' Für Anzeige
        ''' </summary>
        ''' <returns></returns>
        Public Overrides Function ToString() As String
          Return $"Name: {Name}, Mut: {Mut}, Klugheit: {Klugheit}"
        End Function
      End Class
    
    End Class


    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP)
    Meine Homepage mit Tipps und Tricks

    • Als Antwort markiert WarFred Montag, 16. Juli 2018 08:39
    Montag, 16. Juli 2018 08:36

Alle Antworten

  • Hi,

    warum nutzt Du nicht XML Serialisierung/Deserialisierung? Damit ist das doch erheblich einfacher zu machen.

    Hier mal zwei Methoden, mit denen Du aus einem beliebigen serialisierbaren Object einen XML String und umgekehrt aus dem XML String ein passendes Objekt erzeugen kannst.

    Public Shared Function SerializeObject( Of T )( ByVal DataObject As T ) As String
    
    Dim Result       As String
    Dim Serializer   As New XmlSerializer( GetType( T ), String.Empty )
    Dim MemoryStream As New MemoryStream()
    Dim TextWriter   As New XmlTextWriter( MemoryStream, Encoding.UTF8 )
        TextWriter.Indentation = 4
        TextWriter.IndentChar  = " "c
        TextWriter.Formatting  = Formatting.Indented
    
    Dim XmlNamespace As New XmlSerializerNamespaces()
        XmlNamespace.Add( String.Empty, String.Empty )
    
        Serializer.Serialize( TextWriter, DataObject, XmlNamespace )
    
        Result = Encoding.UTF8.GetString( MemoryStream.ToArray() )
    
        TextWriter.Close()
        MemoryStream.Close()
        MemoryStream.Dispose()
    
        Return Result
    
    End Function
    
    Public Shared Function DeserializeString( Of T )( ByVal XmlContent As String ) As T
    
    Dim Result       As T
    Dim Serializer   As New XmlSerializer( GetType( T ) )
    Dim StringReader As New StringReader( XmlContent )
    
        Result = DirectCast( Serializer.DeSerialize( StringReader ), T )
    
        StringReader.Close()
        StringReader.Dispose()
    
        Return Result
    
    End Function
    

    Da musst dann nur noch deine Klassenstruktur erstellen, die dem Aufbau der XML Datei entspricht.

    Über das Hilfsprogramm xsd.exe kannst Du aus der .xsd (oder auch einer .xml) die zugehörigen Codedateien für die Klassen erstellen lassen.

      http://msdn.microsoft.com/de-de/library/x6c1kb0s.aspx

    Über entsprechende Kommandozeilenparameter lassen sich einige Optionen bzgl. der Generierung des Codes einstellen.


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET (2001-2018)
    https://www.asp-solutions.de/ - IT Beratung, Softwareentwicklung, Remotesupport

    Sonntag, 15. Juli 2018 14:58
    Moderator
  • Hallo Stefan,

    erst einmal vielen Dank für deine schnelle Antwort.

    Zu deiner ersten Frage, warum ich das nicht nutze: weil ich davon noch nix gehört habe und auch dein Coding liest sich für mich wie Hebräisch ;)

    Ich behalte es mal im Hinterkopf, weil ich denke, dass es da doch eine "einfachere" Möglichkeit geben muss. Ich kann doch nicht der Erste sein, der dieses Problem hat. Insofern warte ich mal ab, ob noch jemand eine andere Idee hat.

    Sonntag, 15. Juli 2018 15:29
  • Hallo WarFred,

    Stefan hat schon recht, es ist die einfachste und beste Möglichkeit aus dem XML wieder ein Objekt zu machen und erst dann damit zu arbeiten.

    Du könntest aber auch mit JSON arbeiten, ist um einiges einfacher. Hier findest Du auch ein Beispiel Link 


    Gruß Thomas
    13 Millionen Schweine landen jährlich im Müll
    Dev Apps von mir: UWP Segoe MDL2 Assets, UI Strings

    Sonntag, 15. Juli 2018 17:14
  • Das Ganze kommt mir aber so ein bisschen "durch die Brust ins Auge" vor. Da muss es doch was einfacheres geben.

    So in etwa: Node isolieren (also aus einem XElement den richtigen Node heraussuchen), und dann die einzelnen "Unter"Nodes immer mit NextNode durchgehen. Sowas soll nicht einfach gehen? Ich kann es nicht glauben.

    Trotzdem auch Danke für deine Einschätzung Thomas.

    Sonntag, 15. Juli 2018 17:39
  • So, den ersten Teil meiner Aufgabe, das "Extrahieren" der entsprechenden Nodes habe ich mittlerweile hinbekommen:

    Imports System.Xml
    
    Public Class Test
        Private Cls_Klassen As New XDocument
    
        Public Sub New()
            Dim Pfad As String = My.Application.Info.DirectoryPath & "\XML\"
    
            Cls_Klassen = XDocument.Load(Pfad & "Klassen.xml")
    
        End Sub
    
        Public Function Fuelle(id As Integer) As XNode
    
            For Each node As XNode In Cls_Klassen.DescendantNodes
                If node.NodeType = XmlNodeType.Element Then
                    For Each att In DirectCast(node, XElement).Attributes
                        If att.Name = "id" Then
                            If att.Value = id.ToString Then
                                Return node
                                Exit Function
                            End If
                        End If
                    Next
                End If
            Next
            Return Nothing
    
        End Function
    
    End Class

    Aufgerufen wird das Ganze mit:

    Private Sub BtnStart_Click(sender As Object, e As EventArgs) Handles BtnStart.Click
            Dim Var_Klasse As XElement
            Dim Var_Test As New Test()
            Dim Var_Node As XNode
    
            Var_Node = Var_Test.Fuelle(id)
            Var_Klasse = Var_Node
            
        End Sub

    Anschließend habe ich in Var_Klasse nur noch die entsprechende "Klasse" aus dem XML, also nur noch:

      <Klasse id="3">
        <Name>Kämpfer</Name>
        <Attribute>
          <Mut>1W6+8</Mut>
          <Klugheit>1W6+7</Klugheit>
          <Intuition>1W6+5</Intuition>
          <Charisma>1W8+5</Charisma>
          <Fingerfertigkeit>1W8+6</Fingerfertigkeit>
          <Geschicklichkeit>1W8+7</Geschicklichkeit>
          <Konstitution>2W6+6</Konstitution>
          <Körperkraft>2W4+9</Körperkraft>
        </Attribute>
      </Klasse>

    Das Ganze mag bis dahin vielleicht nicht elegant gelöst sein, aber es erfüllt seinen Zweck ohne dass ich mich extra in JASON oder Serialization einarbeiten müsste. Ich hoffe, den Rest kriege ich jetzt auch alleine hin.

    Bei diesem Forum habe ich manchmal das Gefühl, dass unglaubliche Experten hier Tipps geben (und nein, ich meine das nicht sarkastisch oder ironisch, sondern tatsächlich!), die aber das Gefühl für die einfachen Lösungen verloren haben. Dies ist meine zweite Anfrage hier und zum zweiten Mal gebe ich mir selbst die Antwort.

    [EDIT] Sobald ich das eigentliche Parsen auch noch hinbekommen habe, poste ich es hier auch noch.

    • Bearbeitet WarFred Sonntag, 15. Juli 2018 19:29
    Sonntag, 15. Juli 2018 19:27
  • Hi,

    woher kommt deine XML-Datei? Wenn die Daten lediglich aus deinem Programm kommen, kann ich nicht verstehen, was du gegen Serialisierung hast. Ist auch meiner Meinung nach das einfachste.

    Wenn du es "händisch" machen möchtest, kannst du auch LinqToXml  (oder hier) nehmen, das finde ich persönlich ziemlich gut.

    Gruß


    Freiberufler im Bereich Softwareentwicklung Von der PLC und Robotik zu VB.NET & C#, vorrangig WPF und UWP

    Sonntag, 15. Juli 2018 20:17
  • Die Frage ist ganz einfach erklärt: weil ich null Ahnung von Serialization habe und mich da erst einarbeiten müsste (das VB-Buch, das ich mir extra gekauft habe, damit ich hin und wieder mal was nachschlagen kann, hat noch nicht einmal Serialisierung im Index!).

    Und dein Beispiel LinqToXml ist im Grunde genau das, was ich ja auch hinbekommen habe, allerdings in C# und nicht in VB und es löst ja noch nicht das Problem des "Durchparsens".

    [EDIT] Achso: ja, die XML-Datei ist von mir und dient mir als Datenspeicher. Sie ist ja nur ein ganz kleiner Teil von etlichen XML-Dateien, die ich für mein Programm benötige.
    • Bearbeitet WarFred Sonntag, 15. Juli 2018 20:51
    Sonntag, 15. Juli 2018 20:30
  • Am ende macht das aber nun mal viel mehr Arbeit als das De-Serialisieren, vor allem bei JSON. Wir wollen dir natürlich Mehrarbeit ersparen. Hier mal eine Demo mit JSON. Für die Demo brachst Du noch das Nuget Paket Newtonsoft.Json

    Imports System
    
    Module Program
        Sub Main(args As String())
    
            Dim list As List(Of Klassen) = New List(Of Klassen) From {
                New Klassen() With {
                    .Id = 1,
                    .Name = "Dieb",
                    .Attribute = New Attribute() With {
                        .Mut = "1W8+3",
                        .Klugheit = "1W6+8",
                        .Intuition = "1W8+7",
                        .Charisma = "1W8+5",
                        .Fingerfertigkeit = "1W8+9",
                        .Geschicklichkeit = "1W8+8",
                        .Konstitution = "2W4+4",
                        .Körperkraft = "1W10+5"
                    }
                },
                New Klassen() With {
                    .Id = 1,
                    .Name = "Händler",
                    .Attribute = New Attribute() With {
                        .Mut = "1W8+2",
                        .Klugheit = "1W8+8",
                        .Intuition = "1W10+7",
                        .Charisma = "1W10+5",
                        .Fingerfertigkeit = "1W6+6",
                        .Geschicklichkeit = "1W4+8",
                        .Konstitution = "2W4+4",
                        .Körperkraft = "1W8+6"
                    }
                }
            }
    
            'Objekt zu text
            Dim json = Newtonsoft.Json.JsonConvert.SerializeObject(list)
    
            'Text zu Objekt
            Dim list2 = Newtonsoft.Json.JsonConvert.DeserializeObject(Of List(Of Klassen))(json)
    
    
        End Sub
    
        Public Class Klassen
            Public Property Id As Integer
            Public Property Name As String
            Public Property Attribute As Attribute
        End Class
    
        Public Class Attribute
            Public Property Mut As String
            Public Property Klugheit As String
            Public Property Intuition As String
            Public Property Charisma As String
            Public Property Fingerfertigkeit As String
            Public Property Geschicklichkeit As String
            Public Property Konstitution As String
            Public Property Körperkraft As String
        End Class
    End Module

     Ein Json string unterscheidet sich etwas von XML, er sieht in diesem fall so aus

    [
     {
      "Id":1,
      "Name":"Dieb",
      "Attribute":              {
                   "Mut":"1W8+3",
                   "Klugheit":"1W6+8",
                   "Intuition":"1W8+7",
                   "Charisma":"1W8+5",
                   "Fingerfertigkeit":"1W8+9",
                   "Geschicklichkeit":"1W8+8",
                   "Konstitution":"2W4+4",
                   "Körperkraft":"1W10+5"
                  }
     },
     {
      "Id":1,
      "Name":"Händler",
      "Attribute":
                  {
                   "Mut":"1W8+2",
                   "Klugheit":"1W8+8",
                   "Intuition":"1W10+7",
                   "Charisma":"1W10+5",
                   "Fingerfertigkeit":"1W6+6",
                   "Geschicklichkeit":"1W4+8",
                   "Konstitution":"2W4+4",
                   "Körperkraft":"1W8+6"
                  }
     }
    ]


    Gruß Thomas
    13 Millionen Schweine landen jährlich im Müll
    Dev Apps von mir: UWP Segoe MDL2 Assets, UI Strings

    Sonntag, 15. Juli 2018 23:23
  • Hi Fred,
    in VB.NET gibt es eine sehr gute Unterstützung für XML. Es reicht, den XML-Stream (Datei o.ä.) in ein XElement einzulesen. Da wird im Hintergrund der Parser ausgeführt, der im XElement die Struktur der XML-Daten abgelegt. Den Umweg über XDocument brauchst Du nicht zu machen. Mit LinQ to XML kannst Du dann direkt auf die Knoten zugreifen. Diese Unterstützung ist in VB.NET viel eleganter als in C#.NET. Deine Methode Fuelle sieht nach der Umstellung auf XElement und LinQ so aus:

        Public Function Fuelle(id As Integer) As XElement
          Return (From xe1 In xe0.Descendants Where CType(xe1.@id, Integer) = id).FirstOrDefault
        End Function

    Deine Codeschnispel habe ich mal als Demo erstellt. Ich habe lediglich den Dateinamen geändert und zur Erzeugung des Pfades die Path-Klasse genutzt.

    Imports System.IO
    
    Public Class Form1
      Private WithEvents BtnStart As New Button With {.Text = "Start"}
      Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Me.Controls.AddRange(New Control() {BtnStart})
      End Sub
    
      Private Sub BtnStart_Click(sender As Object, e As EventArgs) Handles BtnStart.Click
        Dim Var_Klasse As XElement
        Dim Var_Test As New Test()
        Dim Var_Node As XElement
        Dim id = 3
        Var_Node = Var_Test.Fuelle(id)
        Var_Klasse = Var_Node
    
      End Sub
    
      Public Class Test
        Private xe0 As XElement
    
        Public Sub New()
          Dim Pfad As String = My.Application.Info.DirectoryPath
          xe0 = XElement.Load(Path.Combine(Pfad, "Form45XMLFile1.xml"))
        End Sub
    
        Public Function Fuelle(id As Integer) As XElement
          Return (From xe1 In xe0.Descendants Where CType(xe1.@id, Integer) = id).FirstOrDefault
        End Function
    
      End Class
    End Class


    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP)
    Meine Homepage mit Tipps und Tricks


    • Bearbeitet Peter Fleischer Montag, 16. Juli 2018 07:22
    • Als Antwort markiert WarFred Dienstag, 17. Juli 2018 09:00
    Montag, 16. Juli 2018 07:09
  • Also quasi: Var_Mut = Wert von <Mut> der Klasse mit der id=1

    Das wäre dann in etwa das hier:
    dim klasseidx = from klasse in klassenElement.Element("Klasse")
      where klassenElement.Attribute("id") == 1
    select klasse;

    - Gruß Florian

    Montag, 16. Juli 2018 07:16
  • Super Lösungen! Danke dafür!

    Jetzt besteht nur noch das "eigentliche" Problem, nämlich das XElement Node für Node zu parsen und Variablen zuzuweisen.

    @Thomas: danke für deinen Ansatz, ich werde ihn mir mal beizeiten ansehen. Er hat nur eine gravierende Schwachstelle: es ist nicht das, was ich machen möchte! Ich kenne das aus Foren, wo dann einfach gesagt wird "aber in Programmiersprache XY (<> der Programmiersprache in der man programmiert!) geht das aber viel einfacher!". Ja, das mag sein, aber wenn ich etwas lernen will - und das ist u.a. mein Anspruch an dieses Projekt, dann will ich es auch so machen, wie es von mir vorgesehen war. Die Ansätze von Peter und Florian zeigen, dass es zumindest möglich zu seien scheint. ;)

    Das soll jetzt keine Manöverkritik oder Überheblichkeit sein, ich möchte nur versuchen XML-Verarbeitung in VB.NET zu verstehen. JASON und Serialisierung kriegen vielleicht auch irgendwann mal ihre Zeit. ;)

    Gruß

    Michael

    Montag, 16. Juli 2018 08:06
  • Hi Michael,
    mit dem XElement ist ganz leicht, Knoten für Knoten zu verarbeiten. Wenn mit JSon gearbeitet wird, dann kann man direkt aus dem JSon eigene Objekte erstellen. Eine direkte Umwandlung in .NET-Objekte mit eigener Struktur ist aus dem XElement ist nicht so einfach möglich wie aus JSon. Die Syntax in VB.NET in LinQtoXML ist aber sehr elegant, was das problemlose Extrahieren von Untermengen ermöglicht (einfacher als in C#.NET). Aus diesem Grund ist es wichtig, ob im Projekt mit Objekten eigener Struktur (Klassen) oder nur mit Inhalten aus dem XML zu arbeiten ist. Auch ist wichtig, ob Änderungen der Werte dann in XML zurückzuschreiben sind. Wenn es wenige Klassen sind, dann kann sich der Aufwand lohnen, selbst etwas zu programmieren, z.B. so:

    Imports System.IO
    
    Public Class Form45
      Private WithEvents BtnStart As New Button With {.Text = "Start", .Dock = DockStyle.Top}
      Private lb As New ListBox With {.Dock = DockStyle.Fill}
      Private Sub Form45_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Me.Controls.AddRange(New Control() {lb, BtnStart})
      End Sub
    
      Private Sub BtnStart_Click(sender As Object, e As EventArgs) Handles BtnStart.Click
        Dim Var_Test As New Test()
        lb.DataSource = Var_Test.Fuelle
      End Sub
    
      Public Class Test
        Private xe0 As XElement
    
        Public Sub New()
          Dim Pfad As String = My.Application.Info.DirectoryPath
          xe0 = XElement.Load(Path.Combine(Pfad, "Form45XMLFile1.xml"))
        End Sub
    
        Public Function Fuelle() As List(Of Klasse)
          Return (From xe1 In xe0...<Klasse> Select New Klasse(xe1)).ToList
        End Function
    
      End Class
    
      Public Class Klasse
        Public Sub New(xe2 As XElement)
          Name = xe2...<Name>.Value
          Mut = xe2...<Attribute>.<Mut>.Value
          Klugheit = xe2...<Attribute>.<Klugheit>.Value
          ' usw.
        End Sub
        Public Property Name As String
        Public Property Mut As String
        Public Property Klugheit As String
        ' usw.
    
        ''' <summary>
        ''' Objekt als XML-String zurückgeben
        ''' </summary>
        ''' <returns></returns>
        Public Function SaveKlasse() As String
          Dim xe4 As New XElement("Klasse")
          xe4.Add(New XElement("Name") With {.Value = Name})
          Dim xe5 As New XElement("Attribute")
          xe4.Add(xe5)
          xe5.Add(New XElement("Mut") With {.Value = Mut})
          xe5.Add(New XElement("Klugheit") With {.Value = Klugheit})
          ' usw.
    
          Return xe4.ToString
        End Function
    
        ''' <summary>
        ''' Für Anzeige
        ''' </summary>
        ''' <returns></returns>
        Public Overrides Function ToString() As String
          Return $"Name: {Name}, Mut: {Mut}, Klugheit: {Klugheit}"
        End Function
      End Class
    
    End Class


    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP)
    Meine Homepage mit Tipps und Tricks

    • Als Antwort markiert WarFred Montag, 16. Juli 2018 08:39
    Montag, 16. Juli 2018 08:36
  • Perfekt (ich geh jetzt mal davon aus, dass das Ganze auch funktioniert, aber da bin ich sehr optimistisch! ;) ).

    Genau das, was ich suche.

    Danke Peter!

    Montag, 16. Juli 2018 08:39
  • Hi Michael,
    natürlich funktioniert mein Beispiel. Du kannst es selbst testen. Einfach den gesamten Code in den Codeteil eines leeren Windows Forms kopieren und Klassenname anpassen (aus Form45 z.B. Form1 machen), die XML-Datei mit ins Projekt nehmen (Eigenschaft Copy to Output: copy if newer) und Name der Datei im Code anpassen.


    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP)
    Meine Homepage mit Tipps und Tricks


    Montag, 16. Juli 2018 11:10
  • Ich hatte nicht dran gezweifelt! Und es klappt sehr gut, das war genau das, was mir (auch gedanklich) fehlte.
    Dienstag, 17. Juli 2018 08:59