Einzelne XML Attribute ausgeben

  • VB.NET

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

    Einzelne XML Attribute ausgeben

    Hallo erstmal an alle hier im Forum!

    Hab da ein Problem an dem ich jetzt schon seit 2 tagen rumgrüble und einfach nicht schlauer werde.
    Möchte gerne einen Rechner für ein Spiel machen und deswegen aus einem XML File ein paar Daten rausfiltern.
    Ich weiss nicht ob ich das originale xml File hier posten darf deshalb stell ich nur einen Teil hier ein.

    So jetzt zum Problem:
    Ich will z.B. von ProductionDefinition mit der id=1 die productionTime rausfiltern.
    Also das ich eine Variable mit SteinProductionTime habe mit der ich dann weiterarbeiten kann.

    Würde euch gerne noch sagen was ich alles probiert habe, aber ich weiss es leider nicht mehr ;(
    War so viel das ich mich jetzt nicht mehr auskenne :D

    Gibts da eine Möglichkeit wie in SQL? Select-From-Where usw.

    Jetzt stehts mal so drin.

    Quellcode

    1. Imports System.Xml
    2. Public Class Form1
    3. Private Sub ZeitBox_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ZeitBox.SelectedIndexChanged
    4. Dim Doc As XDocument = XDocument.Load("game_settings.xml")
    5. Dim SteinProductionTime = Doc.Root.<Productions>.<ProductionDefinition>.@id
    6. End Sub
    7. End Class

    Da gibts natürlich nur 1 aus, da es wie ich mal annehme die erste Zeile ist

    Quellcode

    1. <Root>
    2. <Productions>
    3. <ProductionDefinition id="1" name="StoneProduction" inputTyp="Deposit" outputGood="Stone 1" outputStorage="5" productionTime="180" />
    4. <ProductionDefinition id="2" name="ToolsProduction" inputTyp="Good" outputGood="Tools 1" inputGood="Iron 1, Coal 1" outputStorage="5" inputStorage="5,5" productionTime="420" />
    5. <ProductionDefinition id="3" name="GlassProduction" inputTyp="Good" outputGood="Glass 1" inputGood="Potash 1, Quartz 1" outputStorage="5" inputStorage="5,5" productionTime="1260" />
    6. <Productions>
    7. </Root>


    Kann mir da jemand weiterhelfen?
    Oder evtl. Links schicken da wo so ein Beispiel drin ist.

    Danke schon mal :)
    Danke für die Antwort!

    Schema hab ich schon gemacht :)
    Das hab ich mir schon ein paar mal angesehn.
    Das funktioniert bei meiner XML Datei nicht.

    Quellcode

    1. Imports <xmlns="http://schemas.microsoft.com/developer/msbuild/2003">


    Habs jetzt mal so probiert, aber da schreibt er immer: "value" ist kein Member von "String"?
    k.A. was das heisst

    Quellcode

    1. Private Function LoadData() As IEnumerable(Of String)
    2. Dim Doc As XDocument = XDocument.Load("game_settings.xml")
    3. Dim FischProductionTime As String = From xel In Doc.Root.<Productions>.<ProductionDefinition> Where xel.@id.Value = "5" Select xel.@productionTime
    4. Return New String() {}
    5. End Function
    naja, Value ist halt kein Member von String. Was willst du auch mit dem Value an dieser Stelle, btw. von wo haste das abgeschrieben?
    probierma ohne:

    VB.NET-Quellcode

    1. Private Function LoadData() As IEnumerable(Of String)
    2. Dim Doc As XDocument = XDocument.Load("game_settings.xml")
    3. Dim FischProductionTime As String = From xel In Doc.Root.<Productions>.<ProductionDefinition> Where xel.@id = "5" Select xel.@productionTime
    4. Return New String() {}
    5. End Function


    nochmal drauf zurückzukommen:

    zipfermaerzen schrieb:

    ...schreibt er immer: "value" ist kein Member von "String"?
    k.A. was das heisst
    Das heisst genau, was da steht.
    Dein Problem ist vmtl, dass du nicht weißt, was "Member" bedeutet inne objektorientierten Programmierung, dass String ein Datentyp ist, dass xel.@id genau vom Datentyp String ist, und paar annere Sachen.
    Kleiner Einstieg: Grundlagen: Fachbegriffe


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

    Oh, etwas peinlich.
    Trotzdem hab ich noch ein Problem
    Jetzt startet das Script zwar aber das gibt er mir aus?
    Habs in einer TextBox ausgeben lassen
    System.Linq.Enumerable+WhereSelectEnumerableIterator`2[System.Xml.Linq.XElement,System.String]
    Wie gesagt (nö, hab ich noch gar nicht ausdrücklich gesagt - aber jetzt): Kern-Konzept einer typisierten Programmiersprache ist das Konzept "Datentyp".
    Obige Methode etwa gibt als Datentyp IEnumerable(Of String) zurück (sieh hin - stimmt doch, oder?)
    Das ist etwas, was man in einer Textbox gar nicht ausgeben kann, denn ich vermute, du hast es der Textbox.Text-Property zugewiesen.
    Die Textbox.Text-Property ist aber vom Datentyp String - passt also nicht zusammen mit dem, was die Methode zurückgibt.

    Sieh mal nach, wie ich im BeispielProgramm die Ausgabe bewerkstellige.

    Nützlich wird sicher auch sein, du postest die entsprechenden Code-stellen.
    Habs jetzt auch mit einer ListBox!
    Da gibt er mir gar nicht aus?

    VB.NET-Quellcode

    1. Imports System.Xml
    2. Public Class Form1
    3. Public Sub New()
    4. InitializeComponent()
    5. ListBox1.DataSource = LoadData.ToList
    6. End Sub
    7. Private Function LoadData() As IEnumerable(Of String)
    8. Dim Doc As XDocument = XDocument.Load("game_settings.xml")
    9. Return From xel In Doc.<Productions>.<ProductionDefinition> Select xel.@id
    10. Return From xel In Doc.<Productions>.<ProductionDefinition> Where xel.@id = "5" Select xel.@productionTime
    11. Return New String() {}
    12. End Function
    13. End Class


    Hab jetzt mal das XML File angehängt.
    Ich glaub es liegt an dem.
    Kann auch das mit Import <xmls="....... nicht machen
    XSD Schema Hab ich gemacht und zum Projekt hinzugefügt
    Dateien
    • game_settings.xml

      (376,92 kB, 168 mal heruntergeladen, zuletzt: )
    nein, der zeigt dir nix an, weil in deim Xml-Document die übergeordneten Elemente ganz anders heissen als was du abfragst.
    Nutze die Intellisense, wie im Video gezeigt, um deine Abfrage zu formulieren.
    Dazu muss die Schema-Datei aber ins Projekt eingebunden sein (speichern + einbinden!) - wie im Video gezeigt.

    Dass kein Xml-Namespace importiert werden kann liegt daran, dass im Schema keiner definiert ist, weil eben auch im Xml-Dokument keiner enthalten ist.

    Das macht nix, dann gehts nämlich ohne.

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

    Oh, Mann. Bin ich b...
    Sieht man doch den Wald vor lauter Bäumen nicht mehr....
    Bleibt nur noch eines.
    Wie bekomm ich diesen Wert, in dem Fall 110, in eine String variable mit der ich rechnen kann?

    Danke erstmal für Deine Geduld und Hilfe :)
    Dir fehlt wirklich der Begriff Datentyp als Fundament, auf dem du stehst.
    Mit einer String-Variablen kann man nicht rechnen. String ist für Text. Rechnen tut man mit Zahlen. Datentypen hierfür: Integer, Double, Single,...

    Bestimmt hast du Option Strict Off voreingestellt - das solltest du umgehen ändern, noch bevor ich zu deim neueren Problem einen Vorschlag mache.
    Visual Studio - Empfohlene Einstellungen
    (Wenn du schon dabei bist, schmeiss auch gleich den Microsoft.VisualBasic-General-Import raus, das ist die zweite Deppen-Voreinstellung, mit der jeder Vb.Net-Progger erstmal verblödet wird. Wird dort auch gezeigt, wie das geht)
    Hallo ErfinderDesRades!

    Weiß den Unterschied schon zwischen String und Integer. War gestern etwas wirr im Kopf nach der ganzen Googlerei und Probiererei :S
    Hab jetzt mal deinen Rat befolgt und im Visual Studio Strict On eingestellt und den Microsoft.VisualBasic-General-Import rausgeschmissen.
    Muss man ja erst mal wissen als Neueinsteiger?!?!

    Hab mir jetzt auch nochmal deinen Link genauer durchgelesen! Ich werde aber nicht wirklich schlau draus.
    Das kann doch nicht so kompliziert sein diese Attribute einzeln auszulesen und in eine Variable meiner Wahl (Integer, Double oder was auch immer ich brauche) zu packen!
    Nützt in meinem Fall ja nicht wirklich was wenns in einer ListBox steht!
    Ich versteh nicht wieso dies nicht geht!

    VB.NET-Quellcode

    1. Dim Verbrauch as Double = From xel In Doc.Root.<Productions>.<ProductionDefinition> Where xel.@id = 5 Select xel.@productionTime

    oder

    VB.NET-Quellcode

    1. Dim Verbrauch as String = From xel In Doc.Root.<Productions>.<ProductionDefinition> Where xel.@id = 5 Select xel.@inputTyp

    Hab auch mal nach IEnumerable(Of String) gegoogelt aber das zu finden Warum, Weshalb, Weswegen??

    Ganz kurz gesagt: Ich steck da einfach fest und komm trotz intensiver Googlesuche nicht weiter. ;(

    zipfermaerzen schrieb:

    Ich versteh nicht wieso dies nicht geht!

    VB.NET-Quellcode

    1. Dim Verbrauch as Double = From xel In Doc.Root.<Productions>.<ProductionDefinition> Where xel.@id = 5 Select xel.@productionTime
    Wie gesagt: In vb.net ist der Fußboden, auf dem du stehst, das Datentyp-Konzept.
    Wenn du nicht kapierst, dass IEnumerable)(of String) was anneres ist als Double, dann geht halt nix.
    Der Ausdruck From xel In Doc.Root.<Productions>.<ProductionDefinition> Where xel.@id = 5 Select xel.@productionTime gibt IEnumerable(of String) zurück, und das ist numal kein Double, sondern das IEnumerable(of String)
    Das ist gewissermaßen mehrfach inkompatibel
    1. ein Double ist kein String
    2. ein Double ist erst recht kein IEnumerable
    Also IEnumerable bedeutet: es sind viele. Die Abfrage gibt dir alle ProductDefinitions zurück, deren id 5 ist.
    Dabei ist egal, dass nur eine solche ProductDefinition existiert - das kann die Abfrage ja nicht wissen.
    Am besten verzichte auf die Deklaration des (unpassenden) Typen, und lass Type-Inference ihren Job machen

    VB.NET-Quellcode

    1. Dim Verbrauch = From xel In Doc.Root.<Productions>.<ProductionDefinition> Where xel.@id = 5 Select xel.@productionTime
    gesehen? ich hab einfach das As Double weggelassen, und mit Welchen Datentyp hat das Objekt? kannst du überprüfen, dass Verbrauch nun den Datentyp IEnumerable(Of XElement) hat.
    Also viele XElements ist.
    Tatsächlich wird bestenfalls genau ein XElement gefunden, das kanns du folgendermaßen zugreifen:

    VB.NET-Quellcode

    1. dim theXElement = Verbrauch.FirstOrDefault()
    und ist vom Typ XElement

    Dein Code ist jetzt etwas wirr, ich weiß nicht, ob du vom XElement einen Verbrauch, die id, eine ProductionTime, oder einen inputTyp abrufen willst... ?(
    Daher kann ich hier nicht weitermachen.
    Jetzt hab ichs!
    Konnte mit dem IEnumerable nix anfangen!
    Wenn mir vorher einer gesagt hätte was es damit auf sich hat....
    Könnten ja mehrere mit der ID 5 sein, dann kanns natürlich nicht ein einzelner String, Integer oder was auch sonst sein.
    Bei meiner XML ist das aber nicht der Fall. Deswegen die Verwirrung.
    Auf jeden Fall funktioniert es jetzt so wie ich es brauche.
    Mag vielleicht nicht die eleganteste Lösung sein aber für meinen Zweck reichts! :) :)
    Wenns nochmal jemand braucht

    VB.NET-Quellcode

    1. Dim Doc As XDocument = XDocument.Load("game_settings.xml")
    2. Dim FischProductionTime = (From xel In Doc.Root.<Productions>.<ProductionDefinition> Where xel.@id = 5 Select xel.@productionTime).First()
    3. Testbox.Text = FischProductionTime


    Danke ErfinderDesRades für deine Hilfe

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „zipfermaerzen“ ()

    hihi - vmtl. wird niemand ausser dir eine FischproductionTime brauchen. ;)
    Beachte übrigens den Datentyp derselben: String
    Eine Zeitangabe sollte man aber in einer Variablen des Typs Date ablegen, sonst gibts mittelfristig Probleme.
    Etwa beim Sortieren, denn Stringse sortieren sich anners als Datumse.
    Um den String nach Date zu konvertieren verwende Date.Parse()
    Als Doku zu Date.Parse() ziehe den ObjectBrowser heran, also guggemol VisualStudio richtig nutzen (Google ist nicht deine Mami), wie sowas geht...
    Naja eine FischProductionTime wahrscheinlich nicht. :)

    Danke für den Hinweis mit dem Date aber das glaub ich brauch ich in meinem Fall nicht.
    Aber ich seh es mir auf jeden Fall an.
    Ich probier diesen Rechner hier nachzubauen. Halt sozusagen eine Offline Version.
    Meine Feiertagsbeschäftigung neben Familie und dem eigentlichen Spiel!

    http://anno.ultrafine.de/index.php/verbrauchsrechner/verbrauchsrechner-2-0-beta#hint

    LG
    sry - hab nicht kapiert, wie die Site funzt - vmtl. müsste ich mich da registrieren - nein danke.

    egal - das Ding heißt "Rechner", und vmtl. wird da gerechnet. Auch mit Dates kann man rechnen - nur mit String geht das nicht (s.post#10).
    Also wenn du was rechnen willst in deim Rechner - mit Strings kommst du da nicht weiter.
    Die sehen zwar hübsch aus in Text- und List-boxen - aber rechnen kann man mit dene nicht.

    Hast du übrigens inzwischen geschafft, Option Strict On zu stellen? (link in post#10)
    Nein musst nicht angemeldet sein das rechnen kannst.
    Ist etwas verwirrend wennst das Spiel nicht spielst.
    Ja hab die Option Strict On gestellt. Steht auch in Post#11.
    Wegen dem Rechnen. Ich rechne gerade mit den Werten die mir so ausgegeben werden?!?
    Hab jetzt das auslesen der Variablen vom XML File in zwei Module gepackt und auch die XSDs dazu gemacht.
    In den Modulen stehen natürlich mehrer Zeilen drin. Ist jetzt nur gekürzt
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Module Modul_game_settings
    2. Public Doc As XDocument = XDocument.Load("game_settings.xml")
    3. 'Building Materials
    4. Public FischProductionTime = (From xel In Doc.Root.<Productions>.<ProductionDefinition> Where xel.@id = 5 Select xel.@productionTime).First()
    5. End Module

    und

    VB.NET-Quellcode

    1. Module Module_population
    2. Public DocPop As XDocument = XDocument.Load("population.xml")
    3. 'Bauern
    4. Public FischVerbrauchBauern = (From xel In DocPop.Root.<PopulationDefinitions>.<Population>.<RelativeNeed>.<Consumption> Where xel.@id = 1011 Select xel.@amount).First() / 100000
    5. End Module

    Wenn ich jetzt teste

    VB.NET-Quellcode

    1. Testbox.Text = FischVerbrauchBauern * FischProductionTime

    kommt auch das richtige Ergebniss raus

    edit: Muss mich ausbessern. Hab die Option Strict On wieder zurückgestellt. Weiss nicht mehr wieso???
    :) edit-edit: Weils mit Rechnen sonst nicht funzt ?( .

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „zipfermaerzen“ ()

    zipfermaerzen schrieb:

    edit-edit: Weils mit Rechnen sonst nicht funzt
    Klar funzt das net, und darf auch net funzen.
    Sonst könnte man ja auch rechnen: dim crap As Double = "4.3" * "Spätzle mit Linsen" - was meinst du, was da rauskäme?
    Nein, wenn du als Programmierer genau weißt, dass in den Strings Zahlen reingeschrieben sind, dann kannst du parsen. Hierfür haben alle rechen-fähigen Datentypen (Double, Integer, Byte, ..., Date, Timespan, Guid, Dockstyle,...) eine Parse-Methode, mit der man einen String in den Datentyp umwandeln kann.
    Es ist wichtig, dabei korrekt zu bleiben, auch wenns zunächstmal umständlich scheint.
    Das Umständliche kommt aus deiner Programm-Besonderheit, dass deine Daten als String gelesen werden, und dass du sie auch gar nicht weiter verarbeitest, sondern nur anzeigen willst, und auch das Anzeigen geht nur als String.
    Deshalb musst du erst den String parsen, dann rechnen, und dann formatieren, um wieder einen String zu erhalten. Ist nervig, aber damit hast du ein weiteres Grund-Konzept gelernt:
    Die Fachbegriffe fürs Umwandeln von String <--> Datentyp lauten "Parsen / Formatieren". Ist ein wichtiger Bereich inne Informatik, und eine der häufigsten Fehlerquellen. Und gibt einige, z.T. sehr mächtige Methoden, mit denen sowas umzusetzen ist.
    Hierbei sind Methoden, die Parse(), TryParse() heissen die am besten geeignetsten, denn diese sind extra fürs Parsen da (wer hätte das gedacht).
    Auf der String-Seite gibts die String.Format() - Methode als Mädchen für alles, aber das ist auch eine Wissenschaft für sich, die richtig anzuwenden.
    Habe ich dir eiglich schon den ObjectBrowser empfohlen, um Datentypen zu untersuchen?
    Etwa bei der String-klasse wirst du staunen, was die alles kann: VisualStudio richtig nutzen
    Gewöhn dir am besten an, jeden, wirklich jeden Datentyp, den du vor die Tastatur kriegst, zunächstmal gründlich damit zu untersuchen, und browse damit auch die verwandten Datentypen an, bzw. Datentypen, die zusammenhängen ("Verwaandschaft" ist nur eine Form des "Zusammenhangs")




    Jdfs. mal konkret:

    VB.NET-Quellcode

    1. Textbox.Text = (Integer.Parse(FischVerbrauchBauern) * Integer.Parse(FischProductionTime)).ToString

    Dein Code ist übrigens sehr komisch -

    VB.NET-Quellcode

    1. Public FischVerbrauchBauern = (From xel In DocPop.Root.<PopulationDefinitions>.<Population>.<RelativeNeed>.<Consumption> Where xel.@id = 1011 Select xel.@amount).First() / 100000
    - funktioniert das?
    Ich würde denken, diese aufwändigen Vorgänge gehören in eine Methode, nicht direkt ins Modul.

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