XML Deserialisieren

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 16 Antworten in diesem Thema. Der letzte Beitrag () ist von kafffee.

    XML Deserialisieren

    Hallo miteinander ich bins mal wieder :)

    Ich hole mir per HttpClient einen XML String ins Programm, den ich gerne deserialisieren möchte.

    Leider bekomme ich dabei den Fehler:

    System.InvalidOperationException
    Nachricht = Fehler im XML-Dokument (2,2).
    Quelle = System.Xml
    Innere Ausnahme 1:
    InvalidOperationException: <GetLyricResult xmlns='http://api.chartlyrics.com/'> wurde nicht erwartet.

    Das XML das ich bekomme sieht so aus:

    Spoiler anzeigen

    XML-Quellcode

    1. <?xml version="1.0" encoding="utf-8"?>
    2. <GetLyricResult xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://api.chartlyrics.com/">
    3. <TrackId>0</TrackId>
    4. <LyricChecksum>b03874238631db2c71d7766b0a0d2bcb</LyricChecksum>
    5. <LyricId>32407</LyricId>
    6. <LyricSong>Jein</LyricSong>
    7. <LyricArtist>Fettes Brot</LyricArtist>
    8. <LyricUrl>http://www.chartlyrics.com/qxcnXB47Q0CIdOiOzzkcyQ/Chicago.aspx</LyricUrl>
    9. <LyricCovertArtUrl>http://ec2.images-amazon.com/images/P/B000Q7ZM2I.03.MZZZZZZZ.jpg</LyricCovertArtUrl>
    10. <LyricRank>7</LyricRank>
    11. <LyricCorrectUrl>http://www.chartlyrics.com/app/correct.aspx?lid=MwAyADQAMAA3AA==</LyricCorrectUrl>
    12. <Lyric>HIERKOMMENDIELYRICS</Lyric>
    13. </GetLyricResult>



    und mein Code so:

    VB.NET-Quellcode

    1. Dim Songdaten As GetLyricResult
    2. Dim Serialisierer As New XmlSerializer(GetType(GetLyricResult))
    3. Using Ergebnis As System.IO.TextReader = New System.IO.StringReader(Lyrics)
    4. SongDaten = CType(Serialisierer.Deserialize(Ergebnis), GetLyricResult)
    5. End Using


    Und das hier ist die Datenklasse:

    VB.NET-Quellcode

    1. Imports System.Xml.Serialization
    2. <XmlRoot(ElementName:="GetLyricResult")>
    3. Public Class GetLyricResult
    4. <XmlElement(ElementName:="TrackId")>
    5. Public Property TrackId As Integer
    6. <XmlElement(ElementName:="LyricChecksum")>
    7. Public Property LyricChecksum As String
    8. <XmlElement(ElementName:="LyricId")>
    9. Public Property LyricId As Integer
    10. <XmlElement(ElementName:="LyricSong")>
    11. Public Property LyricSong As String
    12. <XmlElement(ElementName:="LyricArtist")>
    13. Public Property LyricArtist As String
    14. <XmlElement(ElementName:="LyricUrl")>
    15. Public Property LyricUrl As String
    16. <XmlElement(ElementName:="LyricCovertArtUrl")>
    17. Public Property LyricCovertArtUrl As String
    18. <XmlElement(ElementName:="LyricRank")>
    19. Public Property LyricRank As Integer
    20. <XmlElement(ElementName:="LyricCorrectUrl")>
    21. Public Property LyricCorrectUrl As String
    22. <XmlElement(ElementName:="Lyric")>
    23. Public Property Lyric As String
    24. <XmlAttribute(AttributeName:="xsd")>
    25. Public Property Xsd As String
    26. <XmlAttribute(AttributeName:="xsi")>
    27. Public Property Xsi As String
    28. <XmlAttribute(AttributeName:="xmlns")>
    29. Public Property Xmlns As String
    30. <XmlText>
    31. Public Property Text As String
    32. End Class


    Hat jemand ne Idee wo der Fehler liegen könnte?

    Hab auch schon probiert das programmatisch zuerst nach JSON zu konvertieren und dann zu deserialisieren, da bekomm ich dann aber einen leeren String zurück...:

    VB.NET-Quellcode

    1. Dim XML As XmlDocument = New XmlDocument
    2. XML.LoadXml(Lyrics)
    3. Dim JSONString As String = JsonConvert.SerializeXmlNode(XML)
    4. TextBox3.Text = JSONString
    5. Dim MeineKlasse As GetLyricResult = JsonConvert.DeserializeObject(Of GetLyricResult)(TextBox3.Text)
    6. TextBox3.Text = MeineKlasse.Lyric
    @kafffee Wie hast Du denn das Dokument serialisiert?
    Das Einlesen erfolgt üblicherweise uinvers dazu.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @HenryV

    Ja das scheint in die Richtung zu gehen. Hab jetzt das:

    VB.NET-Quellcode

    1. Imports System.Xml.Serialization
    2. '<XmlRoot(ElementName:="GetLyricResult")>
    3. Public Class GetLyricResult
    4. System.Serialization.XmlRoot(Namespace:="http://api.chartlyrics.com/")
    5. <XmlElement(ElementName:="TrackId")>
    6. Public Property TrackId As Integer
    7. <XmlElement(ElementName:="LyricChecksum")>
    8. Public Property LyricChecksum As String
    9. <XmlElement(ElementName:="LyricId")>
    10. Public Property LyricId As Integer
    11. <XmlElement(ElementName:="LyricSong")>
    12. Public Property LyricSong As String
    13. <XmlElement(ElementName:="LyricArtist")>
    14. Public Property LyricArtist As String
    15. <XmlElement(ElementName:="LyricUrl")>
    16. Public Property LyricUrl As String
    17. <XmlElement(ElementName:="LyricCovertArtUrl")>
    18. Public Property LyricCovertArtUrl As String
    19. <XmlElement(ElementName:="LyricRank")>
    20. Public Property LyricRank As Integer
    21. <XmlElement(ElementName:="LyricCorrectUrl")>
    22. Public Property LyricCorrectUrl As String
    23. <XmlElement(ElementName:="Lyric")>
    24. Public Property Lyric As String
    25. <XmlAttribute(AttributeName:="xsd")>
    26. Public Property Xsd As String
    27. <XmlAttribute(AttributeName:="xsi")>
    28. Public Property Xsi As String
    29. <XmlAttribute(AttributeName:="xmlns")>
    30. Public Property Xmlns As String
    31. <XmlText>
    32. Public Property Text As String
    33. End Class


    Aber da wird System in Zeile 6 rot unterstrichen mit der Meldung "Deklaration erwartet."

    Hab ein wenig damit rumgespielt, aber ohne Erfolg...
    Hallo,
    das System.Serialization.XmlRoot ist ein Attribut für die Klasse, es muss also über der Klassendeklaration stehen. Beispiel (Achtung, ist konvertierter Code)

    VB.NET-Quellcode

    1. Class SurroundingClass
    2. Private Sub Main()
    3. Dim serializer As XmlSerializer = New XmlSerializer(GetType(GetLyricResult))
    4. Using fs = File.OpenRead("demo.xml")
    5. Dim result = CType(serializer.Deserialize(fs), GetLyricResult)
    6. End Using
    7. End Sub
    8. <XmlRootAttribute("GetLyricResult", [Namespace]:="http://api.chartlyrics.com/")>
    9. Public Class GetLyricResult
    10. Public Property TrackId As Integer
    11. Public Property LyricChecksum As String
    12. Public Property LyricId As Integer
    13. Public Property LyricSong As String
    14. Public Property LyricArtist As String
    15. Public Property LyricUrl As String
    16. Public Property LyricCovertArtUrl As String
    17. Public Property LyricRank As Integer
    18. Public Property LyricCorrectUrl As String
    19. Public Property Lyric As String
    20. End Class
    21. End Class
    :thumbsup: Jou super funktioniert...

    Ich hab nur noch ein Problem: Mir werden die Umlaute und das scharfe "S" in der TextBox (mit MultiLine = True) als Fragezeichen und die Zeilenumbrüche gar nicht angezeigt...

    Bin schon glaube ich ne dreiviertel Stunde oder so am Rödeln und kriegs nicht gebacken....

    Ich gehe jetzt mal davon aus, dass der gelieferte String in UTF-8 ist, weil...:

    XML-Quellcode

    1. <?xml version="1.0" encoding="utf-8"?>


    Jetzt hab ich das versucht zu konvertieren, aber das geht auch nicht:

    VB.NET-Quellcode

    1. Dim UTF8Bytes() As Byte = System.Text.Encoding.UTF8.GetBytes(Songdaten.Lyric) 'String als UTF-8 in Byte Array einlesen
    2. Dim UniCodeBytes() As Byte = Encoding.Convert(Encoding.UTF8, Encoding.Unicode, UTF8Bytes) 'Konvertieren des UTF-8 Byte Array in ein Unicode Byte Array
    3. TextBox3.Text = System.Text.Encoding.Unicode.GetString(UniCodeBytes) 'Konvertieren des Unicode Byte Arrays in einen String


    Vielleicht mit der String.Replace-Methode?

    Aber welche Argumente benutze ich da? Die Methode will ja entweder Strings oder Chars...
    Nee, nix ersetzen. Beim Import ist anzusetzen. Da muss irgendwo ein Encoding-Parameter/-Argument festgelegt werden.
    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.
    Keine Ahnung. Die eingehende Antwort scheinst Du ja zu verarbeiten. Du bekommst eine XML-Antwort? Ist da schon Murks drinne? Dann ist es da wohl schon zu spät.
    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.
    Dann musst Du Dir den Stringinhalt mal per Haltepunkt anschauen. Wird Microsoft.VisualBasic.vbCr oder Microsoft.VisualBasic.vbLf als Zeilentrennung verwendet, wird das in der TextBox nicht angezeigt, jedoch im notepad. Nur beides nacheinander sieht die TextBox als Zeilenumbruch an.
    Aber die Umlaute stimmen ja trotzdem nicht, oder?
    Bilder
    • Brüche.png

      26,83 kB, 1.357×483, 118 mal angesehen
    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.
    @VaporiZed

    Jou danke für den Tipp. Habs jetzt so gemacht: TextBox3.Text = TextBox3.Text.Replace(vbLf, Environment.NewLine) und geht...

    Ja und die Umlaute... Keine Ahnung was ich da noch versuchen soll...

    Das hier geht jedenfalls auch nicht:

    Using Ergebnis As System.IO.StreamReader = New System.IO.StreamReader(Lyrics, System.Text.Encoding.Default)

    Während ich rumprobiert habe, habe ich mal statt der Umlaute auch irgendwas so ähnlich wie E267 oder so bekommen, aber ich weiss einfach nicht mehr, wie ich das gemacht hab...
    Also, ich weiß nicht, was du machst, aber Umlaute sind kein Problem. Die werden mir in meiner Konsolenanwendung einwandfrei angezeigt. (Musst du dir nach VB.NET übersetzen. Ist ein Song von Mötley Crüe.)

    C#-Quellcode

    1. ​using System.Xml.Serialization;
    2. using HttpClient client = new();
    3. using Stream responseStream = await client.GetStreamAsync("http://api.chartlyrics.com/apiv1.asmx/GetLyric?lyricId=160639&lyricCheckSum=47f4a57836d16abe5a8ad6432dd971b5");
    4. XmlSerializer serializer = new(typeof(GetLyricResult));
    5. GetLyricResult? result = serializer.Deserialize(responseStream) as GetLyricResult;
    6. if (result is null)
    7. {
    8. return;
    9. }
    10. Console.WriteLine(result.LyricArtist);
    11. responseStream.Close();
    @ISliceUrPanties

    Okay haha auf die Idee muss man erstmal kommen, dass der werte Autor, der die Lyrics hochgeladen hat, irgendwelche falschen Zeichensätze benutzt hat...

    Habs mal bei ein paar anderen Liedern versucht und da geht es auch...

    Übrigens, die Query kannst du auch einfacher haben:

    "http://api.chartlyrics.com/apiv1.asmx/SearchLyricDirect?artist=" & "Mötley Crüe" & "&song=" & "Girls, Girls, Girls"

    kafffee schrieb:

    Using Ergebnis As System.IO.StreamReader = New System.IO.StreamReader(Lyrics, System.Text.Encoding.Default)
    Da steckt auch schon das falsche Encoding drin. Default=Ansi, UTF8 = UTF-8
    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.