LINQ to XML, wie Eintrag in XML-Datei finden

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 7 Antworten in diesem Thema. Der letzte Beitrag () ist von Ruzbacky.

    LINQ to XML, wie Eintrag in XML-Datei finden

    Hallo zusammen,

    ​ich bin noch relativ neu dabei mir das Programmieren mit VB.NET anzueignen.

    ​Ich habe ein kleines Programm bei dem ich verschiedene Benutzer in einer XML-Datei speichere.

    ​Dank dem @ErfinderDesRades und seinen guten Tutorials klappt das Speichern von Benutzern mit "DataSet only" auch hervorragend.

    ​Nun möchte per LINQ to XML einen Benutzer aus XML-Datei raussuchen und mir verschiedene Eigenschaften zu diesem Benutzer anzeigen lassen.
    ​Und genau hier habe ich auch mein Problem. Ich bekomme einfach nicht die Informationen die ich haben möchte.

    ​Hier ein Ausschnitt aus der XML:

    XML-Quellcode

    1. <?xml version="1.0" standalone="yes"?>
    2. <BenutzerDatenbank xmlns="http://tempuri.org/BenutzerDatenbank.xsd">
    3. <Benutzer>
    4. <ID>-1</ID>
    5. <Vorname>Gast</Vorname>
    6. <Nachname>Gast</Nachname>
    7. <AnmeldeName>Gast</AnmeldeName>
    8. <Passwort>Gast</Passwort>
    9. </Benutzer>
    10. <Benutzer>
    11. <ID>-2</ID>
    12. <Vorname>Max</Vorname>
    13. <Nachname>Mustermann</Nachname>
    14. <AnmeldeName>Max Mustermann</AnmeldeName>
    15. <Passwort>Musterpasswort</Passwort>
    16. </Benutzer>
    17. </BenutzerDatenbank>


    ​Und hier zwei Versuche Informationen zu dem Benutzer Gast zu bekommen mit LINQ to XML:

    VB.NET-Quellcode

    1. 'Gast in Benutzerdatenbank suchen
    2. Dim BenutzerDatenbankPfad As String = INI_ReadValueFromFile("AllgemeineEinstellungen", "BenutzerDatenbank", "", ConfigPfad) 'Speicherort der XML aus der Config.ini beziehen
    3. Dim XBenutzerDatenbank As XElement = XElement.Load(BenutzerDatenbankPfad)
    4. Dim GastAbfrage As IEnumerable(Of XElement) = From Gast In XBenutzerDatenbank.<Benutzer> 'Versuch 1
    5. ​Where Gast.<AnmeldeName>.Value = "Gast"
    6. Select Gast
    7. Dim GastAbfrage As IEnumerable(Of XElement) = From Gast In XBenutzerDatenbank.Elements("Benutzer") 'Versuch 2
    8. Where CStr(Gast.Element("AnmeldeName")) = "Gast"
    9. Select Gast
    10. Debug.Print(GastAbfrage.Count.ToString) 'Hier bekomme ich immer 0 :(
    11. For Each Gast As XElement In GastAbfrage 'Hier passiert natürlich auch nichts, da ich ja 0 habe
    12. Debug.Print(Gast.<ID>.ToString)
    13. Next


    ​Kann mir hier jemand vielleicht helfen?

    ​Danke schonmal.
    Dein XML-Namespace passt nicht. Importiere entweder deinen Namespace in VB oder entferne ihn aus der XML-Datei.

    Lösung 1:

    VB.NET-Quellcode

    1. Imports <xmlns="http://tempuri.org/BenutzerDatenbank.xsd">
    2. Module Module1
    3. Sub Main()
    4. Dim doc = XElement.Load("a.xml") ' Deine Datei
    5. Dim pws = From b In doc...<Benutzer> Where b.<Vorname>.Value = "Max" Select b.<Passwort>.Value
    6. End Sub
    7. End Module

    Lösung 2:

    XML-Quellcode

    1. <?xml version="1.0" standalone="yes"?>
    2. <BenutzerDatenbank> <!-- Kein xmlns -->
    3. ...
    4. </BenutzerDatenbank>

    Gruß
    hal2000
    Hi @hal2000,

    danke dir, genau das löst mein Problem. Ich habe den Namespace der XML nun Importiert und nun funktioniert es so wie ich es mir vorgestellt habe.

    @mox
    Von der XMLSerializer Klasse habe ich schonmal gehört/gelesen, leider habe ich mich mit dieser allerdings noch nicht auseinander gesetzt.
    Eine eigene Klasse für den Benutzer habe ich mir bereits erstellt. Von dieser erzeuge ich mir dann eine Instanz und weise dann den
    Properties die jeweiligen Werte aus der XML zu.
    Wenn ich dann zur Laufzeit Änderungen an einer Instanz meiner Benutzer Klasse vornehmen und diese speichern möchte, vollziehe ich
    das gesamte Prozedere nochmals rückwärts und schreibe die Properties aus der Benutzerklasseninstanz zurück in die XML.

    Wahrscheinlich ein umständlicher Weg?

    Gehe ich richtig in der Annahme das die XMLSerializer Klasse genau dies auf eine einfache Weise macht und mir aus den einzelnen
    Benutzern aus meiner XML die jeweilige Benutzerklasseninstanzen erzeugt?
    (De-)Serialisierung geht so:

    VB.NET-Quellcode

    1. Using fs As New FileStream(path, mode)
    2. Dim xs As New XmlSerializer(GetType(yourClass))
    3. xs.Serialize(fs, instance) ' speichern
    4. instance = DirectCast(xs.Deserialize(fs), yourClass) ' laden
    5. End Using

    Lass dabei aber die Namespaces weg - das macht alles nur kompliziert. Ein Schema kannst du auch ohne eigenen Namespace verwenden.
    Gruß
    hal2000
    Ich habe mir das ganze mal etwas angeschaut.

    Vielleicht sollte ich noch ergänzend etwas zum Drumherum sagen.

    Ich habe ein DataSet mit einer ParentTable in welcher die Benutzer erfasst werden und mehreren ChildTables in welchen
    verschiedene Informationen zu den Benutzern erfasst werden. Dieses DataSet speichere ich zur Laufzeit mit WriteXML in einer XML.
    Und lade es mir bei Bedarf wieder mittels ReadXML in ein DataGridView.

    Nun musste ich feststellen, dass wenn ich den Namespace aus der XML weglasse ich die XML nicht mehr im DGV anzeigen lassen kann.
    LINQ to XML funktioniert allerdings wie oben von dir erwähnt auch ohne Namespace.

    Vielleicht kann hier noch jemand etwas Aufklärungsarbeit bei mir leisten.
    Ich beschäftige mich derweil auch noch etwas mit der Thematik und schaue was ich selbst rausfinden kann.
    Read- und WriteXML verwenden einen XmlTextWriter zum Erzeugen der XML-Darstellung. Dabei wird auch der Namespace geschrieben, sofern er nicht leer ist. Setze testweise die Namespace-Property deines DataSets auf String.Empty - dann sollte der Namespace weg sein. Falls nicht: Never change a running system :)
    Gruß
    hal2000
    Ah ok, jetzt schließt sich der Kreis langsam :)

    ​Eigentlich alles recht einleuchtend, wenn man es erstmal halbwegs verstanden hat.
    ​Und wie du sagst "Never change a running system", werde ich den Namespace in der XML beibehalten, da ich mit diesem nun gut klarkomme
    ​und ich mir so die Option offen halte eventuell einen zweiten Namespace in der XML zu schaffen.
    ​Weis zwar noch wofür ich das in meinem Fall brauchen könnte, aber man weis ja nie ;)

    ​Läuft auf jeden Fall dank eurer Hilfe nun alles genau so wie es soll, danke dafür.