0

I am trying to change values inside XML file. This is my XML "person.xml" file:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<Table>
  <Person>
    <Number>1</Number>
    <Name>Mariano</Name>
    <Last Name>Italiano</Last Name>
    <Age>36</Age>
  </Person>
  <Person>
    <Number>2</Number>
    <Name>John</Name>
    <Last Name>Smith</Last Name>
    <Age>32</Age>
  </Person>
  <Person>
    <Number>3</Number>
    <Name>Bob</Name>
    <Last Name>Leckie</Last Name>
    <Age>50</Age>
  </Person>
  <Person>
    <Number>4</Number>
    <Name>Patrick</Name>
    <Last Name>Collins</Last Name>
    <Age>63</Age>
  </Person>
</Table>

And i want my program to do some things:

  1. Find a name written in textBox2->Text. Then if the name exists i want to change it to name written in textBox3->Text.

  2. Remove (if found) whole Person if CheckBoxDelete is set to true

I know how to create such a XML file (found an example somewhere) but i can't find a solution how to find and remove if neccessary.

I am using Visual Studio 2015 if it matters.

Thank You.

Mariusz
  • 45
  • 1
  • 10
  • Here's some sample to select the node: https://www.csharp-examples.net/xml-nodes-by-name/ and here to delete it: https://stackoverflow.com/questions/919645/how-to-delete-node-from-xml-file-using-c-sharp – mrbitzilla May 24 '20 at 18:07
  • 1
    you can read about linq to xml, by using [**XDocument**](https://learn.microsoft.com/en-us/dotnet/api/system.xml.linq.xdocument?view=netcore-3.1), try this or @RolandoMedina proposition and we will help you by including some code. – Mohammed Sajid May 24 '20 at 18:09
  • It is impossible to "delete" a record in a file directly, but you can obviously read the whole document into memory, deserialize it, modify it and then serialize it again as XML. As already mentioned: XDocument, LINQ and XMLReader will help you with that. – SkryptX May 24 '20 at 18:25

3 Answers3

1

You can use XDocument to replace the value and delete the person according to the Name.

Code:

 public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }
    public string filename = "D:\\test.xml";
    private void BtnRePlace_Click(object sender, EventArgs e)
    {
        XDocument doc = XDocument.Load(filename);
        doc.Descendants("Person").Descendants("Name").Where(i => i.Value == txtReplaceFirstName.Text).FirstOrDefault().SetValue(txtReplaceLastName.Text);
        doc.Save(filename);
    }

    private void btndelete_Click(object sender, EventArgs e)
    {
        XDocument doc = XDocument.Load(filename);
        doc.Descendants("Person").Where(i => i.Element("Name").Value == txtReplaceFirstName.Text&& i.Element("LastName").Value == txtReplaceLastName.Text).FirstOrDefault().Remove();
        doc.Save(filename);
    }
}

Besides, your xml file have an error, the Last Name should be LastName without space.

Jack J Jun
  • 5,633
  • 1
  • 9
  • 27
  • I am trying to modify your code of btndelete_Click so if there would be two persons with same FirstName but different LastName it would delete only one. How to achieve that? Data used to delete are stored in textBoxReplaceFirstName and textBoxReplaceLastName – Mariusz May 30 '20 at 20:06
  • @Mariusz, I have modified my code for it, you can check if it works for you. – Jack J Jun Jun 01 '20 at 01:44
0

You could map (i.e. deserialize) the data to POCO objects, manipulate the data and serialize again. Might be a bit overkill though. As others stated, using XDocument might be good enough.

Here is a minimal example:

public class Person
{
    [XmlElement]
    public int Number { get; set; }
    [XmlElement]
    public string Name { get; set; }
    [XmlElement]
    public string LastName { get; set; }
    [XmlElement]
    public int Age { get; set; }
    public override string ToString() => $"{Name} {LastName} is {Age}";
}

[XmlRoot("Table")]
public class RootObject
{
    [XmlElement("Person")]
    public List<Person> Persons;
}

class Program
{
    static void Main(string[] args)
    {
        var xmlSer = new XmlSerializer(typeof(RootObject));
        using var fs = new FileStream("input.xml", FileMode.Open);
        var doc = (RootObject)xmlSer.Deserialize(fs);

        foreach (var p in doc.Persons)
        {
            System.Console.WriteLine(p);
        }
        // do whatever with the RootObject instance            
    }
}
flipflop
  • 93
  • 4
0

XML is the object, so consider re-using existing objects before creating more POCOs.

Here's code that shows how to find, delete, and update elements in XML. Take some time to learn XPath, it's very powerful, flexible, and available across nearly every platform.

using System;
using System.Threading.Tasks;
using System.Xml;

namespace testconsole
{
        class Program
        {
                public static string strFileName = "c:\\temp\\test.xml";
                static void Main(string[] args) {
                        XmlDocument xml = new XmlDocument();
                        xml.Load(strFileName);

                        string strMatchName = "Mariano";
                        string strXPath = "/Table/Person[Name='" + strMatchName + "']";
                        XmlElement ndPerson = (XmlElement)xml.SelectSingleNode(strXPath);

                        if (ndPerson != null) {
                            // Delete if the person is found
                            ndPerson.ParentNode.RemoveChild(ndPerson);
                        }

                        string strNewName = "Bob";
                        strXPath = "/Table/Person/Name[.='" + strNewName + "']";
                        XmlElement ndName = (XmlElement)xml.SelectSingleNode(strXPath);
                        if (ndName != null) {
                            ndName.InnerText = "Robert"; // new name
                        }

                        xml.Save(strFileName);
                }
        }
}
William Walseth
  • 2,803
  • 1
  • 23
  • 25