【问题标题】:XML persistence more than one item?XML 持久性不止一项?
【发布时间】:2012-12-05 13:38:48
【问题描述】:

嘿,我有以下代码将列表中的数据存储到 XML 文件中,但是当我将第二个项目添加到列表中时,它只会覆盖 XML 中的第一个项目,因此 XML 文件中只有一个项目, 我该如何解决这个问题

public class Visits
{
/*
 * This class represents a single appointment
 */

    private string Customer_Name;
    private string Customer_Address;
    private DateTime Arrival_Time;
    private string Visit_Type;
    private Double Lat1;
    private Double Long1;
    //Private methods. Note the use of DateTime to store arrival time

    public string name{
        //Description property
        set { Customer_Name = value; }
        get {return Customer_Name;}
    }

    public string address
    {//Time property
        set { Customer_Address = value; }
        get { return Customer_Address; }
    }

    public DateTime arrival
    {   //Duration property
        set { Arrival_Time = value; }
        get { return Arrival_Time; }
    }

    public string type
    {
        set { Visit_Type = value; }
        get { return Visit_Type; }
    }

    public Double Lat
    {
        //Description property
        set { Lat1 = value; }
        get { return Lat1; }
    }

    public Double Lon1
    {
        //Description property
        set { Long1 = value; }
        get { return Long1; }
    } 
    public override string ToString()
    {   //Return a String representing the object
        return Visit_Type + "     " + Customer_Name + " " + Customer_Address + " " + Arrival_Time.ToString() + " " + "Latitude  " + Lat1 + " " + "Longitude  " + Long1;
    }
}

}

然后是列表

class List
{
/*
 * This object represents the List. It has a 1:M relationship with the Visit class
 */

    private List<Visits> visits = new List<Visits>();
    //List object use to implement the relationshio with Visits

    public void addVisits(Visits vis)
    {
        //Add a new Visit to the List
        visits.Add(vis);
    }

    public List<String> listVisits()
    {//Generate a list of String objects, each one of which represents a Visit in List.

        List<String> listVisits = new List<string>();
        //This list object will be populated with Strings representing the Visits in the lists

        foreach (Visits vis in visits)
        {
            String visAsString = vis.ToString();
            //Get a string representing the current visit object

            listVisits.Add(visAsString);
            //Add the visit object to the List
        }

        return listVisits;
        //Return the list of strings
    }

    public Visits getVisits(int index)
    {
        //Return the visit object at the <index> place in the list

        int count = 0;
        foreach (Visits vis in visits)
        {
            //Go through all the visit objects
            if (index == count)
                //If we're at the correct point in the list...
                return vis;
            //exit this method and return the current visit
            count++;
            //Keep counting
        }
        return null;
        //Return null if an index was entered that could not be found
    }
}

}

然后添加代码

            thePickup.name = txtCustName.Text;
            thePickup.address = txtCustAddress.Text;
            thePickup.arrival = DateTime.Parse(txtArrival.Text);
            thePickup.Dname = txtDeliveryName.Text;
            thePickup.Daddress = txtDaddress.Text;
            thePickup.Lat = Double.Parse(txtLat.Text);
            thePickup.Lon1 = Double.Parse(txtLong.Text);
            thePickup.type = "Pickup";
            //Update thePickup object to reflect any changes made by the user

            XmlSerializer SerializerObj = new XmlSerializer(typeof(Pickups));

        using (TextWriter WriteFileStream = new StreamWriter(@"Pickup.xml", true))
        {
            SerializerObj.Serialize(WriteFileStream, thePickup);
        }

当我添加一个新条目时它只是改变了原始条目的格式

【问题讨论】:

  • 是文件被覆盖的问题,还是多个节点同名,被覆盖的问题?
  • @MarcelloGrechiLins 问题是,例如,我访问了详细信息 1、1、1、1、1 等,然后我添加了一个新的详细信息为 2、2、2、 2 等当我打开 XML 它只有 2,2,2,2,2 等,它应该同时显示
  • 所以问题是两者都有。 @Valtasarlll 的答案将解决每次创建 StreamWriter 时 StreamWritter 覆盖文件的问题。我的答案将帮助您避免创建具有相同名称的节点,从而相互覆盖。检查两个答案,我希望有帮助
  • @MarcelloGrechiLins 谢谢,我会看两个,我会尝试让 Valtasarllll 回答工作,然后我会看你的

标签: c# xml serialization xml-serialization


【解决方案1】:

您应该尝试使用XPath 支持的库来处理 XML 组装和创建。

当您使用 C# 时,我会推荐 HtmlAgilityPack 来处理“解析”的事情。

为了构建 XML,here 是学习如何使用 XPath 构建 XML 的好资源。

您还可以使用 C# 中的本机 XMLDocument 类,如果您之前在没有任何解析逻辑的情况下构建它,可能会更有用。

看看here

XPath 示例:

这是一个 XPath 示例,可帮助您避免覆盖 XML 文件中的实际节点。

CreateTag("//NODE1/NODE2", "TAG_NAME", tagContent);


    private void CreateTag(string xPath, string tag, string tagContent)
    {
        XmlNode node = _xml.SelectSingleNode(xPath);
        XmlElement element = _xml.CreateElement(tag);

        element.InnerText = tagContent;
        node.AppendChild(element);
    }

如果您的集合有多个同名节点:

CreateTag("//SINTEGRA//SEARCH//RECORDS//RECORD[last()]", kv.Key, kv.Value);

last() 是由大多数 .dll 实现的 XPath 方法,它将索引返回到最后一个节点 + 1,以便在最后一个创建的节点之后插入您的节点

【讨论】:

    【解决方案2】:

    不要序列化单个元素而是列表:

     List<Pickups> list = new List<Pickups>();
    
     foreach ( var pickup in ... )
        list.Add( pickup );
    
     ...
     XmlSerializer SerializerObj = new XmlSerializer(typeof(List<Pickups>));
    
     TextWriter WriteFileStream = new StreamWriter(@"Pickups.xml");
     SerializerObj.Serialize( WriteFileStream, list );
    

    【讨论】:

      【解决方案3】:

      试试这个:

      using(TextWriter WriteFileStream = new StreamWriter(@"Pickups.xml", true))
      {
          SerializerObj.Serialize(WriteFileStream, thePickup);
      }
      

      改为。

      boolean true参数表示StreamWriter将append下一个写入块到现有文件,而不是覆盖它

      否则,您的代码每次都会覆盖 Pickups.xml 文件。并且不要忘记关闭 WriteFileStream 对象。

      我试图重现你的情况:

      
          public class Pickups
          {
              public string name { get; set; }
              public string address { get; set; }
              public string Dname { get; set; }
              public string Daddress { get; set; }
              public string type { get; set; }
              public DateTime arrival { get; set; }
              public DateTime Lat { get; set; }
              public DateTime Lon1 { get; set; }
          }
      
      
      class Program
      {
      
      
          static void Main()
          {
              Pickups thePickup = new Pickups();
              thePickup.name = "nameProp";
              thePickup.address = "addressProp";
              thePickup.arrival = DateTime.Now;
              thePickup.Dname = "txtDeliveryName";
              thePickup.Daddress = "txtDaddress";
              thePickup.Lat = DateTime.Now;
              thePickup.Lon1 = DateTime.Now;
              thePickup.type = "Pickup";
              //Update thePickup object to reflect any changes made by the user
      
              XmlSerializer SerializerObj = new XmlSerializer(typeof(Pickups));
      
              using (TextWriter WriteFileStream = new StreamWriter(@"Pickups.xml", true))
              {
                  SerializerObj.Serialize(WriteFileStream, thePickup);
              }
      
              Pickups thePickup1 = new Pickups();
              thePickup1.name = "nameProp2";
              thePickup1.address = "addressProp2";
              thePickup1.arrival = DateTime.Now;
              thePickup1.Dname = "txtDeliveryName2";
              thePickup1.Daddress = "txtDaddress2";
              thePickup1.Lat = DateTime.Now;
              thePickup1.Lon1 = DateTime.Now;
              thePickup1.type = "Pickup2";
      
              using (TextWriter WriteFileStream = new StreamWriter(@"Pickups.xml", true))
              {
                  SerializerObj.Serialize(WriteFileStream, thePickup1);
              }
          }
      
      }
      

      Pickups.xml 文件中,我得到了预期的结果(2 个实体):

      <?xml version="1.0" encoding="utf-8"?>
      <Pickups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <name>nameProp</name>
        <address>addressProp</address>
        <Dname>txtDeliveryName</Dname>
        <Daddress>txtDaddress</Daddress>
        <type>Pickup</type>
        <arrival>2012-12-05T15:30:37.809487+01:00</arrival>
        <Lat>2012-12-05T15:30:37.810487+01:00</Lat>
        <Lon1>2012-12-05T15:30:37.810487+01:00</Lon1>
      </Pickups><?xml version="1.0" encoding="utf-8"?>
      <Pickups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <name>nameProp2</name>
        <address>addressProp2</address>
        <Dname>txtDeliveryName2</Dname>
        <Daddress>txtDaddress2</Daddress>
        <type>Pickup2</type>
        <arrival>2012-12-05T15:30:37.989487+01:00</arrival>
        <Lat>2012-12-05T15:30:37.989487+01:00</Lat>
        <Lon1>2012-12-05T15:30:37.989487+01:00</Lon1>
      </Pickups>
      

      您确定已修复程序的所有部分吗?也许您从代码的不同位置写入同一个文件?

      【讨论】:

      • @Valtasarlll 这似乎是一个好方法,但是当我这样做时,它不起作用,由于某种原因,当我添加一个新的时,它所做的只是改变布局第一个,或者什么都没有,有什么想法吗?
      • @TAM 尝试在写入后关闭 WriteFileStream 对象(就像在编辑版本中一样),无论如何这是必要的。否则,此解决方案应该可以工作。
      • @Valtasarllll 它仍然无法正常工作我将在帖子中编辑代码以显示我现在拥有的内容,以及 XML 文件在做什么
      • @TAM 我试图重现您的案例,它对我有用。检查编辑的答案。
      • @Valtasarlll 谢谢,它仍然没有发生在我身上,我不知道为什么,但感谢您尝试提供帮助。可以看到的唯一区别是我的没有 thePickup 和 thePickup1,因为每次通过文本框内容将它添加到列表中
      猜你喜欢
      • 1970-01-01
      • 2012-10-22
      • 1970-01-01
      • 2017-01-15
      • 1970-01-01
      • 2013-06-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多