XML Klasse vereinfachen

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

Es gibt 7 Antworten in diesem Thema. Der letzte Beitrag () ist von DanCooper.

    XML Klasse vereinfachen

    Hallo

    gibt es eine Möglichkeit folgende XML Klasse zu vereinfachen:

    VB.NET-Quellcode

    1. <Serializable()>
    2. <XmlRoot("movie")>
    3. Public Class Movie
    4. <XMLElement("title")>
    5. Public Property Title As String
    6. <XMLElement("ratings")>
    7. Public Property Ratings As RatingContainer
    8. End Class
    9. <Serializable()>
    10. Public Class RatingContainer
    11. <XMLElement("rating")>
    12. Public Property Ratings As List(Of Rating)
    13. End Class
    14. <Serializable()>
    15. Public Class Rating
    16. <XMLElement("name")>
    17. Public Property Name As String
    18. <XMLElement("votes")>
    19. Public Property Votes As Integer
    20. End Class


    Das XML sieht so aus (und muss auch so bleiben):

    XML-Quellcode

    1. <movie>
    2. <title>Avatar</title>
    3. <ratings>
    4. <rating>
    5. <name>imdb</name>
    6. <votes>34245</votes>
    7. </rating>
    8. <rating>
    9. <name>tmdb</name>
    10. <votes>687654</votes>
    11. </rating>
    12. </ratings>
    13. </movie>



    Was mich nu stört ist die "Zwischenklasse" RatingContainer und dass ich nun zum Hinzufügen einer neuen Bewertung movie.Ratings.Rating.Add() nutzen muss. Ich hätte gerne einfach nur movie.Ratings.Add(). Das sollte irgendwie unkompliziert so möglich sein, dass die XML trotzdem so gelesen und geschrieben wird, oder?

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

    C#-Quellcode

    1. var xml =
    2. @"<movie>
    3. <title>Avatar</title>
    4. <ratings>
    5. <rating>
    6. <name>imdb</name>
    7. <votes>34245</votes>
    8. </rating>
    9. <rating>
    10. <name>tmdb</name>
    11. <votes>687654</votes>
    12. </rating>
    13. </ratings>
    14. </movie>";
    15. [Serializable]
    16. [XmlRoot("movie")]
    17. class Movie
    18. {
    19. [XmlElement("title")]
    20. public string Title { get; set; }
    21. [XmlElement("ratings")]
    22. public List<Rating> Ratings { get; set; }
    23. }
    24. [Serializable]
    25. class Rating
    26. {
    27. [XmlElement("name")]
    28. public string Name { get; set; }
    29. [XmlElement("votes")]
    30. public int Votes { get; set; }
    31. }


    Damit geht dann:

    C#-Quellcode

    1. new Movie().Ratings.Add(new Rating(..))

    DanCooper schrieb:

    Das XML sieht so aus (und muss auch so bleiben):
    Unmöglich.
    Die ist ungültig.
    Zeile 12 muss </ratings> heißen, sonst geht gar nichts.

    Dann müsste gehen

    VB.NET-Quellcode

    1. <Serializable()>
    2. Public Class Rating
    3. <XmlElement("name")>
    4. Public Property Name As String
    5. <XmlElement("votes")>
    6. Public Property Votes As String
    7. End Class
    8. <Serializable()>
    9. <XmlRoot("movie")>
    10. Public Class Movie
    11. <XmlElement("title")>
    12. Public Property Title As String
    13. <XmlElement("ratings")>
    14. Public Property Ratings As List (Of Rating)
    15. End Class

    Wenn du keinen Wert auf Pascal Case legst, müsste es noch einfacher gehen

    VB.NET-Quellcode

    1. <Serializable()>Public Class rating
    2. Public Property name As String
    3. Public Property votes As String
    4. End Class
    5. <Serializable()>Public Class movie
    6. Public Property title As String
    7. Public Property ratings As List (Of rating)
    8. End Class

    Alles ohne Gewähr, getestet habe ich es nicht.
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --

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

    @petaod Mit deinem und shads Code funktioniert die De-/Serialisierung aber nicht mehr, euer Code wäre für folgendes XML passend:

    XML-Quellcode

    1. <movie>
    2. <title>Avatar</title>
    3. <ratings>
    4. <name>imdb</name>
    5. <votes>34245</votes>
    6. </ratings>
    7. <ratings>
    8. <name>tmdb</name>
    9. <votes>687654</votes>
    10. </ratings>
    11. </movie>


    @DanCooper Dann füg der RatingContainer Klasse eine Add Methode hinzu:

    Quellcode

    1. public void Add(Rating rating)
    2. {
    3. if (this.Ratings == null)
    4. {
    5. this.Ratings = new List<Rating>();
    6. }
    7. this.Ratings.Add(rating)
    8. }
    @DanCooper So (gleiche Schreibweise für Property und ElementName), musst Du im Projekt mit dem Studio umbenennen:

    VB.NET-Quellcode

    1. <Serializable()>
    2. Public Class movie
    3. Public Property title As String
    4. Public Property ratings As RatingContainer
    5. End Class
    6. <Serializable()>
    7. Public Class RatingContainer
    8. Public Property rating As List(Of Rating)
    9. End Class
    10. <Serializable()>
    11. Public Class Rating
    12. Public Property name As String
    13. Public Property votes As Integer
    14. End Class

    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!
    @slice Tatsächlich, das habe ich gestern Abend übersehen.
    So geht es aber richtig (siehe Anhang):

    C#-Quellcode

    1. var xml =
    2. @"<movie>
    3. <title>Avatar</title>
    4. <ratings>
    5. <rating>
    6. <name>imdb</name>
    7. <votes>34245</votes>
    8. </rating>
    9. <rating>
    10. <name>tmdb</name>
    11. <votes>687654</votes>
    12. </rating>
    13. </ratings>
    14. </movie>";
    15. [Serializable]
    16. [XmlRoot("movie")]
    17. class Movie
    18. {
    19. [XmlElement("title")]
    20. public string Title { get; set; }
    21. [XmlArray("ratings")]
    22. [XmlArrayItem("rating", typeof(Rating))]
    23. public List<Rating> Ratings { get; set; }
    24. }
    25. [Serializable]
    26. class Rating
    27. {
    28. [XmlElement("name")]
    29. public string Name { get; set; }
    30. [XmlElement("votes")]
    31. public int Votes { get; set; }
    32. }
    33. var deserialized = new XmlSerializer(typeof(Movie)).Deserialize(new StringReader(xml));
    34. deserialized.Dump();
    35. var sw = new StringWriter();
    36. new XmlSerializer(typeof(Movie)).Serialize(sw, deserialized);
    37. sw.ToString().Dump();
    Bilder
    • output.png

      57,27 kB, 1.916×915, 61 mal angesehen

    petaod schrieb:

    Unmöglich.
    Die ist ungültig.
    Zeile 12 muss </ratings> heißen, sonst geht gar nichts.

    Du hast natürlich recht, war aber ein Schreibfehler ;)

    slice schrieb:

    @petaod Mit deinem und shads Code funktioniert die De-/Serialisierung aber nicht mehr, euer Code wäre für folgendes XML passend:

    XML-Quellcode

    1. <movie>
    2. <title>Avatar</title>
    3. <ratings>
    4. <name>imdb</name>
    5. <votes>34245</votes>
    6. </ratings>
    7. <ratings>
    8. <name>tmdb</name>
    9. <votes>687654</votes>
    10. </ratings>
    11. </movie>


    @DanCooper Dann füg der RatingContainer Klasse eine Add Methode hinzu:

    Quellcode

    1. public void Add(Rating rating)
    2. {
    3. if (this.Ratings == null)
    4. {
    5. this.Ratings = new List<Rating>();
    6. }
    7. this.Ratings.Add(rating)
    8. }

    Ja das würde so funktionieren, war aber nicht die Lösung, die ich gesucht habe.

    shad schrieb:

    So geht es aber richtig (siehe Anhang):

    Besten Dank, genau so wollte ich das!

    Edit: sieht in vb.NET nun so aus bei mir:

    VB.NET-Quellcode

    1. <XmlArray("ratings")>
    2. <XmlArrayItem("rating")>
    3. Public Property Ratings() As List(Of RatingDetails)

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