Elegantere Lösung zum Einlesen XML Dateien

  • VB.NET

Es gibt 15 Antworten in diesem Thema. Der letzte Beitrag () ist von ryg.

    Elegantere Lösung zum Einlesen XML Dateien

    Hallo Paradise,

    ihr werdet es alle irgendwie kennen, das man die ganze Zeit ohne Probleme herum Coded, dann aber irgendwann an ein eigentlich total Simples Problem kommt, und euer Hirn einfach dicht macht.
    So auch grad bei mir... Normalerweise fällt mir die lösung beim Aufstehen oder auf'm Pott ein. Diesmla leider nicht... Und ich bin schon einige Tage dran... xD

    Folgendermaßen sieht es aus:
    Ich bekomme von einer Firefox Extension per XML Daten an einen Port gesendet. Dies funktioniert auch alles Tadellos. Ich kann die Daten lesen, und die Informationen dazu auch in Strukturen speichern. Alles nicht das Ding. Zur veranschaulichung einmal einer dieser XML Datensätze:

    XML-Quellcode

    1. <?xml version="1.0" encoding="UTF-8"?>
    2. <planetinfos xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="planetinfo.xsd">
    3. <header version="2.6" universe="Jupiter" debug="true" language="german" content_type="planetinfo"/>
    4. <planetinfo playername="xxx" playerid="111111" planetname="Atom" moon="false" galaxy="1" system="2" planet="3">
    5. <entry name="Metal" amount="46026"/>
    6. <entry name="Crystal" amount="46006"/>
    7. <entry name="Deuterium" amount="24340"/>
    8. <entry name="Energy" amount="2495"/>
    9. <entry name="Metal Mine" amount="16"/>
    10. <entry name="Crystal Mine" amount="15"/>
    11. <entry name="Deuterium Synthesizer" amount="10"/>
    12. <entry name="Solar Plant" amount="18"/>
    13. <entry name="Fusion Reactor" amount="7"/>
    14. <entry name="Solar Satellite" amount="0"/>
    15. <entry name="Metal Storage" amount="4"/>
    16. <entry name="Crystal Storage" amount="3"/>
    17. <entry name="Deuterium Tank" amount="2"/>
    18. </planetinfo>
    19. </planetinfos>



    An sich ist das Auslesen an dieser Stelle kein Problem. Habe ich ja soweit auch schon vorliegen. Das Problem ist hier, das ich per Endlosschliefe alle entry Nodes durchgehen muss, da abgesehen von dem "Solar Sattelite" Eintrag keine Einträge erstellt werden die eine "amount" von 0 haben.

    Im moment mache ich das ganze auf folgendem Weg:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.Xml
    2. Imports System.Xml.Serialization
    3. Imports System.IO
    4. Imports ogTypes
    5. Public Class clsParseXML
    6. Private ParseType As New ogTypeParsePlanetinfo
    7. Private GTStrings() As String
    8. Private sPageType As String
    9. 'Seitentypen der PlanetInfo XML Seite der GT-Extension
    10. 'ress, faci, rese, fleet, def
    11. Private sPlanetInfoPage As String
    12. ' Öffentliche Klassenvariablen, Ändern des Pfades nach der Instanziierung möglich
    13. Public XMLData As String
    14. Sub New(ByVal Data As String)
    15. XMLData = Data
    16. ' hier nehme ich in der ersten Zeile 2 aufeinanderfolgende Leerzeichen weg
    17. ' das wird hier nur einmal ausgeführt.
    18. 'XMLData = Replace(XMLData, " ", "", 1, 1)
    19. 'Ich habe das hier ein wenig Umgeschrieben, da es (so wie ich das in einem Testfall mitbekommen habe)
    20. 'auch mal sein kann, das nicht nur 2 Stellen sondern auch mal nur eine oder 3 auftreten können.^^
    21. 'Und diese Lösung ist für all diese Fälle geeignet =D
    22. XMLData = "<" & SplitString(XMLData, "<", 2)
    23. End Sub
    24. ''' <summary>
    25. ''' Kategorisiert die einzelnen Planetinfo Daten und fügt diese in ein Parse-Struct
    26. ''' </summary>
    27. ''' <remarks>09.04.2011 - ryg</remarks>
    28. Sub ParseXML_PlanetInfo()
    29. Dim xmlDoc As New XmlDocument
    30. Dim ParseNodes As XmlNodeList
    31. Dim ParseNode As XmlNode
    32. Dim rawData As String
    33. rawData = XMLData
    34. xmlDoc.LoadXml(rawData)
    35. ParseNodes = xmlDoc.GetElementsByTagName("header")
    36. For Each ParseNode In ParseNodes
    37. ParseType.Uni = ParseNode.Attributes("universe").Value
    38. Next
    39. If Not ParseType.Uni = ogProfile.Uni.UniName Then
    40. ' An dieser Stelle sollte zusätzlich geprüft werden, ob ein Profil für die Daten vorhanden ist.
    41. '
    42. '
    43. '
    44. MsgBox(getLngTxt("XMLParse", "WrongUni"), MsgBoxStyle.Critical)
    45. Exit Sub
    46. End If
    47. ParseNodes = Nothing
    48. ParseNodes = xmlDoc.GetElementsByTagName("planetinfo")
    49. For Each ParseNode In ParseNodes
    50. 'Spielername auslesen
    51. ParseType.OwnerName = ParseNode.Attributes("playername").Value
    52. 'Planetenname auslesen
    53. ParseType.Planet.Planet.Name = ParseNode.Attributes("planetname").Value
    54. 'Koordinaten des Planeten auslesen
    55. ParseType.Planet.Koords.Galaxie = ParseNode.Attributes("galaxy").Value
    56. ParseType.Planet.Koords.System = ParseNode.Attributes("system").Value
    57. ParseType.Planet.Koords.Number = ParseNode.Attributes("planet").Value
    58. 'Hier wird geprüft ob es sich hierbei um einen Planeten oder Mond handelt
    59. If CBool(ParseNode.Attributes("moon").Value) = False Then
    60. ParseType.Planet.Planet.Name = ParseNode.Attributes("planetname").Value
    61. Else
    62. ParseType.Planet.Moon.Name = ParseNode.Attributes("planetname").Value
    63. End If
    64. Next
    65. ParseNodes = Nothing
    66. ParseNodes = xmlDoc.GetElementsByTagName("officer")
    67. sPlanetInfoPage = ""
    68. For Each ParseNode In ParseNodes
    69. Try
    70. If Not ParseNode.Attributes("name").Value = vbNullString Then
    71. ParseXML_Overview()
    72. Exit Sub
    73. End If
    74. Catch ex As Exception
    75. End Try
    76. Next
    77. ParseNodes = Nothing
    78. ParseNodes = xmlDoc.GetElementsByTagName("entry")
    79. sPlanetInfoPage = ""
    80. For Each ParseNode In ParseNodes
    81. '#####################################################
    82. 'Ermitteln der Ressourcen
    83. 'Energie wäre zwar auch möglich macht aber keinen Sinn, da wir das lieber mit hilfe der
    84. 'Gebäude und Forschungen errechnen =D
    85. If ParseNode.Attributes("name").Value = "Metal" Then
    86. ParseType.Planet.Planet.Supplies.Metal = ParseNode.Attributes("amount").Value
    87. End If
    88. If ParseNode.Attributes("name").Value = "Crystal" Then
    89. ParseType.Planet.Planet.Supplies.Crystal = ParseNode.Attributes("amount").Value
    90. End If
    91. If ParseNode.Attributes("name").Value = "Deuterium" Then
    92. ParseType.Planet.Planet.Supplies.Deuterium = ParseNode.Attributes("amount").Value
    93. End If
    94. '#####################################################
    95. 'Ermitteln der Gebäude (Ressourcen)
    96. If ParseNode.Attributes("name").Value = "Metal Mine" Then
    97. ParseType.Planet.Planet.Resources.MetalMine = ParseNode.Attributes("amount").Value
    98. sPlanetInfoPage = "ress"
    99. End If
    100. If ParseNode.Attributes("name").Value = "Crystal Mine" Then
    101. ParseType.Planet.Planet.Resources.CrystalMine = ParseNode.Attributes("amount").Value
    102. sPlanetInfoPage = "ress"
    103. End If
    104. If ParseNode.Attributes("name").Value = "Deuterium Synthesizer" Then
    105. ParseType.Planet.Planet.Resources.DeuteriumSynthesizer = ParseNode.Attributes("amount").Value
    106. sPlanetInfoPage = "ress"
    107. End If
    108. If ParseNode.Attributes("name").Value = "Solar Plant" Then
    109. ParseType.Planet.Planet.Resources.SolarPlant = ParseNode.Attributes("amount").Value
    110. sPlanetInfoPage = "ress"
    111. End If
    112. If ParseNode.Attributes("name").Value = "Fusion Reactor" Then
    113. ParseType.Planet.Planet.Resources.FusionReactor = ParseNode.Attributes("amount").Value
    114. sPlanetInfoPage = "ress"
    115. End If
    116. If ParseNode.Attributes("name").Value = "Solar Satellite" Then
    117. ParseType.Planet.Planet.Resources.SolarSatellite = ParseNode.Attributes("amount").Value
    118. ' An dieser Stelle wird der Seitenname NICHT übergeben! Könnte ja auch die Flottenseite sein.
    119. End If
    120. If ParseNode.Attributes("name").Value = "Metal Storage" Then
    121. ParseType.Planet.Planet.Resources.MetalStorage = ParseNode.Attributes("amount").Value
    122. sPlanetInfoPage = "ress"
    123. End If
    124. If ParseNode.Attributes("name").Value = "Crystal Storage" Then
    125. ParseType.Planet.Planet.Resources.CrystalStorage = ParseNode.Attributes("amount").Value
    126. sPlanetInfoPage = "ress"
    127. End If
    128. If ParseNode.Attributes("name").Value = "Deuterium Tank" Then
    129. ParseType.Planet.Planet.Resources.DeuteriumTank = ParseNode.Attributes("amount").Value
    130. sPlanetInfoPage = "ress"
    131. End If
    132. '#####################################################
    133. 'Ermitteln der Gebäude (Facilities)
    134. If ParseNode.Attributes("name").Value = "Robotics Factory" Then
    135. ParseType.Planet.Planet.Facilities.RoboticFactory = ParseNode.Attributes("amount").Value
    136. sPlanetInfoPage = "faci"
    137. End If
    138. If ParseNode.Attributes("name").Value = "Nanite Factory" Then
    139. ParseType.Planet.Planet.Facilities.RoboticFactory = ParseNode.Attributes("amount").Value
    140. sPlanetInfoPage = "faci"
    141. End If
    142. If ParseNode.Attributes("name").Value = "Shipyard" Then
    143. ParseType.Planet.Planet.Facilities.RoboticFactory = ParseNode.Attributes("amount").Value
    144. sPlanetInfoPage = "faci"
    145. End If
    146. If ParseNode.Attributes("name").Value = "Research Lab" Then
    147. ParseType.Planet.Planet.Facilities.RoboticFactory = ParseNode.Attributes("amount").Value
    148. sPlanetInfoPage = "faci"
    149. End If
    150. If ParseNode.Attributes("name").Value = "Terraformer" Then
    151. ParseType.Planet.Planet.Facilities.RoboticFactory = ParseNode.Attributes("amount").Value
    152. sPlanetInfoPage = "faci"
    153. End If
    154. If ParseNode.Attributes("name").Value = "Alliance Depot" Then
    155. ParseType.Planet.Planet.Facilities.RoboticFactory = ParseNode.Attributes("amount").Value
    156. sPlanetInfoPage = "faci"
    157. End If
    158. If ParseNode.Attributes("name").Value = "Missile Silo" Then
    159. ParseType.Planet.Planet.Facilities.RoboticFactory = ParseNode.Attributes("amount").Value
    160. sPlanetInfoPage = "faci"
    161. End If
    162. Next
    163. End Sub
    164. Sub ParseXML_Allypage()
    165. End Sub
    166. ''' <summary>
    167. ''' Erkennt die Hauptkategorie der XML Daten und startet die jehweiligen Parser
    168. ''' </summary>
    169. ''' <remarks>09.04.2011 - ryg</remarks>
    170. Public Sub ParseXML_Read()
    171. Dim xmlDoc As New XmlDocument
    172. Dim ParseNodes As XmlNodeList
    173. Dim ParseNode As XmlNode
    174. Dim rawData As String
    175. '#######################################
    176. '#######################################
    177. '## TEST
    178. ogProfile.Uni.UniName = "Jupiter"
    179. '#######################################
    180. '#######################################
    181. rawData = XMLData
    182. xmlDoc.LoadXml(rawData)
    183. ParseNodes = xmlDoc.GetElementsByTagName("header")
    184. For Each ParseNode In ParseNodes
    185. sPageType = ParseNode.Attributes("content_type").Value
    186. Select Case sPageType
    187. Case "planetinfo"
    188. ParseXML_PlanetInfo()
    189. Case "allypage"
    190. ParseXML_Allypage()
    191. Case "reports"
    192. ParseXML_Reports()
    193. Case "player_stats"
    194. ParseXML_PlayerStats()
    195. Case "ally_stats"
    196. ParseXML_AllyStats()
    197. End Select
    198. Next
    199. 'Bis hier wurden die Daten ausgelesen.
    200. 'Nun kommt das Aktualisieren der Structures.
    201. '(An dieser Stelle wird das Updaten für Deaktivierte Profile noch NICHT berücksichtigt.
    202. ParseXML_UpdateStruct()
    203. End Sub
    204. End Class
    Wie das abläuft sollte soweit ja klar sein. (Die ParseXML_PlanetInfo ist übrigens gekürzt. Sonst hätte es nicht in den Post gepasst.)
    Allerdings bin ich davon überzeugt, das dies auch ein wenig einfacher geht. Ich habe hier in diesem Beispiel grad mal 50% von dem hinzugefügt, das eigentlich noch kommen muss...
    Nur wird das ganze immer komplizierter.

    Hat jemand eine Idee, das ein wenig zu einfachen?
    Grüße,

    ryg
    Sorry, das ich Pushe.
    Allerdings sitze ich nun schon so lange daran, das ich irgendwie Hilfe erhoffe^^

    Und da ich, wenn ich nun weiter mache, keine Lust habe hinterher dann doch wieder alles ändern zu müssen... naja... warte ich lieber auf Ideen.

    Grüße,

    ryg
    Klar =)

    Beispiel:

    Ich weiß, das es folgende Daten gibt:

    Fusion Reactor
    Solar Satellite
    Metal Storage
    uvm.

    Ich weiß aber nicht wann sie kommen. Um das heraus zu bekommen habe ich diese Schleifen drin:

    For Each ParseNode In ParseNodes


    Die Sache ist allerdings folgende:
    Ich bekomme Pro schleifendurchgang eben nur von einem Eintrag heraus, ob er existiert oder nicht.
    Eleganter wäre es, finde ich, wenn ich alles nur einmal Abfragen müsste um eben das gleiche Ergebnis erzielen zu können.
    Also ein Durchlauf und er fülllt mir die Struktur mit allen Daten die vorhanden sind.

    Vieleicht ist dieses For Each ParseNode zeug nicht der richtige Weg. Wenn er es nicht ist, dann habe ich leider noch keinen Besseren gefunden. Und dafür bin ich hier =D


    Ein weiteres Problem meines Weges ist:

    XML-Quellcode

    1. <?xml version="1.0" encoding="UTF-8"?>
    2. <planetinfos xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="planetinfo.xsd">
    3. <header version="2.6" universe="Jupiter" debug="true" language="german" content_type="planetinfo"/>
    4. <planetinfo playername="xxx" rank="123" points="123" num_players="123" playerid="123" planetname="Atom" moon="false" galaxy="1" system="2" planet="3" used_fields="93" fields="194" max_temp="70">
    5. <officers>
    6. <officer name="commander" enabled="false"/>
    7. <officer name="admiral" enabled="false"/>
    8. <officer name="engineer" enabled="false"/>
    9. <officer name="geologist" enabled="true"/>
    10. <officer name="technocrat" enabled="false"/>
    11. </officers>
    12. <queue type="building">
    13. <entry name="Research Lab" level="5" year="2011" month="7" day="3" hour="1" minute="1" second="55"/>
    14. </queue>
    15. <queue type="research"/>
    16. </planetinfo>
    17. </planetinfos>



    Diese XML Daten können auch gesendet werden. Ich kann diese auch auslesen. Wenn aber diese Daten ankommen, habe ich das Problem, das er den entry Punkt im Queue bereich erkennt, wie die entrys im Planetinfo bereich der XML Daten aus dem ersten Post.
    Hier handelt es sich aber um daten einer Warteschlange. Nicht wie im ersten Fall um vorhandene Daten...


    Unter PHP würde ich das ganze mit Assoziativen Arrays machen. Hier funktioniert das allerdings nicht. Es sei denn ich würde mit collections arbeiten... Was in diesem Fall aber aufgrund von Bibliotheken, die ich nicht verändern kann, aber die Strukturen in genau meiner Form Benötigen.

    Ich hoffe das ist nun weniger verwirrend...
    ich habs Prob auch nicht ganz verstanden - vlt. möchtest du ja auf alle entries zugreifen:

    VB.NET-Quellcode

    1. Public Class Form2
    2. Dim XDoc As XDocument = _
    3. <?xml version="1.0" encoding="UTF-8"?>
    4. <planetinfos xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="planetinfo.xsd">
    5. <header version="2.6" universe="Jupiter" debug="true" language="german" content_type="planetinfo"/>
    6. <planetinfo playername="xxx" playerid="111111" planetname="Atom" moon="false" galaxy="1" system="2" planet="3">
    7. <entry name="Metal" amount="46026"/>
    8. <entry name="Crystal" amount="46006"/>
    9. <entry name="Deuterium" amount="24340"/>
    10. <entry name="Energy" amount="2495"/>
    11. <entry name="Metal Mine" amount="16"/>
    12. <entry name="Crystal Mine" amount="15"/>
    13. <entry name="Deuterium Synthesizer" amount="10"/>
    14. <entry name="Solar Plant" amount="18"/>
    15. <entry name="Fusion Reactor" amount="7"/>
    16. <entry name="Solar Satellite" amount="0"/>
    17. <entry name="Metal Storage" amount="4"/>
    18. <entry name="Crystal Storage" amount="3"/>
    19. <entry name="Deuterium Tank" amount="2"/>
    20. </planetinfo>
    21. </planetinfos>
    22. Private Sub Form2_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
    23. For Each Xel As XElement In XDoc.<planetinfos>(0).<planetinfo>(0).<entry>
    24. Debug.WriteLine(Xel.@name & " - " & Xel.@amount)
    25. Next
    26. End Sub
    27. End Class
    Hrm... Das könnte doch schon so zeimlich die Lösung meines Problems Problems sein...

    Erstens ich umgehe 100.000 schleifen, und kann alles recht schnell und vor allem auch gezielter auslesen.
    Was will ich denn mehr?

    Hrm... Ich bin im moment auf der Arbeit und habe die Source nicht komplett vor Ort, daher werde ich das heute abend erst testen können. Wenn ich das gemacht habe, werde ich auf jeden Fall berichten ob es funktioniert hat oder nicht.

    Dank schon mal an euch. =D
    Okay, habe wieder das gleiche Problem.
    Auch wenn das ganze mit Linq wesentlich einfacher von der Hand geht, habe ich wieder den gleichen Logikfehler wie vorher.

    Wenn ich beispielsweise den Entry mit "name = Entry" auslesen will, dann müsste ich das so wie ich das sehe genau so machen wie bisher... In einer schleife und immer wieder einzeln eintrag für Eintrag durch gehen...

    Ich hatte mir das an sich so vorgestellt wie:

    SELECT amount INTO entry WHERE name="Metal"

    Und schon habe ich das ergebnis... Aber das bekomme ich weder mit Linq noch mit den vorher genutzten XmlDocuments hin...

    Wisst ihr was ich meine?

    Momentan gehe ich ja hin und frage ab:

    Wenn Akuteller Entry Name = "Metal" dann packe "amount" in die dazugehörige Variable.
    Und das mache ich in einer Schleife so lange bis ich alles zusammen habe... Gibts denn keinen Weg, das irgendwie so wie das SQL Query oben hinzubekommen?

    Ich habe in verschiedenen Quellen ansätze bezüglich Where Klauseln in Linq gefunden, leider aber da fragen die diese Daten auch ganz anders ab wie in meinem Query.

    Ich hoffe nun ist einigermaßen klar, was ich meine =/

    ryg schrieb:

    Ich hoffe nun ist einigermaßen klar, was ich meine =/

    nee, nicht wirklich. Jetzt scheint mir, du willst ein Dictionary(Of String, Integer) anlegen.

    VB.NET-Quellcode

    1. Private _Dic as new Dictionary(Of String, Integer)
    2. Private Sub Form2_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
    3. For Each Xel As XElement In XDoc.<planetinfos>(0).<planetinfo>(0).<entry>
    4. _Dic(Xel.@name)= Integer.Parse(Xel.@amount)
    5. Next
    6. End Sub
    Okay... xD

    Ich versuchs mal anders:

    Momentan frage ich meine Daten ja wie folgt ab:

    Vereinfacht

    VB.NET-Quellcode

    1. for i = 0 to AnzahlderEntrys - 1
    2. if NameInEntry(i) = "Metal" then
    3. Struktur.Variable = AmountInEntry(i)
    4. end if
    5. next i


    Und diese IF Abfrage muss ich für ALLE Einträge machen.
    Also: Metal, Crystal, Deut, Metalmine, Crystalmine usw...

    Und der Punkt ist das ich versuchen will es ungefähr so hinzubekommen:

    VB.NET-Quellcode

    1. Struktur.Variable = DatenAus(SELECT amount INTO entry WHERE name="Metal")


    das Ergebnis ist das gleiche. Nur habe ich mir diese Schleife gespart. Und ich habe eine Zeile für die Zuweisung.
    Vieleicht habe ich auch einen total denkfehler...

    Ist es nun ein wenig deutlicher?
    Das ist definitiv nicht bös gemeint^^ Ich will ja das ihr mir helfen könnt, weiß nur nicht genau, wie das Problem am besten beschreiben soll xD
    kannst du das mal wenigstens für 2 (besser für 3) Struktur-Dinger ausführen?

    Übrigens käst es mich beinahe an - manche Leuts benennen ihre Klassen extra fürs Posten um, damit man ja keinen Schimmer haben kann, wozu das eiglich gut sein soll.

    Oder heißt deine Struktur tatsächlich "Struktur", und hat eine Property "Variable"?
    Dann Käst es mich an, das ich den Originalcode im ersten Post gepackt habe. Zwar sehr verkürzt was die unterschiedlichen zu sammelnden Daten angeht, da ich leider nur 15k Zeichen in einen Post setzen kann, aber er verdeutlicht was ich meine. Selbst die XML Dateien die ich auslesen will habe ich so ziemlich im Original gepostet... Die einzigen Änderungen sind nicht relevant für das was ich habe. =(

    Egal^^

    Wie die Struktur aufgebaut ist, ist doch einerlei. Ob ich die Daten die hinterher in ner Struktur, nem Array oder ner Variable speichere, tut bei diesem Problem nichts zur sache will ich meinen.

    Nur für den Fall das ich in der Sache doch falsch liege, im Anhang die Strukturen und die anderen Files, die benötigt werden:

    1. Der Bereich für die ParseType
    2. Weitere wichtige Datentypen
    3. Die Klasse, in der die Original XML Parse bereiche drin sind, die ich in einer Für mich umständlichen weise erstellt habe.
    4-10. 7 von insgesamt 12 unterschiedlichen Möglichkeiten, wie die XML Daten aussehen können.

    Nun sollte wirklich alles vorhanden sein. Alles was nun noch fehlt, würde den Rahmen sprengen und ist auch im aktuellen Zustand nicht relevant.

    Was ich bisher geändert habe ist folgendes:

    Neue clsParseXML.vb:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.Xml
    2. Imports System.Xml.Serialization
    3. Imports System.Xml.Linq
    4. Imports System.IO
    5. Imports System.Linq
    6. Imports ogTypes
    7. Public Class clsParseXML
    8. Private ParseType As New ogTypeParsePlanetinfo
    9. Private GTStrings() As String
    10. Private sPageType As String
    11. 'Seitentypen der PlanetInfo XML Seite der GT-Extension
    12. 'ress, faci, rese, fleet, def
    13. Private sPlanetInfoPage As String
    14. ' Öffentliche Klassenvariablen, Ändern des Pfades nach der Instanziierung möglich
    15. Public XMLData As String
    16. Sub New(ByVal Data As String)
    17. XMLData = Data
    18. ' hier nehme ich in der ersten Zeile 2 aufeinanderfolgende Leerzeichen weg
    19. ' das wird hier nur einmal ausgeführt.
    20. 'XMLData = Replace(XMLData, " ", "", 1, 1)
    21. 'Ich habe das hier ein wenig Umgeschrieben, da es (so wie ich das in einem Testfall mitbekommen habe)
    22. 'auch mal sein kann, das nicht nur 2 Stellen sondern auch mal nur eine oder 3 auftreten können.^^
    23. 'Und diese Lösung ist für all diese Fälle geeignet =D
    24. XMLData = "<" & SplitString(XMLData, "<", 2)
    25. End Sub
    26. Sub ParseXML_AllyStats()
    27. End Sub
    28. Sub ParseXML_PlayerStats()
    29. End Sub
    30. Sub ParseXML_Reports()
    31. End Sub
    32. ''' <summary>
    33. ''' Erasst die Übersichtsdaten
    34. ''' </summary>
    35. ''' <remarks>09.04.2011 - ryg</remarks>
    36. Sub ParseXML_Overview()
    37. Dim xmlDoc As New XmlDocument
    38. Dim ParseNodes As XmlNodeList
    39. Dim ParseNode As XmlNode
    40. Dim rawData As String
    41. rawData = XMLData
    42. xmlDoc.LoadXml(rawData)
    43. ParseNodes = Nothing
    44. ParseNodes = xmlDoc.GetElementsByTagName("planetinfo")
    45. sPlanetInfoPage = ""
    46. For Each ParseNode In ParseNodes
    47. 'Hier sollen die Daten aus der Übersichts_Header geparst werden.
    48. With ParseType
    49. .Overview.RankScore = ParseNode.Attributes("rank").Value
    50. .Overview.Points = ParseNode.Attributes("points").Value
    51. .Overview.PlayerTotal = ParseNode.Attributes("num_player").Value
    52. .OwnerOgameID = ParseNode.Attributes("playerid").Value
    53. .Overview.Fields_Used = ParseNode.Attributes("used_fields").Value
    54. .Overview.Fields = ParseNode.Attributes("fields").Value
    55. .Overview.Temperature = ParseNode.Attributes("max_temp").Value
    56. End With
    57. Next
    58. ParseNodes = Nothing
    59. ParseNodes = xmlDoc.GetElementsByTagName("officer")
    60. sPlanetInfoPage = ""
    61. For Each ParseNode In ParseNodes
    62. If ParseNode.Attributes("name").Value = "commander" Then
    63. ParseType.Officers.Commander = ParseNode.Attributes("enabled").Value
    64. End If
    65. If ParseNode.Attributes("name").Value = "admiral" Then
    66. ParseType.Officers.Admiral = ParseNode.Attributes("enabled").Value
    67. End If
    68. If ParseNode.Attributes("name").Value = "engineer" Then
    69. ParseType.Officers.Engineer = ParseNode.Attributes("enabled").Value
    70. End If
    71. If ParseNode.Attributes("name").Value = "geologist" Then
    72. ParseType.Officers.Geologist = ParseNode.Attributes("enabled").Value
    73. End If
    74. If ParseNode.Attributes("name").Value = "technocrat" Then
    75. ParseType.Officers.Technocrat = ParseNode.Attributes("enabled").Value
    76. End If
    77. Next
    78. sPlanetInfoPage = "over"
    79. MsgBox(ParseType.Overview.PlayerTotal)
    80. End Sub
    81. ''' <summary>
    82. ''' Kategorisiert die einzelnen Planetinfo Daten und fügt diese in ein Parse-Struct
    83. ''' </summary>
    84. ''' <remarks>09.04.2011 - ryg</remarks>
    85. Sub ParseXML_PlanetInfo()
    86. Dim xDoc As XDocument = XDocument.Parse(XMLData)
    87. With ParseType
    88. 'Lesen des Headers
    89. .FFExtVersion = xDoc.<planetinfos>.<header>.@version
    90. .Uni = xDoc.<planetinfos>.<header>.@universe
    91. 'Lesen der Planetinfos
    92. .OwnerName = xDoc.<planetinfos>.<planetinfo>.@playername
    93. .OwnerOgameID = xDoc.<planetinfos>.<planetinfo>.@playerid
    94. .Planet.Planet.Name = xDoc.<planetinfos>.<planetinfo>.@planetname
    95. .Planet.Koords.Galaxie = xDoc.<planetinfos>.<planetinfo>.@galaxy
    96. .Planet.Koords.System = xDoc.<planetinfos>.<planetinfo>.@system
    97. .Planet.Koords.Number = xDoc.<planetinfos>.<planetinfo>.@planet
    98. .Overview.RankScore = xDoc.<planetinfos>.<planetinfo>.@rank
    99. .Overview.Points = xDoc.<planetinfos>.<planetinfo>.@points
    100. .Overview.PlayerTotal = xDoc.<planetinfos>.<planetinfo>.@num_players
    101. .OwnerOgameID = xDoc.<planetinfos>.<planetinfo>.@playerid
    102. .Planet.Planet.Fields = xDoc.<planetinfos>.<planetinfo>.@fields
    103. .Planet.Planet.Temperature = xDoc.<planetinfos>.<planetinfo>.@max_temp
    104. 'Hier wird geprüft, ob es sich bei dem Dantensatz um einen Mond oder einen Planeten handelt.
    105. 'Generell wichtig ist das erst beim Übertragen der erfassten Gesamtdaten an die LiveStructure
    106. If CBool(xDoc.<planetinfos>.<planetinfo>.@moon) = False Then
    107. .isPLanet = False
    108. Else
    109. .isPLanet = True
    110. End If
    111. 'Lesen der Ressourcen
    112. With .Planet.Planet.Supplies
    113. .Metal = xDoc.<planetinfos>.<planetinfos>.<entry>.@amount.Where(xDoc.<planetinfos>.<planetinfo>.<entry>.@name.Contains("Metal")
    114. .Crystal = ""
    115. .Deuterium = ""
    116. .Energy = ""
    117. End With
    118. 'Lesen der Ressourcen Seite
    119. With .Planet.Planet.Resources
    120. .MetalMine = xDoc.<planetinfos>.<planetinfo>.<entry>
    121. .CrystalMine = ""
    122. .DeuteriumSynthesizer = ""
    123. .SolarPlant = ""
    124. .FusionReactor = ""
    125. .SolarSatellite = ""
    126. .MetalStorage = ""
    127. .CrystalStorage = ""
    128. .DeuteriumTank = ""
    129. End With
    130. End With
    131. End Sub
    132. Sub ParseXML_Allypage()
    133. End Sub
    134. ''' <summary>
    135. ''' Erkennt die Hauptkategorie der XML Daten und startet die jehweiligen Parser
    136. ''' </summary>
    137. ''' <remarks>09.04.2011 - ryg</remarks>
    138. Public Sub ParseXML_Read()
    139. Dim xDoc As XDocument = XDocument.Parse(XMLData)
    140. MsgBox(xDoc.<planetinfos>.<header>.@version)
    141. '#######################################
    142. '#######################################
    143. '## TEST
    144. ogProfile.Uni.UniName = "Jupiter"
    145. '#######################################
    146. '#######################################
    147. sPageType = xDoc.<planetinfos>.<header>.@content_type
    148. Select Case sPageType
    149. Case "planetinfo"
    150. ParseXML_PlanetInfo()
    151. Case "allypage"
    152. ParseXML_Allypage()
    153. Case "reports"
    154. ParseXML_Reports()
    155. Case "player_stats"
    156. ParseXML_PlayerStats()
    157. Case "ally_stats"
    158. ParseXML_AllyStats()
    159. End Select
    160. 'Bis hier wurden die Daten ausgelesen.
    161. 'Nun kommt das Aktualisieren der Structures.
    162. '(An dieser Stelle wird das Updaten für Deaktivierte Profile noch NICHT berücksichtigt.
    163. ParseXML_UpdateStruct()
    164. End Sub
    165. ''' <summary>
    166. ''' Update der Spieleigenen Structs
    167. ''' </summary>
    168. ''' <remarks>09.04.2011 - ryg</remarks>
    169. Public Sub ParseXML_UpdateStruct()
    170. Select Case sPageType
    171. Case "planetinfo" 'Planeteninfos
    172. Select Case sPlanetInfoPage
    173. Case "ress" 'Ressourcen
    174. MsgBox("Planetinfo Ressoucen")
    175. Case "faci" 'Facilities
    176. MsgBox("Planetinfo Facilities")
    177. Case "rese" 'Research
    178. MsgBox("Planetinfo Research")
    179. Case "over" 'Overview
    180. MsgBox("Overview")
    181. End Select
    182. Case "reports" 'Reports (Spy&Plani)
    183. MsgBox("Reports")
    184. Case "allypage" 'Allianzseite
    185. MsgBox("Allypage")
    186. Case "player_stats" 'Spielerstats
    187. MsgBox("Spieler Stats")
    188. Case "ally_stats" 'Allianzstats
    189. MsgBox("Ally Stats")
    190. End Select
    191. End Sub
    192. End Class


    Ich hoffe das diese Informationen ausreichend sind.

    Grüße,
    ryg
    Dateien
    Ich glaub ich habs verstanden (sogar noch nach dem 3 Post xD).

    Du möchtest mit einer Abfrage ALLE Relevanten Daten aus der XML auslesen und sofort in die richtigen Variabeln schreiben.
    Dabei ist der Aufbau der XML unterschidlich.

    XML-Quellcode

    1. <entry name="Crystal Mine" amount="15"/>
    2. <entry name="Deuterium Synthesizer" amount="10"/>
    3. <entry name="Solar Plant" amount="18"/>
    4. <entry name="Fusion Reactor" amount="7"/>

    oder z. B.

    XML-Quellcode

    1. <entry name="Crystal Mine" amount="15"/>
    2. <entry name="Fusion Reactor" amount="7"/>
    3. <entry name="Solar Plant" amount="18"/>
    4. <entry name="Deuterium Synthesizer" amount="10"/>


    Du suchst jetzt eine Funktion alà:

    VB.NET-Quellcode

    1. Funktion Auslesen(XML As XML)
    2. Deuterium = Suche Sofort nur mit diese Zeile den Eintrag "name="Deuterium"" in XML und nimm den Wert amount davon
    3. Metall = Suche Sofort nur mit diese Zeile den Eintrag "name="Metall"" in XML und nimm den Wert amount davon
    4. Energie = Suche Sofort nur mit diese Zeile den Eintrag "name="Energie"" in XML und nimm den Wert amount davon
    5. ... = ...


    Alles Ohne 100 Schleifen etc.
    Richtig?

    PS: Irgendwie Fail das du Ogame 1:1 nachprogrammieren willst, aber jeder wie er meint ^^
    Die Interpretation von ihm stimmt! Ja! =DD
    Endlich xD
    Mein Gott, ich muss definitiv an meiner Fähigkeit arbeiten mich Sinnvoll mitzuteilen ^^


    Ich will Ogame nicht Nachbauen... xD Das wäre epic Fail!
    Falls du Ogame kennst, dann vieleicht auch den OGeneral. Ich habe damals den Source von diesem Tool bekommen und sollte das Teil weiter Pflegen. Allerdings war das anfangs nur ein kleines Tool mit dem man Timer für Ressourcen erstellen konnte.. Und ist dann Stück für Stück gewachsen. Jedenfalls war das ein unheimliches Sourcegewusel in VB6. Und wir mussten die Daten per Zwischenablage in das Programm einfügen. Mitlerweile bekommen wir die Daten allerdings von der FF-Extension von Galaxytool als Port.
    Und sowas ist das ganze dann auch. Eine komplette Verwaltung des Spiels, mit Raidlisten, Imperiumsansicht, Statistiken, Spioberichten Kampfsimulatoren, Baulisten, Bautimer, uvm...
    Das was ihr hier seht ist lediglich das zerlegen der Daten die von der Extension kommen.

    Aber egal^^

    Wie ihr in dem gestern geposteten Code sehen könnt, hab ich mit:

    xDoc.<planetinfos>.<planetinfos>.<entry>.@amount.Where(xDoc.<planetinfos>.<planetinfo>.<entry>.@name.Contains("Metal")

    Versucht genau das hinzubekommen was du eben meintest. Vor allem, da ich gelesen habe, das Linq (und darum gehts hier hierbei ja) eine an SQL angelehnte Syntax hat. Aber auch wirklich nur Grob... xD

    Jedenfalls habe ich dann irgendwo im Netz gelesen das man auch WHERE Klauseln hinzufügen kann. Leider bin ich damit noch nicht so erfolgreich gewesen. Ich habe das einfach nicht hinbekommen... Zumindest nicht so wie es sollte.^^

    VB.NET-Quellcode

    1. Private Sub Form2_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
    2. Dim _Dic As New Dictionary(Of String, Integer)
    3. For Each Xel As XElement In XDoc.<planetinfos>(0).<planetinfo>(0).<entry>
    4. _Dic(Xel.@name) = Integer.Parse(Xel.@amount)
    5. Next
    6. Deuterium.Variable = _Dic("Deuterium")
    7. Metall.Variable = _Dic("Metall")
    8. Energie.Variable = _Dic("Energie")
    9. End Sub