xml Abfrage per xml Linq

  • VB.NET

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

    xml Abfrage per xml Linq

    Hallo zusammen,

    ich habe ein kleines Problem mit dem Auslesen einer xml Datei und stehe irgendwie auf dem Schlauch.
    Das ist meine kleine xml Datei.

    XML-Quellcode

    1. <?xml version="1.0" encoding="iso-8859-15"?>
    2. <Projekte>
    3. <xmlfilename>Projekte.xml</xmlfilename>
    4. <Projekt>
    5. <ProjektNr>PJ201302001</ProjektNr>
    6. <Thema>Online</Thema>
    7. <Mitarbeiter>
    8. <Eintrag MANummer="01">Herr Müller</Eintrag>
    9. <Eintrag MANummer="02">Herr Meier</Eintrag>
    10. </Mitarbeiter>
    11. <Taetigkeiten>
    12. <Eintrag kstart="01">Consulting</Eintrag>
    13. <Eintrag kstart="02">Vertrieb</Eintrag>
    14. <Eintrag kstart="CO">Consulting Prio</Eintrag>
    15. </Taetigkeiten>
    16. </Projekt>
    17. <Projekt>
    18. <ProjektNr>PJ201302002</ProjektNr>
    19. <Thema>CRMSol Offline</Thema>
    20. <Mitarbeiter>
    21. <Eintrag MANummer="01">Herr Müller</Eintrag>
    22. <Eintrag MANummer="02">Herr Meier</Eintrag>
    23. <Eintrag MANummer="03">Frau Müller</Eintrag>
    24. </Mitarbeiter>
    25. <Taetigkeiten>
    26. <Eintrag kstart="01">Consulting</Eintrag>
    27. <Eintrag kstart="02">Vertrieb</Eintrag>
    28. <Eintrag kstart="CO">Consulting Prio</Eintrag>
    29. </Taetigkeiten>
    30. </Projekt>
    31. </Projekte>



    Ich habe nun eine eigene Parse Funktion geschrieben, die mir die xml Daten in eigene Klassenobjekte schreibt.

    VB.NET-Quellcode

    1. Public Class xmlWorkProjekte
    2. Private Const bereich As String = "Projekte"
    3. Public Shared Function Parse(doc As XDocument) As Projekte
    4. Dim pj As New Projekte
    5. pj.xmlfilename = doc.<Projekte>.<xmlfilename>.Value
    6. pj.Projekt = (From x In doc.<Projekte>.Elements
    7. Select New Projekt With {.Adresse = x.<Adresse>.Value,
    8. .Kto = x.<Kto>.Value,
    9. .Mandant = x.<Mandant>.Value,
    10. .ProjektNr = x.<ProjektNr>.Value,
    11. .Empfangen = x.<ProjektNr>.Value,
    12. .Gesendet = x.<ProjektNr>.Value,
    13. .Thema = x.<Thema>.Value,
    14. .Taetigkeiten = (From y In doc.<Projekte>.<Projekt>.<Taetigkeiten>.Elements
    15. Select New Taetigkeit With {.kstart = y.Attributes.First.Value,
    16. .Value = y.Value}).ToList,
    17. .Mitarbeiter = (From z In doc.<Projekte>.<Projekt>.<Mitarbeiter>.Elements
    18. Select New Mitarbeiter With {.MANummer = z.Attributes.First.Value,
    19. .Value = z.Value}).ToList}).ToList
    20. Return pj
    21. End FunctionEnd Class




    Problem ist nun, dass bei Tätigkeiten und Mitarbeiter immer alle Eigenschaften in meine Liste geschrieben wird.
    Ich möchte aber dass zu dem Projekt PJ201302001 auch nur die Mitarbeiter in der Liste stehen die in dem Projektknoten mit der ProjektNr PJ201302001 enthalten sind.
    Bei dem PJ201302002 natürlich die die da drin sind.

    Wahrscheinlich sehe ich den Wald vor lauter Bäumen nicht mehr :(

    Vielen Dank für die Hilfe.
    Ja das stimmt schon, mit der habe ich ja mein kleines Problem.

    VB.NET-Quellcode

    1. .Taetigkeiten = (From y In doc.<Projekte>.<Projekt>.<Taetigkeiten>.Elements
    2. Select New Taetigkeit With {.kstart = y.Attributes.First.Value,
    3. .Value = y.Value}).ToList,


    Wenn ich da ein Where anfüge, müsste das ja so aussehen

    VB.NET-Quellcode

    1. y.???????? = ???????


    Ich habe auf der Ebene von y aber die Eigenschaft ProjektNr nicht so dass ich auf diese Filtern könnte.
    Xml ist keine gute Basis, um ein Datenmodell daraus zu bauen.
    lern Datenmodellierung und mach das Zeug im typisierten Dataset.
    die relationale GrundIdee
    Du bist auch garnet weit weg von relationaler Modellierung, das sieht man an deim Xml, wo scheinbar jeder Datensatz eine Identifikations-Nummer hat.

    Wenn mans als Xml abspeichert siehts übrigens fast genauso aus, nur dasses halt richtig organisiert ist, was mir bei deim Xml zweifelhaft ist.
    DB-Programmierung ohne Datenbank

    Ein typ Dataset mit Linq abzufragen ist vielfach komfortabler als diese Xml-Sosse.
    kann man mit den Xml-Erstellern reden?
    Weil was die da generieren ist grauselig. Nämlich der Tag <Eintrag> taucht sowohl als SubElement von <Mitarbeiter> als auch als SubElement von <Taetigkeit> auf, und das gehört sich überhaupt nicht.

    (oder das ist wieder son Sch... - Beispiel, was inne Realität garnet vorkommt) :cursing:
    Ne das ist leider live und real.
    Hast du einen Tipp wie man die umgestalten kann, so dass man damit anständig arbeiten kann?

    Das eine hab ich schon notiert, dass "Eintrag" nicht doppelt vorkommen darf.

    Ich hab mir auch mal dein Phonebook Beispiel geladen und schaue mir da an wie das mit den xml Daten ein Datenset aufbaut.
    Denn so wie du bestimmt schon vermutet hast, müssen die xml Daten als DataSource für DataGridViews herhalten ;(
    also entweder ich kapier nicht, was das soll, oder das Xml ist einfach Schrott.
    Was soll das denn eiglich aussagen?
    soll das Mitarbeiter und Tätigkeiten zu Projekten zuordnen?

    Wieso sind die Tätigkeiten nicht sowohl Projekt als auch Mitarbeiter zugeordnet?

    Das ergibt doch keinen Sinn, dass einem Projekt 3 Mitarbeiter zugeordnet sind, und auch 3 Tätigkeiten, aber nicht geklärt ist, wer für was zuständig ist.



    egal
    jedenfalls ein bischen kriegst du so raus:

    VB.NET-Quellcode

    1. Dim XDoc As XDocument = <?xml version="1.0" encoding="iso-8859-15"?>
    2. <Projekte>
    3. <xmlfilename>Projekte.xml</xmlfilename>
    4. <Projekt>
    5. <ProjektNr>PJ201302001</ProjektNr>
    6. <Thema>Online</Thema>
    7. <Mitarbeiter>
    8. <Eintrag MANummer="01">Herr Müller</Eintrag>
    9. <Eintrag MANummer="02">Herr Meier</Eintrag>
    10. </Mitarbeiter>
    11. <Taetigkeiten>
    12. <Eintrag kstart="01">Consulting</Eintrag>
    13. <Eintrag kstart="02">Vertrieb</Eintrag>
    14. <Eintrag kstart="CO">Consulting Prio</Eintrag>
    15. </Taetigkeiten>
    16. </Projekt>
    17. <Projekt>
    18. <ProjektNr>PJ201302002</ProjektNr>
    19. <Thema>CRMSol Offline</Thema>
    20. <Mitarbeiter>
    21. <Eintrag MANummer="01">Herr Müller</Eintrag>
    22. <Eintrag MANummer="02">Herr Meier</Eintrag>
    23. <Eintrag MANummer="03">Frau Müller</Eintrag>
    24. </Mitarbeiter>
    25. <Taetigkeiten>
    26. <Eintrag kstart="01">Consulting</Eintrag>
    27. <Eintrag kstart="02">Vertrieb</Eintrag>
    28. <Eintrag kstart="CO">Consulting Prio</Eintrag>
    29. </Taetigkeiten>
    30. </Projekt>
    31. </Projekte>
    32. Private Sub LinqXmlTryals()
    33. For Each project In XDoc...<Projekt>
    34. MessageBox.Show(project.<ProjektNr>.Value)
    35. For Each ma In project.<Mitarbeiter>.<Eintrag>
    36. MessageBox.Show(ma.Value)
    37. Next
    38. For Each taet In project.<Taetigkeiten>.<Eintrag>
    39. MessageBox.Show(taet.Value)
    40. Next
    41. Next
    42. End
    43. End Sub
    Das ist zwar kein Linq, aber zumindest stimmen schoma die Zugriffe
    Das wird dann eine Zeiterfassung.

    Auf das Projekt können nur für die Mitarbeiter Zeiten erfasst werden, die dem Projekt zugeordnet sind. Daher einmal 2 und einmal 3 Mitarbeiter.
    Bei den Tätigkeiten verhält es sich auch so, dass diese an das Projekt gekoppelt sind und nicht an den Mitarbeiter (ich weiss etwas unlogisch aber da hab ich keinen Einfluss drauf :( )

    Das heisst in der ersten Maske habe ich alle Projekte mit Projektnummer und Thema (Anzeige in einem DataGridView)
    Doppelklick darauf öffnet ein neues Formular mit einem DataGridView für Zeiten und da gibts dann natürlich ComboBoxen die mit den Mitarbeitern gefüllt werden.
    Hieraus wird dann eine Neue Datei erzeugt (Nur Projekt mit Von/Bis Zeit, Datum, MA und Tätigkeit).
    Das spannende ist, es funktioniert auch alles, abgesehen davon, dass in dem ZeitGridView immer alle MA Einträge (also 5) in den Comboboxen vorhanden waren. 8-)

    Das Ganze findet dann mit einem Up- und Download statt, damit man Offline erfassen kann. Die Daten werden dann wieder in ein anderes System importiert :)

    Das ganze so als Hintergrundinfo um den ganzen schnodder ein wenig zu umreisen
    Jo. Mach ein ordentliches Datenmodell mit einem typDataset, und schreib Konverter zu diesem Schrott-Format. So hast du den Schaden eingekapselt wie eine Zyste, und der Eiter verbreitet sich nicht in deiner Anwendung.

    Deiner Anwendung kannste basierend auf dem Datenmodell eine saubere, datenbindung-getriebene Oberfläche spendieren.
    Code keine komplizierte Projekt-Klasse. Diese Verhältnisse musst du im Dataset abbilden, denn es treten da auch m:n-Relationen auf, die du mit OOP-Klassen nicht bewältigen kannst. die relationale GrundIdee

    Frag auch mal nach, ob die die Tätigkeiten nicht mit ordentlichen Zuständigkeiten versehen wollen. Wenn sie das überzeugt, hast du mit einer guten Idee geglänzt, und wenn nicht, dann hast du die Wahrscheinlichkeit gesenkt, dass sie iwann von selbst auf die Idee kommen, und dann mit genau dieser zusätzlichen Anforderung ankommen werden.