XML einlesen und mit DataGridview vergleichen

  • VB.NET
  • .NET (FX) 4.0

Es gibt 52 Antworten in diesem Thema. Der letzte Beitrag () ist von ErfinderDesRades.

    XML einlesen und mit DataGridview vergleichen

    Hallo,

    ich habe im Verzeichnis der *.exe eine config.xml. Ist in etwas so aufgebaut:

    XML-Quellcode

    1. <Person>
    2. <Klaus>
    3. <alter>40</alter>
    4. <tel>2345</tel>
    5. </Klaus>
    6. <Heinz>
    7. <alter>41</alter>
    8. <tel>121212</tel>
    9. </Heinz>
    10. </Person>


    Nun möchte ich die XML einlesen und mit einer Tabelle (DataGridview) vergleichen. Bei übereinstimmung sollen
    Zellen ausgeüllt werden.


    VB.NET-Quellcode

    1. Dim reader As System.Xml.XmlTextReader = New System.Xml.XmlTextReader("config.xml")
    2. For i = 0 To DataGridView1.RowCount
    3. If DataGridView1.Item(0, i).Value = XML-KNOTEN-KLAUS then
    4. DataGridView1.Item(1, i).Value = XML-KNOTEN-KLAUS.alter
    5. DataGridView1.Item(2, i).Value = XML-KNOTEN-KLAUS.tel
    6. End if
    7. Next

    Passenden Code kenne ich leider nicht, daher nur ein XML-KNOTEN-KLAUS

    Wenn jemand etwas Hilfestellung leistet, wäre ich dankbar.

    Gruß


    Edit:
    Evtl ist es so besser die XML aufzubauen?

    XML-Quellcode

    1. <Person>
    2. <item>
    3. <name>Klaus</name>
    4. <alter>40</alter>
    5. <tel>2345</tel>
    6. </item>
    7. <item>
    8. <name>Heinz</name>
    9. <alter>41</alter>
    10. <tel>121212</tel>
    11. </item>
    12. </Person>

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „noxx2“ ()

    ok, danke. Aber wie bekomme ich so eine XML mit dem Inhalt einer DataGridview-Zelle verglichen?
    Finde keinen Ansatz und google hat mich auch nicht in die Richtung geführt.

    Nur ein

    VB.NET-Quellcode

    1. Dim xdoc As XDocument = XDocument.Load("config.xml")

    anstatt

    VB.NET-Quellcode

    1. Dim reader As System.Xml.XmlTextReader = New System.Xml.XmlTextReader("config.xml")
    naja - willst du nicht lieber lernen, wie man ein DGV an ein typisiertes Dataset bindet?
    Dann kannst du das Dataset die Xml schreiben lassen, und vermeidest so jede Menge Fußangeln.
    Und ein typDataset bietet auch jede Menge Möglichkeiten zur strukturierten Suche.

    Xml ist eiglich Low-Level, mit dem man sich eiglich nicht abzugeben braucht.
    guggemol Daten laden und speichern

    Wenn du aber weiter drauf bestehst, in Xml zu wühlen, guggemol Xml verarbeiten mit Intellisense (Schema und XDocument)

    Aber das ist ja nur die halbe Miete, die andere Hälfte ist das herumwühlen im DatagridView. Und davon sowas halte ich ja gar nicht viel.

    Je nachdem, was du eigentlich machen willst, kann es ganz einfach seinj - man muss nur den Kopf von diesen blöden Controls wegkriegen, und das Datenmodell in den Blick nehmen: Da kannst du auch mehrere typDatasetse miteinander vergleichen, und mw. auch Übereinstimmungen dann in einem DGV markieren.

    Ich wüsste zwar nicht, warum man Konfigurations-Dateien miteinander vergleichen will, ...
    ​Je nachdem, was du eigentlich machen willst


    Im Moment liest mein Mini-Tool eine CSV ein und gibt die Werte ein einer DGV aus (Spalte 1-4)
    Nun soll die CSV auf Knopfdruck mit einer XML verglichen werden, wenns eine Übereinstimmung
    gibt, dann soll in Spalte 5 ein Wert eingetragen werden.

    CSV einlesen und Ausgabe in DGV klappt. Das einlesen der XML über xdoc = XDocument.Load(PFAD)
    anscheinend auch.

    Aber dann ist Ende und komme auch nicht weiter. Würde gerne ungern das ganze Prg umbauen...

    Gruß
    ich würd aber grad zum Umbau raten - da kannste eine Menge neuer nützlicher Dinge lernen, und evtl. biste sogar schneller fertig.

    ZB liesse sich die csv ebensogut in ein typisiertes Dataset einlesen.
    Wenn dann deine Xml einfach das Xml ist, was ein sich speicherndes typDataset schreibt, dann wären damit die beiden Formate doch schon kompatibel.

    Und wer will kann natürlich noch ein DGV dran anbinden.

    Ich stosse immer wieder darauf, dass Daten eingelesen werden, und ist gar kein Datenmodell da, wohinein sie eingelesen werden. Die landen dann in iwelchen DatagridViews, Textboxen, Comboboxen, und jedes Weiterverarbeiten stellt die Autoren vor unlösbare Aufgaben.
    ok, dann muss ich mir zeit nehmen, die ich heute leider nicht habe.

    wenn du sagst, anderes gehts nicht und ich muss alles nochmal umbauen,
    dann muss ich ggf das einlesen und vegleichen der XML wieder rauswerfen,
    oder statt XML besser CSV verwenden.

    gruß und danke
    Das wäre nett, danke. Ich halte es mal klein. Wenn ich eine Lösung
    für dieses kleine Beispiel hätte, bekomme ich das schon hin auf mein
    Tool anzupassen.

    Das DGV ist gefüllt, anbei eine Beispiel der ersten Zeile.
    Ingesamt hat das DGV 5 Spalten:

    Quellcode

    1. DataGridView1.Item(0, 0) = Hans
    2. DataGridView1.Item(0, 1) = Albers
    3. DataGridView1.Item(0, 2) = Baumstrasse
    4. DataGridView1.Item(0, 3) = 1
    5. DataGridView1.Item(0, 4) =


    Beispiel XML:

    XML-Quellcode

    1. <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    2. <personen>
    3. <person>
    4. <name>Hans</name>
    5. <tel>089-12345</tel>
    6. </person>
    7. <person>
    8. <name>Klaus</name>
    9. <tel>089-55555</tel>
    10. </person>
    11. </personen>


    Wenn die XML eingelesen wird, soll <name> in Spalte 1 gesucht werden und wenn
    gefunden, dann die entsprechende <tel> in Spalte 5 eingetragen werden.

    Gruß
    ok, hier der Code zum einlesen der Werte in DataGridView1

    VB.NET-Quellcode

    1. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btn_import.Click
    2. If System.IO.File.Exists("c:\temp\personen.txt") Then
    3. Dim lines() As String = Nothing
    4. DataGridView1.Rows.Clear()
    5. Me.Cursor = Cursors.AppStarting
    6. Try
    7. lines = IO.File.ReadAllLines("c:\temp\personen.txt")
    8. Catch ex As Exception
    9. Me.Cursor = Cursors.Default
    10. Exit Sub
    11. End Try
    12. Dim Menge As Integer = lines.GetLength(Menge) - 1 ' Anzahl der Zeilen ermitteln
    13. For i = 0 To Menge
    14. Dim Eintrag As String = lines(i)
    15. Dim parts() As String = Split(Eintrag, ",")
    16. Dim RowCount As Integer = DataGridView1.RowCount - 1
    17. DataGridView1.Rows.Add()
    18. DataGridView1.BeginEdit(CBool(RowCount))
    19. Dim SplittCount As Integer = parts.Length - 1 ' Anzahl der Einträge in Splitt
    20. If SplittCount >= 0 Then
    21. For g = 0 To SplittCount
    22. DataGridView1.Rows(RowCount).Cells(g).Value = parts(g)
    23. Next g
    24. End If
    25. Next i
    26. DataGridView1.Update()
    27. DataGridView1.EndEdit()
    28. Me.Cursor = Cursors.Default
    29. End If
    30. End Sub


    und im Anhang Beispiel XML und TXT
    Dateien
    • config.xml

      (257 Byte, 213 mal heruntergeladen, zuletzt: )
    • personen.csv.txt

      (114 Byte, 131 mal heruntergeladen, zuletzt: )
    Eine Frage zu deinem Code:
    Wozu dient die ContactDts.xml

    Eine Frage zu meinem Code:
    (auch wenn nicht perfekt)

    Wie hätte der Code aussehen müssen, damit er funktioniert?

    VB.NET-Quellcode

    1. Dim XmlDoc As XDocument = XDocument.Load("c:\temp\config.xml")
    2. For i = 0 To DataGridView1.RowCount
    3. If DataGridView1(0, i).Value = XmlDoc.<personen>.<person>.<name>.Value Then
    4. DataGridView1(4, i).Value = XmlDoc.<personen>.<person>.<tel>.Value
    5. End If
    6. Next

    noxx2 schrieb:

    Eine Frage zu deinem Code:
    Wozu dient die ContactDts.xml


    VB.NET-Quellcode

    1. Private _Csv As New FileInfo("..\..\personen.csv")
    2. Private _Xml As New FileInfo("..\..\config.xml")
    3. Private _Dataset As New FileInfo("..\..\ContactDts.xml")
    4. Private Sub AnyButton_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btLoadCsv.Click, btReadConfig.Click, btSaveDataset.Click, btLoadDataset.Click
    5. Select Case True
    6. Case sender Is btLoadDataset
    7. ContactDts.Clear()
    8. ContactDts.ReadXml(_Dataset.FullName)
    9. Case sender Is btLoadCsv : LoadCsv()
    10. Case sender Is btReadConfig : LoadConfig()
    11. Case sender Is btSaveDataset : ContactDts.WriteXml(_Dataset.FullName)
    12. End Select
    13. System.Media.SystemSounds.Asterisk.Play()
    14. End Sub
    gugge zeilen #3, #15: in ContactDts.xml wird das Dataset abgespeichert.
    Also aus personen.csv kann man was importieren, aus config.xml etwas hinzufügen, und in ContactDts.xml wird das zusammengefügte persistiert (also man kanns natürlich ebensogut auch wieder einlesen (#9)



    Wie das als Xml-Query zu formulieren wäre, weiss ich nicht im Einzelnen. Ich mag Xml-Queries nicht, weil man normalerweise keine Intellisense-Unterstützung hat - es sei denn, man treibt einen erheblichen Aufwand.

    Vor allem proggst du Strict Off, weißt also garnicht, welche Datentypen du in welcher Variable wirklich hast, was du mit was anderem vergleichst und solche Sachen.
    So kann man eh nicht gscheit coden.

    Oder wüsstest du, welchen Datentyp der Ausdruck XmlDoc.<personen>.<person>.<name>.Value ergibt?

    Aber auch strukturell haut die schleife vorn und hinten nicht hin, denn für deinen Abgleich musst du ja jeden Eintrag aus dem einen Datenbestand mit jedem anderen aus dem anderen Datenbestand abgleichen.
    Mit soner einfachen For-Schleife ist das nicht getan.



    Ich habe dafür eine Linq-Query bemüht - inne Datenbänkerei sind derlei "jeder-gegen-jeden-Abgleiche" als Joins bekannt:

    VB.NET-Quellcode

    1. Dim matches = From ctx In ContactDts.Contact Join cfg In dtsConfig.Contact On cfg.Firstname Equals ctx.Firstname
    Das ist eiglich idiotensicherer selbsterklärender Code:
    Aus dem einen Dataset die Contact-Tabelle wird mit der Contact-Tabelle des anderen Datasets gejoint:
    From ctx In ContactDts.Contact Join cfg In dtsConfig.Contact
    Und als TrefferKriterium gilt, ob die Firstname-Werte übereinstimmen:
    On cfg.Firstname Equals ctx.Firstname
    Iwie logisch oder?

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „ErfinderDesRades“ ()

    Klingt alles logisch. Aber versuche gerade das ganze anzupassen, aber
    es es kracht ständig.
    dafür bin ich vermutlich auch nicht tief genug drin, um alles zu verstehen
    was du da reingemacht hast.

    Gruß


    Edit:

    Nachdem ich versuche alles anzupassen, habe ich mal die Einträge Contact in Item geändert,
    sowohl in der XML, als auch im Code sowie in der ContactDts.xsd.

    Nun schmeißt mir VB einen Fehler aus:

    Warnung 1 Die DataMember-Eigenschaft Contact kann in der DataSource nicht gefunden werden. C:\...\frmAddressCompleter.Designer.vb 193 0



    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „noxx2“ ()

    Ja, jedes Form hat eine Designer-Datei, mit Code drin, den der Designer schreibt. Also was du im Form-Designer designest, das scripted der quasi im Hintergrund zu Vb.net-Code, der dann zur Laufzeit deine Oberfläche instand setzt.
    ...

    Und in dem Designer-Code dort sind die Bindings definiert, unter Benutzung von String-Schlüsseln, also eiglich ziemlich miserabler Code, deshalb lässt man es ja den Designer machen.
    Wenn du dann aber im Nachhinein an den Entitäten herumpfuschst, dann musst du immer auch drauf achten, ob was du da werkelst, nicht auch Designer-Code affektiert.
    Das betrifft insbesondere Löschungen von Spalten und Änderungen von Spalten-Namen.

    Was ich immer sehr empfehle ist: viele Backups. Dazu empfehle ich ein Tool von mir, das kann Backups mit 1 Klick zurecht-zippen: SolutionExplorer - OpenSource
    Es lohnt sich die Mühe, das einzurichten, am Backup-Problem kommt keiner vorbei.
    danke für die Erklärung. Backup werde ich dran denken :)

    Noch was:
    in der config xml steht
    xmlns="http://tempuri.org/ContactDts.xsd

    was ist das für eine URL?`wenn ich die ändere, wird nichts
    mehr eingelesen, warum?
    xmlns="http://tempuri.org/BeispielDts.xsd

    Gruß