RSS XML Datei in DataTable einlesen

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

Es gibt 11 Antworten in diesem Thema. Der letzte Beitrag () ist von John422.

    RSS XML Datei in DataTable einlesen

    Hallo,

    ich bekomem ich RSS Dokument mit nur einem Chanel und möchte den Inhalt in eine DataTable laden. Die XML Datei füge ich exemplarisch an.

    Ich habe folgenden Code gefunden

    VB.NET-Quellcode

    1. Dim rssdoc As New XmlDocument()
    2. rssDoc.Load(Me.txtFilePath.Text)
    3. Dim rssitems As XmlNodeList = rssDoc.SelectNodes("rss/channel/item")
    4. Dim i As Integer = 0
    5. Dim dt As DataTable = New DataTable("table")
    6. dt.Columns.Add("title", Type.GetType("system.string"))
    7. dt.Columns.Add("link", Type.GetType("system.string"))
    8. While i < rssItems.Count
    9. Dim node As XmlNode = rssItems.Item(i).SelectSingleNode("title")
    10. Dim title As String
    11. Dim link As String
    12. If node IsNot Nothing Then
    13. title = node.InnerText
    14. Else
    15. title = ""
    16. End If
    17. node = rssItems.Item(i).SelectSingleNode("link")
    18. If node IsNot Nothing Then
    19. link = node.InnerText
    20. Else
    21. link = ""
    22. End If
    23. Dim dr As DataRow = dt.NewRow()
    24. dr("title") = title
    25. dr("link") = link
    26. dt.Rows.Add(dr)
    27. i += 1
    28. End While
    29. Me.dgv.DataSource = dt


    Funktioneirt zwar aber ich finde das unelegant, weil man sich um jede Spalte namentlich per Hand kümmern muß. Hat jemand von Euch einen schöneren Ansatz?

    Viele Grüße

    John
    Dateien
    • test.xml

      (941 Byte, 54 mal heruntergeladen, zuletzt: )

    John422 schrieb:

    weil man sich um jede Spalte namentlich per Hand kümmern muß.
    Das ist wohl grundsätzlich erstmal so.
    Xml kann beliebige Datenstrukturen modellieren, und DataTable kann auch beliebige Datenstrukturen modellieren.
    Will man das eine ins andere überführen, muss man iwas programmieren, was Elemente des einen auf Elemente des anderen abbildet.

    Man kann sich auch was generisches basteln, aber das funzt dann nur im Rahmen gewisser Konventionen, und failt, sobald eine Xml-Datei auftritt, die anders strukturiert ist.

    Aber deinen Code kann man trotzdem stark vereinfachen:

    VB.NET-Quellcode

    1. Private Function LoadXml(rssdoc As XmlDocument) As DataTable
    2. Dim dt As DataTable = New DataTable("table")
    3. dt.Columns.Add("title", GetType(String))
    4. dt.Columns.Add("link", GetType(String))
    5. For Each xItm As XmlElement In rssdoc.SelectNodes("rss/channel/item")
    6. Dim dr As DataRow = dt.NewRow()
    7. dr("title") = If(xItm.SelectSingleNode("title")?.InnerText, "")
    8. dr("link") = If(xItm.SelectSingleNode("link")?.InnerText, "")
    9. dt.Rows.Add(dr)
    10. Next
    11. Return dt
    12. End Function
    Vielen Dank, @ErfinderDesRades das machts schonmal einfacher

    Jetzt möchte ich nur noch meine Spalten in eine Liste schreiben und den Code dadurch noch etwas abkürzen, weil es doch viele Spalten werden. Leider kracht das hier in Zeile 19. Kannst Du mir erklären, wieso?

    Fehler: "Namespace-Manager oder 'XsltContext' erforderlich. Diese Abfrage hat einen Präfix, eine Variable oder eine benutzerdefinierte Funktion."



    VB.NET-Quellcode

    1. Dim lstCols As New List(Of String)
    2. lstCols.Add("g:id")
    3. lstCols.Add("title")
    4. lstCols.Add("link")
    5. Dim rssDoc As New XmlDocument()
    6. rssDoc.Load(Me.txtFilePath.Text)
    7. Dim dt As DataTable = New DataTable("table")
    8. For Each sCol In lstCols
    9. dt.Columns.Add(sCol, Type.GetType("System.String"))
    10. Next
    11. For Each xItm As XmlElement In rssDoc.SelectNodes("rss/channel/item")
    12. Dim dr As DataRow = dt.NewRow()
    13. For Each sCol In lstCols
    14. dr(sCol) = If(xItm.SelectSingleNode(sCol)?.InnerText, "")
    15. Next
    16. dt.Rows.Add(dr)
    17. Next
    18. Me.dgv.DataSource = dt

    da hamwas schon:

    ErfinderDesRades schrieb:

    failt, sobald eine Xml-Datei auftritt, die anders strukturiert ist.


    hängt wohl mit zeile #2 zusammen: lstCols.Add("g:id") g bezeichnet wohl einen xml-Namespace, alias xmlns.
    Sagt der Fehler ja auch: ein Namespace-Manager sei erfordelich.
    Aber prüf mal den Wert von sCol, wenn der Fehler auftritt - obs da wirdklich um g:id geht.

    John422 schrieb:

    Kannst Du mir erklären, wieso?
    Das wird mir zu mühsam, weil mit xml umzugehen, was xmlns' enthält, ist eine Wissenschaft für sich.

    Man muss iwie das xDoc erweitern, dessen Namespace-Table befüllen und so Kram.
    Ziemlich nervig.
    Ja, es liegt am g:id
    Ich habe jetzt einen Namespace-Manager hinzu gefügt. Kein Fehler mehr aber leider eine leere Spalte g:id im Ergebnis.

    VB.NET-Quellcode

    1. Dim rssdoc As New XmlDocument()
    2. rssdoc.Load(Me.txtFilePath.Text)
    3. Dim rssitems As XmlNodeList = rssdoc.SelectNodes("rss/channel/item")
    4. Dim nsmgr As New XmlNamespaceManager(rssdoc.NameTable)
    5. nsmgr.AddNamespace("g", "")
    6. Dim dt As DataTable = New DataTable("table")
    7. dt.Columns.Add("g:id", GetType(String))
    8. dt.Columns.Add("title", GetType(String))
    9. dt.Columns.Add("link", GetType(String))
    10. For Each xItm As XmlElement In rssdoc.SelectNodes("rss/channel/item")
    11. Dim dr As DataRow = dt.NewRow()
    12. dr("g:id") = If(xItm.SelectSingleNode("//g:id", nsmgr)?.InnerText, "")
    13. dr("title") = If(xItm.SelectSingleNode("title")?.InnerText, "")
    14. dr("link") = If(xItm.SelectSingleNode("link")?.InnerText, "")
    15. dt.Rows.Add(dr)
    16. Next
    17. Me.dgv.DataSource = dt
    Hallo,
    warum die Xml-Datei manuell einlesen, wenn das .NET Framework Klassen zur Verfügung stellt, um mit Atom- und RSS-Dateien zu arbeiten?
    Hier mal ein Beispiel für deine bereitgestellte Datei

    C#-Quellcode

    1. ​using System;
    2. using System.ServiceModel.Syndication;
    3. using System.Xml;
    4. using XmlReader reader = XmlReader.Create(@"D:\Temp\test.xml");
    5. SyndicationFeed feed = SyndicationFeed.Load(reader);
    6. foreach (var item in feed.Items)
    7. {
    8. // Elemente mit Custom Namespace auslesen
    9. foreach (var extension in item.ElementExtensions)
    10. {
    11. Console.WriteLine(extension.GetObject<string>());
    12. }
    13. Console.WriteLine(item.Title.Text);
    14. }
    @ISliceUrPanties vielen Dank für Deinen Ansatz, das sieht sehr gut aus.

    leider hat meine XML Datei noch zwei Probleme, bei denen ich nicht weiter kommen

    1. <pubDate>Fri, 03 Sep 2021 10:20:41 CEST</pubDate> - der XML Reader stört sich an der Zeitzone, die bei mir als CEST enthalten ist
    2. Da gibts noch Unterelemte, die ich im ersten Beispiel der Einfachheit weg gelassen habe und die mit extension.GetObject<string>() einen Fehler werfen

    Ich habe hier ein erweitertes Beispiel angefügt. Hast Du dafür eine Idee?
    Dateien
    • test2.xml

      (1,29 kB, 43 mal heruntergeladen, zuletzt: )
    Hallo,
    zu deinem 1. Problem habe ich folgendes gefunden: docs.microsoft.com/en-us/troub…formatter-throw-exception .
    Zu der zweiten Frage. Wenn du keine Strings erwartest, kannst du GetObject auch sagen, dass du z.B. ein XmlElement erwartest.

    C#-Quellcode

    1. foreach (var extension in item.ElementExtensions)
    2. {
    3. var customElement = extension.GetObject<XmlElement>();
    4. // ... Xml Unterelemente selbst auslesen.
    5. foreach (XmlNode childNode in customElement.ChildNodes)
    6. {
    7. Console.WriteLine($"name: {childNode.Name} - innerText: {childNode.InnerText}");
    8. }
    9. }