Auslesen von Xml-Website mit Regex

  • VB.NET

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

    Auslesen von Xml-Website mit Regex

    Moin Leute, ich habe da folgendes problem.
    Ich möchte gerne aus einer xml website "parameter" auslesen also namen oder zahlen.
    die website ist so aufgebaut:

    XML-Quellcode

    1. <steamid>4565667963536</steamid>
    2. <communityvisibilitystate>3</communityvisibilitystate>
    3. <profilestate>1</profilestate>
    4. <personaname>peterpan</personaname>
    5. <lastlogoff>1547951954</lastlogoff>

    genau so ist die aufgebaut mit den selben umbrüchen etc.

    das habe ich schon und funktioniert:

    VB.NET-Quellcode

    1. Imports System.Text.RegularExpressions
    2. Dim wc1 As New Net.WebClient
    3. wc1.DownloadStringAsync(New Uri("URL"))
    4. AddHandler wc1.DownloadStringCompleted, AddressOf wc1_DownloadStringCompletedPrivate Sub wc1_DownloadStringCompleted(ByVal sender As Object, ByVal e As System.Net.DownloadStringCompletedEventArgs)
    5. Dim text As String = e.Result
    6. End Sub


    so nun möchte ich die parameter auslesen, wozu ich schon vieles ausprobiert habe. wie z.b.

    VB.NET-Quellcode

    1. Dim stringSource As New Regex("<steamid>(\d+)</steamid>", RegexOptions.IgnoreCase Or RegexOptions.Singleline)
    2. Dim stringMatches As MatchCollection = stringSource.Matches(text)
    3. For Each match As Match In stringMatches
    4. Label1.Text = match.Groups(1).Value


    aber ich kann immer nur 1 string auslesen also 1 parameter , wie schreibe ich das, dass ich beispielweise steamid UND playername auslesen kann und in eine listbox oder label packen kann.
    das sind meine probleme

    Danke für eure hilfe

    *Codetags eingefügt* ~NoFear23m

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

    VB.NET-Quellcode

    1. Dim stringSource As New Regex("<(\w+>).*?\1", RegexOptions.IgnoreCase)
    2. [...]
    3. Label1.Text &= match.Groups(1).Value & " "
    Ähm - warum heisst die Variable stringSource?? Es ist doch weder ein String noch eine Source, sondern ist ein Regex!?!?!

    Ansonsten empfehle ich dringend, deinen Code in lesbarer Form zu präsentieren
    Hallo @CroNeX

    Vieleicht solltest du etwas mehr über die "Website" plaudern, allen anschein nach ist dies nämlich keine Website sondern das Ergebniss einer API/Webservice.
    Und wenn dem so ist könntest dieses Webservice in VS einbinden und dir werden alle PRoxyklassen automatisch erzeugt, so brauchst du gar nicht mit XML, RegEx oder sonstwas herumhantieren.

    Aber wie gesagt, da müssten wir mal wissen um was es genau geht.

    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 danke für die antworten.
    ja genau durch die steam web api, erfrage ich durch die userID welche stats derjenige hat und das wird mir in einer json oder xml ausgegeben.
    das möchte ich denn gerne angezeigt bekommen in einer listbox oder listview etc
    Bilder
    • Unbenannt.JPG

      84,9 kB, 1.086×533, 59 mal angesehen
    Hallo @CroNeX

    Du musst mich nicht unbedingt per PN anschreiben das du eine Antwort verfasst hast, ich bekomme ohnehin eine Benachrichtung.

    Na wenn du eh eine JSON auch zurück bekommen kannst würde ich wie folgt vorgehen.
    Den Response kopieren und mit jsonutils.com/ eine Klasse generieren lassen.

    Zb. würde der Converter für die Adresse folgende KLasse ausspucken:

    VB.NET-Quellcode

    1. Public Class Todo
    2. Public Property userId As Integer
    3. Public Property id As Integer
    4. Public Property title As String
    5. Public Property completed As Boolean
    6. End Class


    Jetzt musst du nur noch mit Json.Net das ganze serialisieren.
    Hierfür gibt es ein NuGet-Paket: nuget.org/packages/Newtonsoft.Json/

    Das Bindest du ein und dann kannst du ganz einfach damit Serialisieren:

    VB.NET-Quellcode

    1. Dim webClient As New System.Net.WebClient
    2. Dim result As String = webClient.DownloadString("https://jsonplaceholder.typicode.com/todos")
    3. Dim TodoList As List(Of Todo) = JsonConvert.DeserializeObject(Of List(Of Todo))(result)
    4. TodoList.ForEach(Sub(x) Console.WriteLine($"Todo ID: {x.id} - Title: {x.title}"))


    Folgender Screenshot zeigt das Ergebniss in der Console. Einfacher kann man finde ich eine WebAPI gar nicht mehr nutzen.



    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 danke für die hilfe schon mal :)
    Wie soll ich das sagen, kannst du mir dabei helfen das kleine programm zu schreiben ?
    z.b. wie mach ich das am besten : "Den Response kopieren und mit jsonutils.com/ eine Klasse generieren lassen." ?
    das habe ich schon: "Hierfür gibt es ein NuGet-Paket: nuget.org/packages/Newtonsoft.Json/"wäre echt klasse von dir, danke
    Super, also das NuGet-Paket hast du schonmal eingebunden. Gut.

    Jetzt zeige mal einen JSON Response und wir werden sehen wie wir dir diesen so schön wie möglich in eine Klasse packen.
    Aller Anfang ist schwer, aber das schaffst du schon - solange der Wille zu lernen da ist.

    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. ##

    Nene, du sollst den Response posten. Also das was du zurück bekommst wenn du ein Get diese URI sendest.

    Beispiel für folgendes Webservice: jsonplaceholder.typicode.com/todos

    Im Fiddler einen Request im Composer absetzen indem du die URI welche du an Steam sendest in das Feld kopierst.
    Dann auf EXECUTE klicken.

    Anschliessend wechselst du in den Reiter Inspector und dort wählst du für die Anzeige RAW.

    Den String kannst du Posten.

    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. ##

    okay nun sollte ich es haben.



    {"response":{"players":[{"steamid":"76561198403130256","communityvisibilitystate":3,"profilestate":1,"personaname":"peters12jolina","lastlogoff":1548048046,"profileurl":"https://steamcommunity.com/profiles/76561198403130256/","avatar":"https://steamcdn-a.akamaihd.net/steamcommunity/public/images/avatars/fe/fef49e7fa7e1997310d705b2a6158ff8dc1cdfeb.jpg","avatarmedium":"https://steamcdn-a.akamaihd.net/steamcommunity/public/images/avatars/fe/fef49e7fa7e1997310d705b2a6158ff8dc1cdfeb_medium.jpg","avatarfull":"https://steamcdn-a.akamaihd.net/steamcommunity/public/images/avatars/fe/fef49e7fa7e1997310d705b2a6158ff8dc1cdfeb_full.jpg","personastate":1,"primaryclanid":"103582791429521408","timecreated":1499157807,"personastateflags":0,"gameextrainfo":"Rust","gameid":"252490"}]}}
    Naja, fast.

    Das sollte nun deine Playerklasse sein welche du mit Newtonsoft.Json Serialisieren kannst:

    VB.NET-Quellcode

    1. Public Class Player
    2. <JsonProperty("steamid")>
    3. Public Property Steamid As String
    4. <JsonProperty("communityvisibilitystate")>
    5. Public Property Communityvisibilitystate As Integer
    6. <JsonProperty("profilestate")>
    7. Public Property Profilestate As Integer
    8. <JsonProperty("personaname")>
    9. Public Property Personaname As String
    10. <JsonProperty("lastlogoff")>
    11. Public Property Lastlogoff As Integer
    12. <JsonProperty("profileurl")>
    13. Public Property Profileurl As String
    14. <JsonProperty("avatar")>
    15. Public Property Avatar As String
    16. <JsonProperty("avatarmedium")>
    17. Public Property Avatarmedium As String
    18. <JsonProperty("avatarfull")>
    19. Public Property Avatarfull As String
    20. <JsonProperty("personastate")>
    21. Public Property Personastate As Integer
    22. <JsonProperty("primaryclanid")>
    23. Public Property Primaryclanid As String
    24. <JsonProperty("timecreated")>
    25. Public Property Timecreated As Integer
    26. <JsonProperty("personastateflags")>
    27. Public Property Personastateflags As Integer
    28. <JsonProperty("gameextrainfo")>
    29. Public Property Gameextrainfo As String
    30. <JsonProperty("gameid")>
    31. Public Property Gameid As String
    32. End Class


    Der Abruf läuft wie oben in Post 5 bereits von mit gepostet ab. Sollte was nicht klappen Poste die genaue Fehlermeldung setze einen Haltepunkt und Poste auch den String welcher sich in der Variable result befindet indem du auf die kleine Lupe klickst.

    Viel Glück

    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. ##

    sooo da bin ich wieder. habe folgendes problem, wenn ich versuche das ganze zu Serialisieren kommt die Fehlermeldung das x.steamid oder x.personaname nicht exestiert, da ich das ganze in eine andere klasse packen muss. wie verweise ich auf die classe "player", damit es funktioniert ?

    Das Bindest du ein und dann kannst du ganz einfach damit Serialisieren:

    VB.NET-Quellcode

    1. Dim webClient As New System.Net.WebClient
    2. Dim result As String = webClient.DownloadString("https://jsonplaceholder.typicode.com/todos")
    3. Dim TodoList As List(Of Todo) = JsonConvert.DeserializeObject(Of List(Of Todo))(result)
    4. TodoList.ForEach(Sub(x) Console.WriteLine($"Todo ID:[u][b] {x.id}[/b][/u] - Title: [u][b]{x.title}[/b][/u]"))



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

    Hallo und guten Morgen

    Moment mal....
    Warum Postest du nun wieder meinen Quellcode? Hast du den etwas genau so übernommen? Wie soll das funktionieren?
    Mein Autoschlüssel wird bei deinem Auto auch nicht passen oder? :whistling:

    Du musst den Quellcode schon anpassen.

    Du hast die Klasse Player erstellt richtig?
    OK, dann passt du meinen Quellcode an:


    VB.NET-Quellcode

    1. Dim webClient As New System.Net.WebClient
    2. Dim result As String = webClient.DownloadString("https:\\dieUrlzudeinemWebservice")
    3. Dim AllPlayers As List(Of Player) = JsonConvert.DeserializeObject(Of List(Of Player))(result)
    4. TodoList.ForEach(Sub(x) Console.WriteLine($"Todo ID: {x.Streamid} - Title: {x.Personaname}"))


    So sollte es mal kompilieren.
    Sollte nun ein Fehler kommen, Poste bitte die genaue(!!) Fehlermeldung und wie oben schon genannt den Text in der Variable result !!

    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 klar hatte ich dein code überarbeitet und ihn nicht 1 zu 1 übernommen :)

    soo die erste fehlermeldung:

    VB.NET-Quellcode

    1. ​Newtonsoft.Json.JsonSerializationException ist aufgetreten.
    2. HResult=0x80131500
    3. Nachricht = Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[Steam_Hour_Boostr_Info.Player]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
    4. To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List<T>) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.
    5. Path 'response', line 1, position 12.
    6. Quelle = <Die Ausnahmequelle kann nicht ausgewertet werden.>
    7. Stapelüberwachung:
    8. at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
    9. at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
    10. at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
    11. at Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings)
    12. at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value, JsonSerializerSettings settings)
    13. at Steam_Hour_Boostr_Info.Form1.Button1_Click(Object sender, EventArgs e) in C:\Users\Max\documents\visual studio 2017\Projects\Steam Hour Boostr Info\Steam Hour Boostr Info\Form1.vb:line 30
    14. at System.Windows.Forms.Control.OnClick(EventArgs e)
    15. at System.Windows.Forms.Button.OnClick(EventArgs e)
    16. at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
    17. at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
    18. at System.Windows.Forms.Control.WndProc(Message& m)
    19. at System.Windows.Forms.ButtonBase.WndProc(Message& m)
    20. at System.Windows.Forms.Button.WndProc(Message& m)
    21. at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
    22. at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
    23. at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
    24. at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
    25. at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
    26. at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun()
    27. at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel()
    28. at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(String[] commandLine)
    29. at Steam_Hour_Boostr_Info.My.MyApplication.Main(String[] Args) in :line 81
    Und?
    Wo ist der Inhalt der Variable Result und dein aktueller Code??

    Lass dir bitte nicht alles aus der Nase ziehen.
    Da ich keinen Steam Account habe und mir auch sicher keinen deshalb zulege kann ich nur mit den Daten Arbeiten die DU mir gibst.

    Du gibst mir nur nichts.
    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. ##

    okay okay, also mein result ist immer noch der selbe.
    hier mein cod:

    VB.NET-Quellcode

    1. Imports Newtonsoft.Json
    2. Imports System.Net
    3. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    4. Dim webClient As New System.Net.WebClient
    5. Dim result As String = webClient.DownloadString("http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?key=XXXXXXX&steamids=XXXXX&format=json")
    6. Dim AllPlayers As List(Of Player) = JsonConvert.DeserializeObject(Of List(Of Player))(result)
    7. AllPlayers.ForEach(Sub(x) Console.WriteLine($"Todo ID: {x.personaname} - Title: {x.steamid}"))
    8. Public Class Player
    9. Public Property steamid As String
    10. Public Property communityvisibilitystate As Integer
    11. Public Property profilestate As Integer
    12. Public Property personaname As String
    13. Public Property lastlogoff As Integer
    14. Public Property profileurl As String
    15. Public Property avatar As String
    16. Public Property avatarmedium As String
    17. Public Property avatarfull As String
    18. Public Property personastate As Integer
    19. Public Property primaryclanid As String
    20. Public Property timecreated As Integer
    21. Public Property personastateflags As Integer
    22. Public Property gameextrainfo As String
    23. Public Property gameid As String
    24. End Class
    25. Public Class Response
    26. Public Property players As Player()
    27. End Class
    28. Public Class info
    29. Public Property response As Response
    30. End Class


    *API Keys unkenntlich gemacht* ~NoFear23m

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

    OK, fange ich mal an. Ich habs ja jetzt Testen können, du hast ja deine SteamId mit Online gestellt. Ich war so frei und habe diese entfernt.

    1.) Du hast die Player Klasse nicht so übernommen wie ich sie in Post #11 gepostet hatte. Warum? Willst du nicht das es funktioniert?
    2.) Wollte ich das du den Response postest, egal jetzt habe ich dank deines API Keys ja selbst testen können.

    Also, beim deserialisieren mit Newtonsoft waren noch zwei ebenen mehr enthalten. Wie man an dem Response in Post #10 von dir eh auch sehen hat können, hier hätte dir dann 10 Sekunden Google folgende Seite offenbart:
    newtonsoft.com/json/help/html/SerializingJSONFragments.htm
    Auf dieser Seite sieht man gut wie man das anstellen muss um auf die unteren Knoten zu kommen um diese anschliessend in Objekte Casten zu können.

    C#-Quellcode

    1. JObject googleSearch = JObject.Parse(googleSearchText);
    2. // get JSON result objects into a list
    3. IList<JToken> results = googleSearch["responseData"]["results"].Children().ToList();
    4. // serialize JSON results into .NET objects
    5. IList<SearchResult> searchResults = new List<SearchResult>();
    6. foreach (JToken result in results)
    7. {
    8. // JToken.ToObject is a helper method that uses JsonSerializer internally
    9. SearchResult searchResult = result.ToObject<SearchResult>();
    10. searchResults.Add(searchResult);
    11. }


    Wenden wir diesen C# Code auf unsere Struktur an und wandeln ihn in VB um erhalten wie ca. sowas:

    VB.NET-Quellcode

    1. Dim allPlayersToken As List(Of JToken) = response("response")("players").Children().ToList()
    2. Dim allPlayers As New List(Of Player)
    3. allPlayersToken.ForEach(Sub(x) allPlayers.Add(x.ToObject(Of Player)))


    Tja, und nun müssen wir diese nur noch in der Console ausgeben mit: allPlayers.ForEach(Sub(x) Console.WriteLine($"Personenname: {x.Personaname} - SteamId: {x.Steamid}"))

    Und alles ist gut. Man darf Code eben nicht einfach nur kopieren sondern muss versuchen ihn zu verstehen. Und gerade wenn man 3rd Party Bibliotheken wie NewtonsoftJSon verwendet sollte man auch man in deren Doku reinsehen. Ja, das ist Programmieren, der Anfang ist schwer, aber auch die Besten müssen sich schlau machen wie man welche Frameworks anwendet und wie man zum gewünschten Ergebniss kommt.
    Hier ist eben eigeninitiative gefragt.

    Anbei für ganz faule nun auch die Solution. (API Key habe ich rausgenommen, man wird gefragt und kann ihn dann in die Konsole kopieren.)
    Es gehen übrigens auch mehrere abzufragen indem man die SteamIds mit ; trennt. Siehe Screenshot



    Grüße
    Sascha
    Dateien
    • TestSteamApi.zip

      (633,08 kB, 19 mal heruntergeladen, zuletzt: )
    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 danke danke danke für deine tolle Hilfe :)
    es läuft nun endlich. habs statt in einem modul, in eine form1 gepackt und möchte damit noch ein bisschen rumprobieren ;)

    nun habe ich wieder 2 fragen an dich oder auch 3 :D
    kann ich das result also

    VB.NET-Quellcode

    1. ​allPlayers.ForEach(Sub(x) ListBox1.Items.Add($"Personenname: {x.personaname} - Test: {x.gameextrainfo}"))
    auch mit zeilenumbruch anzeigen lassen ... d.h. untereinander oder muss ich es seperat coden ?

    VB.NET-Quellcode

    1. ​allPlayers.ForEach(Sub(x) ListBox1.Items.Add($"Name: {x.personaname}"))
    2. allPlayers.ForEach(Sub(x) ListBox1.Items.Add($"Test: {x.gameextrainfo}"))


    so nun 2 frage, kann ich den Text den ich vorher angebe wie "Personenname", mit einer bestimmten farbe versehen ? habe da nichts gefunden bis jetzt.

    frage 3, die ist komplizierter. kann ich auch 2 hintereinander folgenede strings also "Urls" auslesen oder muss ich warten bis Json den 1 String fertig hat und denn den 2 String verarbeiten kann ?

    also bei allen fragen habe ich schon gegoogelt und/oder nichts richtiges gefunden was mir weiterhelfen könnte.

    CroNeX schrieb:

    auch mit zeilenumbruch anzeigen lassen ... d.h. untereinander oder muss ich es seperat coden ?
    Die ListBox unterstützt keine mehrzeiligen Einträge. Deinen Alternativ-Vorschlag hast Du wohl nicht ausprobiert, sonst wüsstest Du schon dass dabei rauskommen würde:

    Quellcode

    1. Person1
    2. Person2
    3. Person3
    4. ...
    5. gameextrainfo1
    6. gameextrainfo2
    7. gameextrainfo3

    CroNeX schrieb:

    kann ich den Text [...] mit einer bestimmten farbe versehen
    Nein, zumindest nicht in einer ListBox. Diese ermöglicht von Haus aus keine unterschiedlichen Zeilenfarben. Nimm stattdessen ein DGV, welches man so gestalten kann, dass es wie eine ListBox aussieht.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Häufig von mir verwendete Abkürzungen: CEs = control elements (Labels, Buttons, DGVs, ...) und tDS (typisiertes DataSet)
    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht in den Spekulatiusmodus gehen.