Auslesen von Xml-Website mit Regex

  • VB.NET

Es gibt 40 Antworten in diesem Thema. Der letzte Beitrag () ist von CroNeX.

    ja da habe ich mich wohl falsch ausgedrückt, ich meinte wie ich 2 strings gleichzeitig oder hintereinander abfragen kann

    VB.NET-Quellcode

    1. ​Dim result As String = webClient.DownloadString($"http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?key={apiKey}&steamids={steamID}&format=json")

    aber danke für die antwort

    CroNeX schrieb:

    ich meinte wie ich 2 strings gleichzeitig oder hintereinander abfragen kann

    Sehe ich das richtig mit "2 Strings" das du meinst das du zwei oder mehr User gleichzeitig abrufen willst?

    Genau das macht ja mein Beispiel. Siehe Screenshot. Oder komme ich jetzt nicht mit?

    Versuche bitte dich korrekt auszudrücken. Meinst du vieleicht das du zwei Abfragen (vielleicht mit unterschiedlicher URL, also unterschiedlicher API Endpunkte)?
    In dem Fall kannst du ja eine zweite Variable erstellen und wieder mit DownloadString arbeiten. Sollte ja klar sein anhand meines Beispiels. Insofern verstehe ich die Frage nicht wirklich.

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    also ich möchte gerne 2 verschiedene urls auslesen mit einem button in die beiden results in die listbox laden.
    so wie schreibe ich das hier auch damit ich meine werte playtime 2 weeks und playtime forever bekomme.

    VB.NET-Quellcode

    1. {"response":{"game_count":2,"games":[{"appid":252490,"playtime_2weeks":3740,"playtime_forever":3740},{"appid":700580,"playtime_forever":0}]}}

    VB.NET-Quellcode

    1. Dim allPlayersToken2 As List(Of JToken) = response2("response")("games").Children().ToList()

    das geht nicht und als fehler habe ich das bekommen: System.NullReferenceException: "Der Objektverweis wurde nicht auf eine Objektinstanz festgelegt."

    das habe ich auch schon:

    VB.NET-Quellcode

    1. ​Public Class Game
    2. Public Property appid As Integer
    3. Public Property playtime_2weeks As Integer
    4. Public Property playtime_forever As Integer
    5. End Class
    6. Public Class Response
    7. Public Property game_count As Integer
    8. Public Property games As Game()
    9. End Class
    10. Public Class GamesInfo
    11. Public Property response As Response
    12. End Class
    Hallo

    Sorry, aber ich habe dir ein komplett funktionierendes Beispiel hochgeladen.
    Ich kau dir sicher nicht alles vor, da würde der lerneffekt total auf der Strecke bleiben.

    Schau dir wegen deiner Exception mal folgenden Thread GENAU an: Debuggen, Fehler finden und beseitigen

    Versuche der Code von mir zu verstehen. Also nicht nur Copy&Paste sondern Analysiere Zeile für Zeile und schau dir genau an was die macht.
    Dann solltest du eigendlich kein Problem mehr haben.

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Ja Freunde, ich versuche den Code zu verstehen.
    Also mein fehler den ich gepostet habe, habe ich gefixt. nun geht alles soweit.

    Nur hierbei brauche ich hilfe.

    VB.NET-Quellcode

    1. ​{"response":{"game_count":2,"games":[{"appid":252490,"playtime_2weeks":4543,"playtime_forever":4543},{"appid":700580,"playtime_forever":0}]}}

    mit dem .Children() wähle ich ja somit die untergruppen-Tokens aus, stimmts ?
    nun wird aber bei der abfrage 2 mal "appid" oder "playtime_forever" abgefragt. kann ich mit .Children() das so schreiben da er nur die ersten "appid" und "playtime_forever" nimmt ?

    probiert habe ich schon .Children()("playtime_forever") aber da gibt er mir den error das er den string, also die zahl die er hat, nicht umwandeln kann da er ja denn direkt die "playtime" nimmt und nicht später, wie in deinem code.
    Oder müsste ich den code denn komplett umschreiben um denn speziell nur "playtime_forever" raus zu bekommen.

    Ich weiß es ist schwer mit mir aber ich versuche mein bestes und versuche auch es klar und deutlich zu schildern was für ein problem ich habe.
    Danke
    Hallo @CroNeX

    Naja, aber wenn du eh schon die Klasse Response und die Klasse GamesInfo erstellt hast ist es ja sowieso ganz einfach.
    Dann reicht ja ein Simples Dim gi As GamesInfo = JsonConvert.DeserializeObject(Of GamesInfo)(result)
    Das wars dann auch.

    Weist du, ich verstehe nicht warum man sich die Doku von Newtonsoft.Json nicht durchlesen kann. Wenn man ein Framework verwenden will, muss man sich damit beschäftigen, was du aber nicht machst. Und das kostet dir mehr Zeit als du glaubst.

    Hoffe jetzt klappt ews bei dir.

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Und in welcher Hinsicht??
    Ein bischen konkreter musst du schon werden.
    Hast du es schon probiert??

    Hast du schin nen Haltepunkt gesetzt?
    Wie man das macht habe ich dir ja verlinkt. Gelesen?

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Moin, ja Haltepunkte kann ich setzen und mir nachrichten per Debug ausgeben auch.
    nur verstehe ich den Sinn hinter deinem code nicht. magst du ihn mir erklären

    VB.NET-Quellcode

    1. ​Dim gi As GamesInfo = JsonConvert.DeserializeObject(Of GamesInfo)(result)


    ja ich habe klassen angelegt.

    VB.NET-Quellcode

    1. ​Public Class Game
    2. Public Property appid As Integer
    3. Public Property playtime_2weeks As Integer
    4. Public Property playtime_forever As Integer
    5. End Class
    6. Public Class Response
    7. Public Property game_count As Integer
    8. Public Property games As Game()
    9. End Class
    10. Public Class GamesInfo
    11. Public Property response As Response
    12. End Class


    aber wie bekomme ich nun dein code in einklang mit meinen klassen, also das ich die liste korrekt ausgeben lassen kann per listbox ?
    Hallo

    CroNeX schrieb:

    nur verstehe ich den Sinn hinter deinem code nicht. magst du ihn mir erklären

    Wie? Mittels Json.Net wird der JSon String Deserialisiert und du erhaltest genau das was du willst. ein Instanz von deiner Response Klasse.


    CroNeX schrieb:

    aber wie bekomme ich nun dein code in einklang mit meinen klassen, also das ich die liste korrekt ausgeben lassen kann per listbox ?

    Das ist schon im "Einklang" mit deinen Klassen. Was du dann damit machst bleibt dir überlassen. Ob du eine ListBox füllst oder die PlayTime deiner Omi per SMS schickst ist ja nun völlig irrelevant.
    Es geht hier ja um den Abruf. Ich hoffe doch das du weist wie man eine ListBox füllt, ansonsten ist dies ein Thema für einen neuen Thread.

    Fakt ist: Mit dieser einen Zeile hast du alles was benötigt wird, vorausgesetzt der Response der API sieht so aus wie von dir oben gepostet.

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Oh, hab den letzten Beitrag von dir Total übersehen.
    Werde mir morgen mal die Solution laden und nachsehen was du da überhaupt hast.

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    @CroNeX

    Ich weis ja nicht was genau du vorhast und was du alles mit der API machen willst. Sollte es mehr sein/werden als nun in deinem aktuellen Projekt ersichtlich solltest du zusehen das du das ganze etwas generischer gestaltest, auf lange sicht gesehen hast du so viel weniger Arbeit.

    Ich habe mal einen Primitiven Ansatz erstellt indem ich eine Klasse SteamHelper erstellt habe. Dieser Helper kümmert sich um alles was den Abruf von Webservice betrifft.
    Die Klasse setzt die URI zusammen und kümmert sich um die Deserialisierung des JSon-Response in die Klasse ApiResponse. Von dort aus geht es weiter.

    VB.NET-Quellcode

    1. Imports System.Net
    2. Imports System.Text
    3. Imports Newtonsoft.Json
    4. Imports Newtonsoft.Json.Linq
    5. Public NotInheritable Class SteamHelper
    6. Private ReadOnly _steamBaseApiUri As String = "http://api.steampowered.com"
    7. Private ReadOnly _apiKey As String
    8. Private ReadOnly _apiVersion As String
    9. Private Const ApiResponseFormat As String = "json"
    10. Public Sub New(apiKey As String)
    11. Me.New(apiKey, "http://api.steampowered.com")
    12. End Sub
    13. Public Sub New(apiKey As String, rootUrl As String, Optional version As Integer = 1)
    14. _apiKey = apiKey
    15. _apiVersion = $"v{version.ToString("####")}"
    16. _steamBaseApiUri = rootUrl
    17. End Sub
    18. Public Function GetApiResponse(steamInterface As SteamInterface, steamMethod As String, ParamArray parameter() As String) As ApiResponse
    19. Using webClient As New WebClient
    20. Dim result As String = webClient.DownloadString(GetRequestUri(steamInterface, steamMethod, parameter))
    21. Dim response As ApiResponse = JsonConvert.DeserializeObject(Of ApiResponse)(result)
    22. Return response
    23. End Using
    24. End Function
    25. Private Function GetRequestUri(steamInterface As SteamInterface, steamMethod As String, ParamArray parameter() As String) As String
    26. Dim tempUriString = String.Format(GetBaseUri(steamInterface), steamMethod)
    27. For Each p In parameter
    28. tempUriString += $"&{p}"
    29. Next
    30. Return tempUriString
    31. End Function
    32. Private Function GetBaseUri(steamInterface As SteamInterface) As String
    33. 'http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?key={apiKey}&steamids={steamID}&format=json
    34. Return $"{_steamBaseApiUri}/I{steamInterface.ToString}/{{0}}/{_apiVersion}/?key={_apiKey}&format={ApiResponseFormat}"
    35. End Function
    36. End Class
    37. Public Enum SteamInterface
    38. SteamNews = 0
    39. SteamUserStats = 1
    40. SteamUser = 2
    41. PlayerService = 3
    42. End Enum


    Das ganze könnte man noch viel besser gestallten, es soll für dich aber im Moment nur als "anregung" dienen.
    Es gibt ein Modul welches die Methoden der API als Constanten hält, damit man nicht immer gucken muss wie nun die Methode heisst sowie einen Enumerator für die Interfaces der SteamApi. Aus dem selben Grund.

    Eines der Grundgesetze beim Programmieren: Wiederhole dich nicht. Also, schreibe Code nicht mehrmals. Du hast die ganze Response-Sache immer und immer wieder geschrieben. Warum? Pack das in eine Methode oder wie ich in eine Klasse und gut ists.

    Generell musst du dir bei solchen Unternehmungen immer vorher gut überlegen was du genau alles machen willst und danach gestaltest du deine Klassen. Gewöhne dir überhaupt an immer mit Klassen zu Arbeiten.
    Wenn du dir den Code ansiehst wirst du merken wie einfach ich nun beispielsweise die PlayerInfos auslese:

    VB.NET-Quellcode

    1. Dim steamApi As New SteamHelper(apiKey)
    2. Dim gi As ApiResponse = steamApi.GetApiResponse(SteamInterface.SteamUser, SteamUserMethods.GetPlayerSummaries, "steamIds=" & steamID)
    3. gi.response.players.player.ToList.ForEach(Sub(x) ListBox1.Items.Add($"Name: {x.personaname} - Aktuelles Game: {x.gameextrainfo}" ))


    3 Zeilen. Man kanns sogar in eine oder zwei Zeilen packen aber egal, es ist auf jeden fall kürzer. UND... was ist wenn sich die Version der API ändert? Was ist wenn sich die URL ändert?
    Tja, in deinem Fall darfst du dann an 100 stellen immer und immer wieder die Version anpassen. Und nix vergessen sonst suchst du dann!!
    So hast du eine Klasse und die regelt dir alles. Änderungen machst du 1x in dieser Klasse. Fertig.

    Gut, anbei das Projekt. Ich habe dir ein paar Abfragen reingepackt, die restlichen darfst du selbst erweitern.

    Grüße
    Sascha
    Dateien
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Ja Moin, da hast du mir aber einen grooooßen ansatz gegeben, da muss ich mich erstmal reinlesen und erkunden. das ist aber echt eine menge, dankeschön.
    kannst du mir sagen wie ich an den einfachen result in der Form1 komme.
    also wie schreibe ich das in dem falle wie z.b. hier

    VB.NET-Quellcode

    1. ​Dim steamApi As New SteamHelper(apiKey)


    das wäre meine einzige frage bis jetzt.

    gruß CroNeX

    CroNeX schrieb:

    kannst du mir sagen wie ich an den einfachen result in der Form1 komme.

    Ich habe dir bereits oben den Link zum Thread Debuggen, Fehler finden und beseitigen verlinkt, wenn du das nicht lernst kann ich dir nicht Helfen.
    Schau dir dir Klassenstruktur an, dann sollte der rest selbsterklärend sein. Echt jetzt, ich kann dir ja nicht die Grundlagen hier beibringen.

    Besorg dir ein Buch oder lade dir eines der kostenlosen eBooks und lerne die Grundlagen. Dir das hier beizubringen würde den Rahmen des Forums echt sprengen.
    Wenn ICH dir die Grundlagen der Objektorientierten Programmierung beibringen soll kannst du gerne was mit mir ausmachen und ich stelle dir eine Rechnung aus. 8-)

    Im ernst, etwas eigeninitiative musst du schon zeigen. In dem Beispiel habe ich die Struktur EXTRA einfach gehalten, das schaffst du.

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Moin Leute da bin ich wieder.
    Lange ist es her, aber ich arbeite wieder an meinem tool :)

    Kurze frage an euch:
    Wie kann ich eine NullReferenceException verhindern oder abfangen bei meiner funktion. ( siehe bild) ">
    Also gehen wir davon aus das der Anwender eine nicht vorhandene SteamID eingibt, kommt ein error.
    momentan crasht die anwendung und ich weiß nicht wie ich diese NullReference abfangen soll, da in der bestimmung von result ja abgefragt wird

    Wenn nötig reupload ich meine neuere version vom tool

    Danke.
    Fang bitte erstmal damit an, die Infos richtig wiederzugeben. Du hast keine NullReferenceException, sondern eine WebException. Du könntest die Zeile natürlich mit einem Try-Catch ummanteln und daraufhin entsprechend reagieren (z.B. Programmabbruch o.ä.). Aber besser wäre, wenn Du die Ex im Voraus verhinderst. Weißt Du denn, wodurch der Fehler überhaupt kommt?
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.