C# XML LinQ

  • C#
  • .NET (FX) 4.5–4.8

Es gibt 19 Antworten in diesem Thema. Der letzte Beitrag () ist von mausekeks.

    Hallo Community,

    ich lerne momentan für meinen Beruf C# und erstelle momentan ein Projekt in welchem ich per XDocument <items> aus einer XML- Datei auslese.

    XML-Quellcode

    1. <TestItems>
    2. <item name="" id="1" type="">
    3. <vendor></vendor>
    4. <model></model>
    5. <power></power>
    6. </item>
    7. <item name="" id="2" type="">
    8. <vendor></vendor>
    9. <model></model>
    10. <power></power>
    11. </item>
    12. </TestItems>



    Das auslesen erfolgt in eine List<Item>itemList welche aus folgender Klasse generiert wird.

    C#-Quellcode

    1. public List<Item> itemList;
    2. public partial class Item
    3. {
    4. public string name { get; set; }
    5. public string type { get; set; }
    6. public int id { get; set; }
    7. public string vendor { get; set; }
    8. public string modell { get; set; }
    9. }


    Die methode dafür sieht dann so aus:

    C#-Quellcode

    1. itemList = new List<Item>(from s in doc.Root.Elements("item")
    2. select new Item
    3. {
    4. name = (string)s.Attribute("name").Value,
    5. type = (string)s.Attribute("type").Value,
    6. id = Convert.ToInt32(s.Attribute("id").Value),
    7. vendor = (string)s.Element("vendor"),
    8. modell = (string)s.Element("modell"),
    9. }).ToList();



    Die List ist als Databinding für eine Listbox mit DisplayMember "name" und Value Member "id" gesetzt
    wird ein element angeklickt werden r. o. Textboxen mit den restlichen daten aus item.* gefüllt.


    mein problem ist es das ich an dieses Bestehende konstrukt neue <item> hinzufügen und bestehende ändern möchte.

    Hat jemand evtl Tipps für mich :D

    Schonmal vielen Dank im Vorraus :)

    Mit freundlichen Grüßen Mausekeks
    Brain is Loading: 35%
    Auch wenn ich nicht so oft mit C# und XML-pur zu tun hab. Aber wenn Du die itemList hast, was hindert Dich daran zu schreiben:

    C#-Quellcode

    1. itemList.Add(new itemList());
    Ggf. noch nen Konstruktor rein, damit die Member gleich befüllt werden. Und dann später zum Bearbeiten des 1. Items:

    C#-Quellcode

    1. itemList[0].name = "Test";
    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.
    Danke für die schnelle Antwort.

    ich werde es gleich einmal ausprobieren.

    das einzige was mich daran hindert ist mein Kopf der momentan den Baum vor lauter Wald nicht sieht ^^
    ich bin noch ziemlich neu was c# und vorallem xml angeht und habe meine ausbildung erst vor kurzem begonnen .

    Lg

    Mausekeks
    Brain is Loading: 35%
    Gut danke das anlegen von neuen <Item> klappt schonmal soweit

    nun zu einem anderen thema und zwar dem Bearbeiten von elementen?

    wenn ich werte in der Liste manipuliere muss ich die geänderte Liste wieder zurück in das XML File schreiben, je mehr <item> aber hinzukommen desto unsinniger wird es jedesmal die gesamte liste neu in dasXML FIle zu schreiben.
    wie bekomme ich nun den geänderten Node aus meiner liste an stelle des Nodes in der XML Datei?

    Schonmal wieder vielen dank im Vorraus


    Mausekeks
    Brain is Loading: 35%
    Tja, eine XML-Datei ist nun mal keine Datenbank. Es bleibt Dir nichts übrig, als die gesamte Datei zu schreiben. Man könnte sich überlegen, wenn Du keine Datenbank benutzen willst oder kannst, für jedes Item eine eigene Datei anzulegen, dann wird der Schreibaufwand bei einer Änderung nicht so groß. Darum fragte ich ja, ob Du die XML-Datei vorgegeben hast oder ob Du diese nach Belieben erzeugen kannst.

    Auch eine gute Möglichkeit wäre, das gesamte Datenmodell als Dataset anzulegen. Hier wird Dir auch vom Framework her kräftig unter die Arme gegriffen, insbesondere was Änderungen angeht. Aber auch hier wird eine gesamte XML-artige Datei geschrieben.
    Die Unendlichkeit ist weit. Vor allem gegen Ende. ?(
    Manche Menschen sind gar nicht dumm. Sie haben nur Pech beim Denken. 8o
    Oke danke mal wieder für die fixe antwort,

    besteht die möglichkeit das <item> welches in der liste verändert wurde anhand des ID Attributs in der XML Datei zu ersetzen
    also nicht nur einzelne geänderte werte sondern immer den Gesamten <item> node?

    Ich weiss fragen über fragen, nur google gibt mir nicht das was ich will ^^
    und nein ich bin nicht zu doof ?( zu googlen ^^


    edit: Die idee mit einzelnen XML Files hatte ich auch schon und sogar schon zu 90% fertig, dann kam jemand mit der Vorgabe speicher das doch alles in Eine Datei.
    Wohl als herausforderung gemeint ?! ^^
    Brain is Loading: 35%

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

    Du hast immer noch nicht die Frage von @SpaceyX beantwortet.
    Ist der Aufbau der XML eine Vorgabe oder kannst Du dies selbst bestimmen?
    Wenn Du es selbst bestimmen kannst, nimm ein typ. Dataset, da kannst Du Laden und Speichern in 2 Zeilen Code!
    Änderungen machst Du direkt in den Controls an denen Du gebunden hast...
    "Hier könnte Ihre Werbung stehen..."
    Hier ein ganz ganz grundlegender Aufbau eines DataSets. Wie gesagt, bleibt es Dir auch hier nicht erspart, bei einer Änderung die gesamte Datei zu neu zu schreiben. Der Vorteil hier ist, dass Du durch DataBinding (im Video wird an ein DataGridView gebunden) enorm leistungsstarke Anwendungen erzeugen kannst und das mit einem minimalen Aufwand an Code. Spätestens wenn Du eine zweite, dritte, vierte Abbildung von Daten brauchst, die zueinander in Beziehung stehen, führt ohnehin kein Weg mehr an dieser Denkweise vorbei. Auch lässt sich die Datenquelle recht leicht austauschen. Will meinen, dass Du anstatt einer XML-Datei später evtl. eine Datenbank im Background hast. Verschwende nicht Deine Zeit und Energie mit dem Rumhantieren von "puren" XML-Dateien, sondern erarbeite Dir eine die richtige Denkweise, Deine Daten richtig abzubilden.

    Auch solltest Du Dir nicht zuviele Gedanken darüber machen, ob nun eine gesamte Datei geschrieben wird oder nicht, überlege, wann eine Sicherung nötig ist und lass den Rest vom Betriebssystem regeln. Festplatten sind dazu da, um Daten zu speichern. Ich habe schon mit Datasets gearbeitet, die 50k+ Einträge hatten und es war 0 Problem, das zu schreiben, bzw. zu lesen. Aber früher oder später wirst Du eh bei Datenbanken landen.

    Hier das besagte Video. Wirklich nur sehr rudimentär, aber als Einstieg sollte es Dir erstmal genügen.

    youtube.com/watch?v=qMPG8NluqfU&feature=youtu.be

    Du kannst die Daten auch an TextBoxen oder andere Controls binden. Das bleibt alleine Dir überlassen. Ich finde jedoch das DataGridView sehr angenehm.
    Die Unendlichkeit ist weit. Vor allem gegen Ende. ?(
    Manche Menschen sind gar nicht dumm. Sie haben nur Pech beim Denken. 8o

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

    Oh Gott,

    @SpaceyX vielen vielen dank für deine Hilfe und Mühe extra ein Video dafür zu machen.
    Es hat geholfen danke schön

    Ich habe ein Dataset erstellt und es in meiner form an eine Listbox gebunden die restlichen werte werden dann in Textboxen angezeigt.

    Einzige(hoffe ich zmd.) frage noch:

    wenn ich das Dataset in einer Form2 ändere wie aktualiesiere ich die daten in form1?


    Lg Mausekeks
    Brain is Loading: 35%
    Das ist eine passende Frage @ErfinderDesRades. Der hat dafür einige Hilfsklassen geschrieben, um das Problem zu bearbeiten. Das fiese an der Geschichte ist, dass jedes Formular seine eigene tDS-Instanz hat. Und damit seine eigenen Daten. Sehr kurz zusammengefasst: Du musst dafür sorgen, dass alle Formulare auf die selben Daten zugreifen. Die BindingSource-Property DataSource ist da eines der Anlaufziele. Die musst Du zu Beginn eines Formularaufrufs "umstöpseln", den BindingSources also das "richtige" tDS zuordnen. Eine Alternative (falls für Dich möglich; bei mir geht das oft, da ich nur eine tDS-DataTable-Zeile in einem Einstellungsdialog ändern will): Man erzeugt eine neue DataRow im Hauptformular und übergibt bei Erzeugung von Form2 diesem jene neue Row. Dann werden (natürlich) Änderungen in Form2 an jener Row auch im tDS des Hauptformulars übernommen. Wenn Du aber ein vollwertiges tDS in mehreren Forms brauchst, ist es - wie genannt - komplexer.
    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.
    Da meine C#-Kenntnisse nicht so dolle sind, hier in VB. Der Sinn dahinter dürfte aber klar sein:

    VB.NET-Quellcode

    1. Dim NewDataRow = DeinTds.DeineDataTable.NewDeineDataTableRow()
    2. Using DlgForProperties As New Form2
    3. DlgForProperties.SetDataRow(NewDataRow)
    4. If DlgForProperties.ShowDialog(Me) = DialogResult.OK Then DeinTds.DeineDataTable.AddDeineDataTableRow(NewDataRow)
    5. End Using

    In Form2 gibt es dann eben eine Sub namens SetDataRow, die diese NewDataRow in einer Form-internen Variable abspeichert und dann im weiteren Verlauf verändert. Sobald Form2 mit DialogResult.OK (ist Dir klar, wie das geht?) beendet wurde, wird die neue DataRow ins tDS des Hauptforms übernommen. Anderenfalls bei nächster Gelegenheit entsorgt.
    Man kann sich den Spaß mit SetDataRow auch sparen, indem man einen passenden Kostruktor für Form2 erzeugt, der als Parameter eine DataRow akzeptiert. Aber das ist Geschmackssache. Und eben nicht nach meinem.
    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.
    Oke danke,

    in C# wäre das dann in etwa:
    in Form1:

    C#-Quellcode

    1. //Variable NewItemsRow
    2. var NewDataRow = itemsDataSet.Items.NewItemsRow();

    und im Aufruf für Form2:

    C#-Quellcode

    1. Form2 frm = new Form2();
    2. frm.Show(this);
    3. frm.SetDataRow(NewDataRow);


    und in Fom2(frm):

    C#-Quellcode

    1. //lokale variable für die übergebene Row
    2. object Row;
    3. internal void SetDataRow(object newDataRow)
    4. {
    5. Row = newDataRow
    6. }


    Stimmt das in etwa so oder wäre ein anderer Datentyp von vorteil


    und auf deine Frage hin ob ich das mit dem DialogResult verstehe ist die Antwort in Kombination mit einer Form nein
    bei einem normalen OFD oder SFD schon wie implentiere ich das in eine Form?



    Danke für die Hilfe VaporiZed :love:

    LG
    Brain is Loading: 35%
    Oha. Das Ganze wird komplizierter, wenn Du mit .Show und nicht mit .ShowDialog() arbeitest, da bei letzterem nur 1 Fenster auftauchen kann (-> nur eine DataRow ist neu erstell- und bearbeitbar), jedoch bei .Show() niemand davon abgehalten wird, 20 Fenster gleichzeitig zu öffnen. Musst Du ausprobieren, ob das geht. Ein weiterer Vorteil bei ShowDialog ist: Man kann auswerten, wie das Dialog-Ergebnis ist. Und darauf reagieren, wie in meinem Beispielcode. Ohne ShowDialog ist das Ergebnis nicht auswertbar, da ja nicht gewartet wird, bis Form2 geschlossen wird, sondern das Hauptformular läuft ja weiter. Da müsstest Du (m.E.) kompliziert mit Events arbeiten und Form2 müsste so dem Hauptformular mitteilen, ob die neue DataRow akzeptiert werden soll oder nicht. Dazu dieser Thread von RfG.
    Der Datentyp muss ganz konkret sein. Nix mit Object. Sonst kannst Du ja gar nicht vernünftig typbasiert in Form2 arbeiten. Wie willst Du mit einem Object den Wert einer DataRow-Spalte festlegen. Benutze in Form2: itemsDataSet.ItemsRow Row;. Das ist ja ein projektbekannter Typ.
    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.
    Ja die Funktionsweise mit .ShowDialog() verstehe ich nun.
    und es funtioniert auch.

    auch mit dem Datentyp hast du natürlich Recht, macht natürlich sinn wenn es schon da ist ^^

    Die Variable NewDataRow muss per referenzverweis übergeben werden um später in form1 die werte aus form 2 zu bekommen oder täusche ichm ich da?
    Brain is Loading: 35%
    Nö. Ist ja kein Wertetyp wie int, sondern ein Referenztyp, da eine Klasse => Es ist wurscht, ob Du das so oder so übergibst. Geändert wird's immer.
    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.
    Oke also mein aufbau sieht jetzt aus wie folgt:

    Form1:

    C#-Quellcode

    1. ItemsDataSet.ItemsRow NewDataRow = itemsDataSet.Items.NewItemsRow();
    2. Form2 f = new Form2();
    3. f.SetDataRow(NewDataRow);
    4. if (f.ShowDialog(this) == DialogResult.OK)
    5. {
    6. itemsDataSet.Items.Rows.Add(NewDataRow);
    7. }


    und in Form2:

    C#-Quellcode

    1. ItemsDataSet.ItemsRow ItemRow;
    2. public void SetDataRow(ItemsDataSet.ItemsRow Row)
    3. {
    4. ItemRow = Row;
    5. }
    6. private void btnOk_Click(object sender, EventArgs e)
    7. {
    8. this.DialogResult = DialogResult.OK;
    9. }
    10. private void button1_Click(object sender, EventArgs e)
    11. {
    12. ItemRow.Type = textBox1.Text;
    13. ItemRow.Name = textBox2.Text;
    14. }



    Uuuuuund es funktioniert!!!!

    Vielen Vielen Dank an alle die hier fleißig gepostet Haben insbesondere an @SpaceyX und @VaporiZed ^^ :saint:


    Lg Mausekeks
    Brain is Loading: 35%