Autor |
Beitrag |
Bl!tz
      
Beiträge: 22
|
Verfasst: Do 19.07.12 08:02
Hi,
bin ganz neu hier in der Entwickler-Ecke und auch relativ neu bei C# und .NET und wollte mich erstmal kurz vorstellen. Ich bin Student (Elektro- und Informationstechnik) und im Moment in einem Urlaubssemester.
aber jetzt zu meinem Problem.
ich habe folgende XML:
XML-Daten 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <worker> <type> <name>workertype 1</name> <rate>75</rate> </type> <type> <name>workertype 2</name> <rate>83</rate> </type> </worker> |
Diese XML lad ich in eine Winforms-Combobox was auch schon funktioniert. Jetzt möchte ich aber anhand dessen was ich in der Combobox auswähle, also entweder workertype 1 oder workertype 2 (ich habe nicht die ganze XML gepostet, es kommen also noch viel mehr workertype's) die jeweilige rate in eine Variable speichern um mit diesem Wert dann zu rechnen.
das ist mein bisheriger Ansatz:
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30:
| private void comboWorkerType_SelectedIndexChanged(object sender, EventArgs e) { string worker = comboWorkerType.SelectedItem.ToString(); string subsidiary = comboSubsidiaryTravel.SelectedItem.ToString(); string path = @"C:\Users\Bl!tz\Documents\Visual Studio 2010\Projects\MBG.SimpleWizard\Demo\bin\Debug\Subsidiaries.xml";
switch (subsidiary) { case "GH": path = @"C:\Users\Bl!tz\Downloads\MBG.SimpleWizard\Demo\bin\Debug\GHworkerType.xml"; break; default: break; } XmlTextReader reader = new XmlTextReader(path);
while (reader.Read()) { if (reader.NodeType == XmlNodeType.Text) { if (reader.Value == worker) { reader.ReadToNextSibling("rate"); string name = reader.Value; MessageBox.Show(name); } } } } |
aber das funktioniert so nicht. ich möchte also, sobald reader.Value == worker ist, zum nächsten Element (rate) springen und diesen Wert dann abspeichern.
Der Inhalt bzw. die XML mit der ich comboWorkerType befülle hängt davon ab was ich in comboSubsidiaryTravel auswähle.
wie kann ich das denn am besten umsetzen?
vielen dank schon mal für alle antworten.
Mfg
Bl!tz
Moderiert von Th69: XML-Tags hinzugefügt
Moderiert von Th69: C#-Tags hinzugefügt
|
|
Th69
      

Beiträge: 4798
Erhaltene Danke: 1059
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Do 19.07.12 10:03
Hallo Bl!tz
da du dich bei reader.Value == worker innerhalb eines Tags befindet, gibt es dazu dann keinen "Sibling", sondern du müßtest erst noch ein Element weiterlesen ( Reader.Read).
Generell ist jedoch das händische Einlesen ("Parsen") einer XML-Datei nicht sinnvoll, sondern man sollte den Weg über die Serialisierung gehen, s. Mit XmlSerializer Objekte als XML speichern und laden.
Und dann ist mir noch aufgefallen, daß du absolute Pfade im Code vermeiden solltest. Nimm stattdessen
C#-Quelltext 1:
| string path = Path.Combine(Application.StartupPath, "Subsidiaries.xml"); |
P.S. Bitte füge demnächst selber die XML- bzw. C#-Tags ein (unter "Bereiche"), danke.
Zuletzt bearbeitet von Th69 am Do 19.07.12 12:10, insgesamt 1-mal bearbeitet
|
|
Bl!tz 
      
Beiträge: 22
|
Verfasst: Do 19.07.12 10:55
na das nenn ich mal ne flotte antwort.
vielen dank für den hinweis mit den Pfaden.
hab mir dein Beispiel mal angesehen aber es nicht ganz durchblickt.
Serialisieren heißt das die XML genommen wird und eingelesen wird? wohin wird die dann eingelesen und wie kann ich so darauf zugreifen wie ich es in meinem Fall brauche?
Deserialisieren heißt das vorhandene Daten genommen werden und in eine XML gepackt werden?
sehe ich das richtig?
mfg
Bl!tz
|
|
mats74
      
Beiträge: 189
Erhaltene Danke: 26
Win 10
VS 2017/19, C++, C#
|
Verfasst: Do 19.07.12 11:50
Hallo Bl!tz
Die XML-Serialisierung kannst Du hier nachlesen.
Und Beispiele gibt es hier eine ganze Menge.
MSDN sei dank 
_________________ Gruss
mats74
|
|
Bl!tz 
      
Beiträge: 22
|
Verfasst: Do 19.07.12 14:16
hab mir die ganzen Beispiel mal angeschaut und hab mal n bisschen versucht was zu stande zu bekommen:
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9:
| private void Serialize(string path) { Stream eingabe = File.OpenRead("GHworkerType.xml"); XmlSerializer serial = new XmlSerializer(eingabe); XmlText xml = (XmlText)serial.Deserialize(eingabe); eingabe.Close();
} |
aber das funktioniert so nicht ganz. ich weiss auch nicht wirklich was ich vom Xmlserializer zurück bekomme wenn ich diese XML deserialisiere. Im moment hab ich einfach angenommen das es vom Typ Xmltext ist aber das funktioniert auch nicht.
hab noch n paar verständnis schwierigkeiten.
mfg
Bl!tz
Edit:
ich hab jetzt einiges gelesen über die Serialisierung und Deserialisierung aber irgendwie ist das so wie ich es verstehe nicht das richtige für mich. aber ich lass mich natürlich eines besseren belehren.
so wie ich das sehe ist Serialisierung der Vorgang ein Objekt in eine XML zu packen.
Die Deserialiseriung ist das ganze umgekehrt, aber meine XML wurde ja nicht von einem Objekt erstellt bzw. enthält ja kein objekt.
ich muss ja bei Deserialiserung eine Typecast machen der in den beispielen die ich gesehen habe war das immer eine Klasse bzw. ein Objekt.
ich bin jetzt komplett verwirrt
|
|
mats74
      
Beiträge: 189
Erhaltene Danke: 26
Win 10
VS 2017/19, C++, C#
|
Verfasst: Do 19.07.12 16:19
Hallo Bl!tz
Ich habe aus meinem Link ein kleines Beispiel zur Serialisierung von XMLElement herausgenommen:
C#-Quelltext 1: 2: 3: 4: 5: 6:
| XmlSerializer ser = new XmlSerializer(typeof(XmlElement)); XmlElement myElement = new XmlDocument().CreateElement("MyElement", "ns"); myElement.InnerText = "Hello World"; TextWriter writer = new StreamWriter(@"C:\Temp\Hallo.xml"); ser.Serialize(writer, myElement); writer.Close(); |
Dieser Code erzeugt Dir eine XML- Datei mit dem entsprechenden Inhalt.
Natürlich kannst Du den Weg auch wieder zurück gehen und den Dateiinhalt deserialisieren und in Deinen Code zurückholen.
Ob Du diese Technik für Deine Zwecke einsetzen willst, musst Du natürlich selbst entscheiden.
_________________ Gruss
mats74
|
|
Bl!tz 
      
Beiträge: 22
|
Verfasst: Do 19.07.12 16:46
das wurde mir ja von Th69 empfohlen, das so zu machen.
wenn ich so den einen Wert, passend zu dem was ich in meiner comboWorkerType ausgewählt habe, in eine Variable speichern kann, dann würde ich es gerne so machen.
ich bin nur total verwirrt weil ich überall gelesen habe das wenn es um serialisieren/deserialisieren geht, ich immer ein Objekt habe.
das habe ich aber nicht. meine XML ist ja eine selbstverfasste XML-Datei und kein Objekt.
|
|
Th69
      

Beiträge: 4798
Erhaltene Danke: 1059
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Do 19.07.12 16:49
Hallo mats74,
ein XmlElement zu serialisieren, erscheint mir ja doch etwas sehr eigenartig
Und nun zu Bl!tz:
genau das ist der Sinn der Serialisierung, d.h. man erzeugt sich selber eine Klasse und arbeitet dann intern in seinem Programm nur noch damit (und die Persistierung ist dann unabhängig davon, also ob Text-Datei, XML-Datei, Datenbank, ...).
Die Klasse würde bei dir ja einfach so aussehen:
C#-Quelltext 1: 2: 3: 4: 5:
| public class WorkerType { public string Name { get; set; } public int Rate { get; set; } } |
Und dies würde man dann in eine List<WorkerType> stecken und im Programm dann nur noch damit arbeiten:
C#-Quelltext 1: 2:
| XmlSerializer serializer = new XmlSerializer(typeof(List<WorkerType>)); List<WorkerType> workerTypes = (List<WorkerType>)serializer.Deserialize(eingabe); |
Wenn die XML-Datei jedoch schon von extern gegeben ist, so muß man dem Serializer einige Attribute mitgeben, damit dieser die Datei richtig erkennt, s. Steuern der XML-Serialisierung mit Attributen
Ich weiß, das erscheint für einen zuerst ziemlich viel Aufwand zu sein, aber wenn man den Dreh einmal raus hat, dann kommt man gar nicht (bzw. kaum) mehr auf die Idee eine XML-Datei händisch parsen zu wollen 
|
|
Bl!tz 
      
Beiträge: 22
|
Verfasst: Do 19.07.12 17:51
ich hab jetzt folgenden Code in meinem UserControl wo die Comboboxen sind:
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9:
| public static List<workerType> Serialize(string path) { Stream eingabe = File.OpenRead(path); XmlSerializer serial = new XmlSerializer(typeof(List<workerType>)); List<workerType> workerTypes = (List<workerType>)serial.Deserialize(eingabe);
return workerTypes;
} |
und die Klasse workerType zum Serialisieren/Deserialisieren hab ich so erstellt wie du es geschrieben hast.
jetzt kommt dieser Fehler:
InvalidOperationException wurde nicht behandelt: Fehler im XML-Dokument (2,2)
ich denke mal dass der Fehler daher kommt das ich dem Serializer erst noch diese Attribute geben muss (die ich mir jetzt dann erst noch durchlesen muss).
Ist das richtig?
mfg
Bl!tz
|
|
Bl!tz 
      
Beiträge: 22
|
Verfasst: Fr 20.07.12 09:14
ich hab jetzt ziemlich viel versucht aber bin bis jetzt noch auf keinen grünen zweig gekommen.
so sieht mein Code im moment aus:
hier die zu serialisierende klasse:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33:
| using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Xml.Serialization;
namespace Demo { [XmlRoot("worker")]
public class workerType { private double[] element_list; private string[] string_list;
public workerType() { }
[XmlArrayItem("name", typeof(string))] public string[] strList { get { return string_list; } set { string_list = value; } } [XmlArrayItem("rate", typeof(double))] [XmlArray("type")] public double[] List { get { return element_list; } set { element_list = value; } } } } |
und hier die Methode aus dem UserControl mit den Combobxen:
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9:
| public static List<workerType> Serialize(string path) { Stream eingabe = File.OpenRead(path); XmlSerializer serial = new XmlSerializer(typeof(List<workerType>)); List<workerType> workerTypes = (List<workerType>)serial.Deserialize(eingabe); return workerTypes;
} |
wenn ich das ausführe bekomme ich diese Meldung:
System.InvalidOperationException wurde nicht behandelt.
Message=Fehler im XML-Dokument (2,2).
ich denke mal das es an den Attirbuten liegt die ich in der klasse workerType gesetzt habe. aber ich hab google die letzten 2 stunden bemüht und hab keine Lösung gefunden.
|
|
Th69
      

Beiträge: 4798
Erhaltene Danke: 1059
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Fr 20.07.12 10:46
Hallo Bl!tz,
das beste ist, du spielst ersteinmal ein bißchen mit dem Serializer rum (bevor du den Deserializer benutzt).
Benutze als Ausgangsbasis meine WorkerType-Klasse und laß dir eine Liste davon aus einem Testprogramm heraus mal als XML-Datei ausgeben:
C#-Quelltext 1: 2: 3: 4: 5: 6: 7:
| List<WorkerType> workerTypes = new List<WorkerType>();
workerTypes.Add(new WorkerType { Name = "workertype 1", Rate = 75 }); workerTypes.Add(new WorkerType { Name = "workertype 2", Rate = 83 });
|
Und dann schau dir die erzeugte XML-Datei mal an. Und nun kannst du noch ein bißchen mit den XML-Attributen spielen (um die erzeugte XML-Datei zu verändern).
Erst wenn du dies gemacht (und verstanden  ) hast, dann lies die Datei wieder mit dem Deserializer ein.
|
|
Bl!tz 
      
Beiträge: 22
|
Verfasst: Fr 20.07.12 13:05
hab jetzt n bisschen rumprobiert und war recht erfolgreich
hier meine Methode:
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| public static void Serialize(string path) { List<workerType> workerTypes = new List<workerType>(); List<workerType> workerOut = new List<workerType>();
workerType wt = new workerType(); Stream serialStream = new FileStream("serialtest.xml", FileMode.Create);
workerTypes.Add(new workerType { Name = "type 1", Rate = 75 }); workerTypes.Add(new workerType { Name = "type 2", Rate = 83 });
XmlSerializer serial = new XmlSerializer(workerTypes.GetType());
serial.Serialize(serialStream, workerTypes);
} |
das ist die klasse
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18:
| using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Xml.Serialization;
namespace Demo { [XmlRoot(ElementName = "type")] public class workerType { [XmlElement("name")] public string Name { get; set; }
[XmlElement("rate")] public double Rate { get; set; } } } |
und das ist das Ergebnis
XML-Daten 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| <?xml version="1.0"?> <ArrayOfWorkerType xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <workerType> <name>type 1</name> <rate>75</rate> </workerType> <workerType> <name>type 2</name> <rate>83</rate> </workerType> </ArrayOfWorkerType> |
was bezwecke ich den mit dieser Zeile: [XmlRoot(ElementName = "type")]? bei mir ändert sich an der XML nämlich nichts.
jetzt hab ich mich mal am Deserialisieren probiert:
C#-Quelltext 1:
| serial.Deserialize(serialStream); |
diese Zeile hab ich einfach in meiner Methode von oben ganz unten angehängt. Jetzt weiss ich aber nicht wie ich auf das Deserialisierte Konstrukt zugreifen kann.
danke schonmal soweit. hat mich schon um einiges weiter gebracht.
UPDATE:
hab die XML jetzt auch erfolgreich in eine List deserialisiert. Hier meine komplette Methode:
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21:
| public static void GetRate(string path, int index) { List<workerType> workerTypes = new List<workerType>(); List<workerType> workerOut = new List<workerType>();
workerType wt = new workerType(); Stream serialStream = new FileStream("serialtest.xml", FileMode.Create); workerTypes.Add(new workerType { Name = "type 1", Rate = 75 }); workerTypes.Add(new workerType { Name = "type 2", Rate = 83 });
XmlSerializer serial = new XmlSerializer(workerTypes.GetType());
serial.Serialize(serialStream, workerTypes); serialStream.Close(); Stream reader = new FileStream("serialtest.xml", FileMode.Open); workerOut = (List<workerType>)serial.Deserialize(reader); double rate = workerOut[index].Rate; MessageBox.Show(rate.ToString());
} |
aber mit dem Deserialisieren MEINER EIGENEN XML komm ich nicht klar. Diese Attribute und ich sind noch keine Freunde geworden.
Kannst du mir vielleicht nochmal auf die Sprünge helfen?
|
|
Bl!tz 
      
Beiträge: 22
|
Verfasst: Mo 23.07.12 08:59
hi,
ich hab mich jetzt gebeugt und den weg des geringsten widerstands genommen
ich hab jetzt einfach meine XML so angepasst, dass der deserialisierer was damit anfangen kann.
aber vielen vielen dank für die hilfe. hat mich enorm weiter gebracht.
auf zum nächsten Problem
mfg
Bl!tz
|
|