winforms 在XMLNode上创建/删除元素c#

mlnl4t2r  于 2022-11-17  发布在  C#
关注(0)|答案(2)|浏览(152)

这是我第一次使用XML,我使用的基本XML文件格式如下:

<root>
  <staff id="1">
    <name>name 1</name>
    <phone>123456</phone>
  </staff>
  <staff id="2">
    <name>name 2</name>
    <phone>123789</phone>
    <phone2>123789</phone2>
  </staff>
</root>

一些节点有更多的元素(在本例中为phone2)。我想在节点上添加(或删除)一个元素。我正在用C#创建一个使用此XML的WinForms。我正在做:

  • 我读取XML以获得XmlNodeList变量。
  • 从XmlNodeList中获取要修改为XmlNode变量的节点。
  • 我在XmlNode上修改姓名或电话
  • 我再次读取XML文件,并使用XmlNode变量new info更新正确的节点。

我的问题是我不知道如何在XmlNode变量上添加(或删除)元素“phone2”。
program.cs:

public static XmlNode staff;
public static XmlNodeList xnList = GetList();

        public static XmlNodeList GetList()
        {
            XmlNodeList xnList;

            XmlDocument doc = new XmlDocument();
            doc.Load(path);
            xnList = doc.SelectNodes("/root/staff");

            return xnList;
        }

        public static void GetID(string id)
        {
            foreach (XmlNode xn in xnList)
            {
                if(xn.Attributes["id"].Value == id)
                {
                    staff = xn;
                }
            }
        }

form1.cs

private void btnOK_Click(object sender, EventArgs e)
{
   Program.staff["name"].InnerText = textBoxName.Text;
   Program.staff["phone"].InnerText = textBoxPhone.Text;
   
   if (Program.staff.SelectSingleNode("phone2") == null)
   {
      // here I want to create "phone2" in Program.staff if not exist
      // to update XML file later.

      Program.staff["phone2"].InnerText = textBoxPhone2.Text;
   }

}

我没有找到正确的方法来做这件事,也许这不是最好的方法,但我接受建议...

7eumitmz

7eumitmz1#

处理XML文件有多种方法,下面我将介绍两种方法。

测试.xml

<root>
  <staff id="1">
    <name>Name 1</name>
    <phone>123456</phone>
  </staff>
  <staff id="2">
    <name>Name 2</name>
    <phone>123457</phone>
    <phone>123458</phone>
  </staff>
</root>

选项1(LINQ到XML):

使用指令添加以下内容:

  • using System.Xml.Linq;
    创建XmlLinq
private void CreateXmlLinq(string filename)
{
    XElement root = new XElement("root",
                        new XElement("staff", new XAttribute("id", "1"),
                            new XElement("name", "Name 1"),
                            new XElement("phone", "123456")),

                        new XElement("staff", new XAttribute("id", "2"),
                            new XElement("name", "Name 2"),
                            new XElement("phone", "123457"),
                            new XElement("phone", "123458"))
                        );

    root.Save(filename);
}

用法

using (SaveFileDialog sfd = new SaveFileDialog())
{
    sfd.Filter = "XML File (*.xml)|*.xml";
    sfd.FileName = "Test.xml";

    if (sfd.ShowDialog() == DialogResult.OK)
    {
        //save to file
        CreateXmlLinq(sfd.FileName);
        Debug.WriteLine($"Info: Saved to {sfd.FileName}");
    }
}

要删除staff id = 2的电话号码123458,请执行以下操作:

删除电话

private void RemovePhone(string filename, string id, string phoneNumber)
{
    //load from file
    XElement root = XElement.Load(filename);

    //remove specified phone number
    root.Elements("staff").Where(s => s.Attribute("id").Value == id).Elements("phone").Where(p => p.Value == phoneNumber).Remove();

    //save to file
    root.Save(filename);
}

选项2(XML序列化):

对于这种方法,我们将使用嵌套类。

将以下using指令添加到每个类

  • using System.Collections.Generic;
  • using System.Xml;
  • using System.Xml.Serialization;

你可以随意命名类,我选择在前面加上“Xml”这个词。另外,对于嵌套类,我选择附加祖先的名字。在这个例子中,只有一个祖先(父)“root”。

  • XML根目录
  • XmlRootStaff文件夹:(“XmlRoot”+“员工”)
    XML根目录.cs
[XmlRoot(ElementName = "root", IsNullable = false)]
public class XmlRoot
{
    [XmlElement(ElementName = "staff")]
    public List<XmlRootStaff> Staff { get; set; } = new List<XmlRootStaff>();
}

XML根工作人员.cs

public class XmlRootStaff
{
    [XmlAttribute(AttributeName = "id")]
    public string Id { get; set; }

    [XmlElement(ElementName = "name")]
    public string Name { get; set; }

    [XmlElement(ElementName = "phone")]
    public List<string> Phone { get; set; } = new List<string>();
}

要反序列化XML(从文件中读取),我们将使用以下方法:

将XML文件反序列化为对象

public static T DeserializeXMLFileToObject<T>(string xmlFilename)
{
    T rObject = default(T);

    try
    {
        if (string.IsNullOrEmpty(xmlFilename))
        {
            return default(T);
        }

        using (System.IO.StreamReader xmlStream = new System.IO.StreamReader(xmlFilename))
        {
            System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(T));
            rObject = (T)serializer.Deserialize(xmlStream);
        }
    }
    catch (Exception ex)
    {
        System.Diagnostics.Debug.WriteLine(ex.Message);
        throw ex;
    }

    return rObject;
}

用法(反序列化):

private XmlRoot _root = null;
             ...

using (OpenFileDialog ofd = new OpenFileDialog())
{
    ofd.Filter = "XML File (*.xml)|*.xml";
    ofd.FileName = "Test.xml";

    if (ofd.ShowDialog() == DialogResult.OK)
    {
        //deserialize
        _root = HelperXml.DeserializeXMLFileToObject<XmlRoot>(ofd.FileName);
    }
}

要序列化XML(写入文件),我们将使用以下方法:

将对象序列化为XML文件

public static void SerializeObjectToXMLFile(object obj, string xmlFilename)
{
    try
    {
        if (string.IsNullOrEmpty(xmlFilename))
        {
            return;
        }//if

        System.Xml.XmlWriterSettings settings = new System.Xml.XmlWriterSettings();
        settings.OmitXmlDeclaration = false;
        settings.Indent = true;
        settings.NewLineHandling = System.Xml.NewLineHandling.Entitize;

        using (System.Xml.XmlWriter xmlWriter = System.Xml.XmlWriter.Create(xmlFilename, settings))
        {
            //specify namespaces
            System.Xml.Serialization.XmlSerializerNamespaces ns = new System.Xml.Serialization.XmlSerializerNamespaces();
            ns.Add(string.Empty, "urn:none");

            //create new instance
            System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(obj.GetType());

            //write XML to file
            serializer.Serialize(xmlWriter, obj, ns);

        }
    }
    catch (Exception ex)
    {
        System.Diagnostics.Debug.WriteLine(ex.Message);
        throw ex;
    }
}

用法(序列化):

private XmlRoot _root = null;
                     ...

using (SaveFileDialog sfd = new SaveFileDialog())
{
    sfd.Filter = "XML File (*.xml)|*.xml";
    sfd.FileName = "Test.xml";

    if (sfd.ShowDialog() == DialogResult.OK)
    {
        //create new instance
        _root = new XmlRoot();

       //add data
       _root.Staff.Add(new XmlRootStaff() { Id = "1", Name = "Name 1", Phone = new List<string>() { "123456" } });
       _root.Staff.Add(new XmlRootStaff() { Id = "2", Name = "Name 2", Phone = new List<string>() { "123457", "123458" } });

        //serialize - save to file
        SerializeObjectToXMLFile(_root, sfd.FileName);
        Debug.WriteLine($"Info: Saved to {sfd.FileName}");
    }
}

要删除staff id = 2的电话号码123458,请执行以下操作:

private void RemovePhone(string id, string phoneNumber)
{
    if (_root != null)
    {
        for (int i = 0; i < _root.Staff.Count; i++)
        {
            if (_root.Staff[i].Id == id)
            {
                //remove
                _root.Staff[i].Phone.Remove(phoneNumber);
                break;
            }
        }
    }
}

资源

sauutmhj

sauutmhj2#

最后我解开了变化:
program.cs

public static XmlDocument doc = new XmlDocument(); // ADDED THIS HERE
public static XmlNode staff;
public static XmlNodeList xnList = GetList();

        public static XmlNodeList GetList()
        {
            XmlNodeList xnList;
            // REMOVED XmlDocument from HERE
            doc.Load(path);
            xnList = doc.SelectNodes("/root/staff");

            return xnList;
        }

        public static void GetID(string id)
        {
            foreach (XmlNode xn in xnList)
            {
                if(xn.Attributes["id"].Value == id)
                {
                    staff = xn;
                }
            }
        }

form1.cs

private void btnOK_Click(object sender, EventArgs e)
{
   Program.staff["name"].InnerText = textBoxName.Text;
   Program.staff["phone"].InnerText = textBoxPhone.Text;
   
   if (Program.staff.SelectSingleNode("phone2") == null)
   {
       XmlElement elem = Program.doc.CreateElement("phone2");
       elem.InnerText = textBoxPhone2.Text;

       Program.staff.AppendChild(elem);
   }
}

相关问题