C# Projekt - XML-Daten einlesen, bearbeiten und speichern


Pantera

Grünschnabel
Hallo zusammen,

seit ein paar Tagen versuche ich mich an folgender Aufgabe:
Ich möchte meine Kanal Liste meines TV Tuners am PC bearbeiten!

Hierzu möchte ich eine XML Datei einlesen. Die XML Datei hat folgende Struktur:
Code:
<channels>
	<channel>
		<broadcast>None</broadcast>
		<diseqc>1</diseqc>
		<name>89 HIT FM</name>
		<polarisation>0</polarisation>
		<modulation>None</modulation>
		<selected>0</selected>
		<sys>5</sys>
		<scrambled>0</scrambled>
		<serviceid>12664</serviceid>
		<frequency>12633</frequency>
		<provider>MEDIA BROADCAST</provider>
		<symbolrate>22000</symbolrate>
		<position>-1</position>
	</channel>
...
</channels>
Der <channel> Tag wiederholt sich einige hundert mal. Ich möchte den Name des Senders <name> in einer Listbox ausgeben.

Jetzt soll es möglich sein aus dieser Listbox die gewünschten Sender auswählen und sie in eine 2 Listbox zu verschieben. Wenn ich alle gewünschten Sender in die Listbox2 übertragen habe, möchte ich diese wieder in dem selben Format als XML Datei speichern.

Ich habe folgendes Problem:
Wenn ich eine Listbox mit dem Inhalt des <name> Tags fülle, werden mir alle Sendernamen aufgelistet. Kopiere ich den Listeneintrag jetzt in Listbox2, beinhaltet Listbox2 nur den <name>Tag. Es fehlen alle weiteren Informationen (<position>,<frequency>,...)

Kennt Ihr eine Möglichkeit oder habt ihr eine Idee?
Ich habe hier meinen Code angefügt:


Code:
        //Datei öffnen
            OpenFileDialog openFileDialog1 = new OpenFileDialog();
            openFileDialog1.Filter = " XML Files|*.xml";

            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                XDocument xmldoc = XDocument.Load(openFileDialog1.FileName);
                var channels = (from i in xmldoc.Descendants("channel")
                                orderby i.Element("name").Value ascending
                                select new
                                {
                                    broadcast = i.Element("broadcast").Value,
                                    diseqc = i.Element("diseqc").Value,
                                    name = i.Element("name").Value,
                                    polarisation = i.Element("polarisation").Value,
                                    modulation = i.Element("modulation").Value,
                                    selected = i.Element("selected").Value,
                                    sys = i.Element("sys").Value,
                                    scrambled = i.Element("scrambled").Value,
                                    serviceid = i.Element("serviceid").Value,
                                    frequency = i.Element("frequency").Value,
                                    provider = i.Element("provider").Value,
                                    symbolrate = i.Element("symbolrate").Value,
                                    position = i.Element("position").Value,
                                }
                                ).ToList();
//Listbox1 zeigt jetzt den Namen der Sender
              listBox1.DataSource = channels;
              listBox1.DisplayMember = "name";
anschließend kopiere ich den "name" in Listfeld 2. Und genau hier verliere ich alle anderen Informationen die zu dem Sender dazugehören.

Ich bedanke mich für jede Hilfe ;)

MfG
Tobi
 

Turri

Erfahrenes Mitglied
Hallo,

willkommen im Forum. :)

Die schnelle Lösung wäre:
Du hast in deinem "var Channels" ja Sender drin samst Infos,
und jeder Sender kommt nur 1x vor, also der Name ist eindeutig.
Speicher dir diese Liste irgendwo in einer Klasse.
Aktuell hast du sie ja scheinbar nur kurz beim einlesen.

Und dann such in der "Channels-Liste" nach dem Sender den du in ListBox2 angeklickt hast, dann hast du ja wieder alle Infos.
 

Pantera

Grünschnabel
Hallo,

danke für die Antwort und die nette Begrüßung :)

Ich habe die Idee aufgegriffen und habe eine neue Variante getestet.

Im Ersten Schritt lade ich die XML Datei in ein DataSet.
Anschließend sage ich meiner Listbox1: Zeige mir die Spalte "name" an.
Jetzt kopiere ich die Datensätze in Listbox2.

Kann mir jemand helfen die Einträge aus Listbox2 wieder als DataSet zu speichern?
Anschließend möchte ich das DataSet in einer XML Datei speichern.

Hier mein Code:

Code:
private void ReadXmlButton_Click(object sender, EventArgs e)
        {
            AuthorsDataSet.Clear();
            string filePath = "C:/Users/tms/Dropbox/ReadingXML/authors.xml";
                        
            AuthorsDataSet.ReadXml(filePath);

            dataGridView1.DataSource = AuthorsDataSet;
            dataGridView1.DataMember = "channel";

            foreach (DataRow dr in AuthorsDataSet.Tables[0].Rows)
            {

                listBox1.Items.Add(dr["name"].ToString());
            }
                    
        }

private void button1_Click(object sender, EventArgs e)
        {
            var auswahlsender = listBox1.SelectedItem;
            listBox2.Items.Add(auswahlsender);
        }
Danke für jede Idee :)
 

Turri

Erfahrenes Mitglied
Hallo,

mir hat ja der XDocument Ansatz besser gefallen.

Kannst es dir im Anhang ja mal anschauen. :)
Diverse Fehlerbehandlung fehlt aber.

Es gibt im Ordner "Debug" eine "Channels.xml" mit meinem Beispiel.
Dort entsteht auch die Datei "Result.xml" die deinem Ergebnis entsprechen müsste.
 

Anhänge

Pantera

Grünschnabel
Hey,

erstmal super vielen Dank!
Das ist genau das was ich versucht habe zu erreichen :)

Ich versuche gerade noch einen OpenFileDialog und einen SaveFileDialog entsprechend zu implementieren. Ich weiß nur noch nicht wie ich das in den
Code:
AllSenders = XDocument.Load("Channels.xml");
einbauen kann :(
 

Pantera

Grünschnabel
kurzer Nachtrag:

der SaveFileDialog funktioniert jetzt. Allerdings habe ich immer noch Probleme den OpenFileDialog einzubinden.

Wenn mir jemand auf Basis der Datei von Turri eine Idee hat, bitte ich darum ;)

LG
 

Spyke

Premium-User
Machs denn Helfern leichter und zeigt denn Codeauschnitt mit deinem problem.
Hilf uns dir zu helfen, nicht alle haben lust irgendwelche dateien extra runterzuladen.
 

Pantera

Grünschnabel
Oh... Sorry stimmt!

Hier der Code:

Code:
private void button5_Click(object sender, EventArgs e)
        {
            /// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
            /// Sender in Listbox1 einfügen
            /// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
            AllSenders = XDocument.Load("Channels.xml");

            foreach (XElement elem in AllSenders.Element("channels").Elements())
            {
                if (elem.Name == "channel")
                {
                    listBox1.Items.Add(elem.Element("name").Value);
                }
            }
        }
 

Spyke

Premium-User
Und das problem genau ist?
Du musst das OpenFileDialog aufrufen und die Eigenschaft Filename abfragen

Ungefähr so (Code ungetestet ausm Gedächtnis heraus geschrieben):
Code:
using(OpenFileDialog dlg=new OpenFileDialog())
{
   dlg.Filter="XML Datei (*.xml)|*.xml";
   if(dlg.ShowDialog()==DialogResult.OK)
      TuWasMitDerDatei(dlg.FileName);
}
 

chmee

verstaubtes inventar
Premium-User
Das Thema an sich scheint ja geklärt zu sein. Ich hätte da einen simplen Ansatz, der mit den großen OOP- und XML-Read-Dingen weniger zu tun hat, aber quick und dirty ist.

Da Du mit den XML-Daten keine großen Dinge machst, ist das XML-konforme Einlesen ein bisschen Kanonen auf Spatzen..

(1) XML-Datei einlesen als string, nicht als XML-Objekt.
(2) Jeden Channel-Tag in eine eigene List<string> channelXML speichern.
(3) Dazu auch eine List<string> channelName für den Sendernamen anlegen.
* normales Array tät's auch, da ist die Verbindung über den index simpler
channelXML[1] <=> channelName[1]

(4) GUI arbeitet lediglich mit der channelName-List
(5) beim "Speichern" werden die Indizes der ausgewählten Sender genutzt, um die neue XML-Datei zu bauen, natürlich auf Basis der channelXML.

mfg chmee

(habe den Titel nachgebessert, er war so ..nichtssagend..)