2

我正在制定一个计划来管理我们公司的所有客户。我想使用 XML 文件来保存客户。所以我创建了一个 XML 文件(如果不存在)并用元素填充它。在这里你可以看到我是怎么做的:

string path = "C:\\Users\\Römel\\Desktop\\Save";
List<Kunde> kunde = new List<Kunde>();

private void Form1_Load(object sender, EventArgs e)
{
    XmlDocument xdocument = new XmlDocument();
    xdocument.Load(path + "\\save.xml");
    foreach (XmlNode xnode in xdocument.SelectNodes("Kundenverwaltung/Kunde"))
    {
        Kunde k = new Kunde();
        k.KundenNr = xnode.SelectSingleNode("KundenNr").InnerText;
        k.Nachname = xnode.SelectSingleNode("Nachname").InnerText;
        k.Vorname = xnode.SelectSingleNode("Vorname").InnerText;
        k.Adresse = xnode.SelectSingleNode("Adresse").InnerText;
        k.Ort = xnode.SelectSingleNode("Ort").InnerText;
        k.Telefon = xnode.SelectSingleNode("Telefon").InnerText;
        k.Mail = xnode.SelectSingleNode("Mail").InnerText;

        kunde.Add(k);
        listViewKunden.Items.Add(k.Nachname + " " + k.Vorname);
    }
}

private void btnAddCustomer_Click(object sender, EventArgs e)
{
    if(!Directory.Exists(path))
    {
        Directory.CreateDirectory(path);
    }

    if (!File.Exists(path + "\\save.xml"))
    {
        XmlTextWriter xwriter = new XmlTextWriter(path + "\\save.xml", Encoding.UTF8);
        xwriter.WriteStartElement("Kundenverwaltung");
        xwriter.WriteEndElement();
        xwriter.Close();
    }

    Kunde k = new Kunde();
    k.KundenNr = txtKundenNr.Text;
    k.Nachname = txtKundeNachname.Text;
    k.Vorname = txtKundeVorname.Text;
    k.Adresse = txtKundeAdresse.Text;
    k.Ort = txtKundeOrt.Text;
    k.Telefon = txtKundeTel.Text;
    k.Mail = txtKundeMail.Text;

    kunde.Add(k);
    listViewKunden.Items.Add(k.Nachname + " " + k.Vorname);

    txtKundenNr.Text = "";
    txtKundeNachname.Text = "";
    txtKundeVorname.Text = "";
    txtKundeAdresse.Text = "";
    txtKundeOrt.Text = "";
    txtKundeTel.Text = "";
    txtKundeMail.Text = "";
}

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
    XmlDocument xdoc = new XmlDocument();
    xdoc.Load(path + "\\save.xml");
    XmlNode xnode = xdoc.SelectSingleNode("Kundenverwaltung");
    xnode.RemoveAll();

    foreach (Kunde k in kunde)
    {
        XmlNode xtop = xdoc.CreateElement("Kunde");
        XmlNode xkundennr = xdoc.CreateElement("KundenNr");
        XmlNode xnachname = xdoc.CreateElement("Nachname");
        XmlNode xvorname = xdoc.CreateElement("Vorname");
        XmlNode xadresse = xdoc.CreateElement("Adresse");
        XmlNode xort = xdoc.CreateElement("Ort");
        XmlNode xtel = xdoc.CreateElement("Telefon");
        XmlNode xmail = xdoc.CreateElement("Mail");

        xkundennr.InnerText = k.KundenNr;
        xnachname.InnerText = k.Vorname;
        xvorname.InnerText = k.Nachname;
        xadresse.InnerText = k.Adresse;
        xort.InnerText = k.Ort;
        xtel.InnerText = k.Telefon;
        xmail.InnerText = k.Mail;

        xtop.AppendChild(xkundennr);
        xtop.AppendChild(xnachname);
        xtop.AppendChild(xvorname);
        xtop.AppendChild(xadresse);
        xtop.AppendChild(xort);
        xtop.AppendChild(xtel);
        xtop.AppendChild(xmail);

        xdoc.DocumentElement.AppendChild(xtop);
    }

    xdoc.Save(path + "\\save.xml");

    e.Cancel = false;
    this.Close();
}

对于KundenNr等,Nachname我在文件末尾创建了一些类。我希望这不是太多的代码。

第一:我不能使用右上角的常规“X”按钮,因为如果我点击它没有反应。所以我创建了一个Exit按钮。

第二:每次我点击退出按钮离开程序时,都会在这一行出现错误:

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
    xdoc.Load(path + "\\save.xml");
}

“缺少根元素”出现。有人知道这个错误并且可以给我一个提示吗?

编辑:因为btnExit_Click我使用此代码:

private void btnExit_Click(object sender, EventArgs e)
{
    this.Close();
}
4

2 回答 2

2

XmlDocument 强制执行有效 XML 文档必须有一个根元素的规则。

不确定您的代码到底在做什么,但我怀疑它正在创建可能如下所示的 XML:

<Kunde ... />
<Kunde ... />
<Kunde ... />
<Kunde ... />
<Kunde ... />

...它需要看起来像这样的地方:

<Kunden>
    <Kunde ... />
    <Kunde ... />
    <Kunde ... />
    <Kunde ... />
    <Kunde ... />
</Kunden>

换句话说,您需要创建一个且只有一个元素直接添加到文档中(这将成为您的根元素)并在其中添加所有其他元素。

于 2013-09-28T02:37:31.873 回答
1

您可以从一件事加载XmlDocument并将其保存到另一件事。这是内存中的表示。鉴于您正在尝试进行完全覆盖以尝试处理这是不必要的,这比创建根节点要多得多。

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
  XmlDocument xdoc = new XmlDocument();
  xdoc.LoadXml("<Kundenverwaltung"></Kundenverwaltung>"); // You might want to put any xml directives, default attributes, etc. in here.
  XmlNode xnode = xdoc.SelectSingleNode("Kundenverwaltung");
  foreach (Kunde k in kunde)
  {
     //Create and add each Kunde node as before
  }
  xdoc.Save(path + "\\save.xml");
  e.Cancel = false;
}

所以现在你要做的就是删除你现在拥有的 duff 。不过,我看到了一些潜在的问题。无论是否有任何更改,都在写入文件。 XmlDocument将所有内容保存在内存中,因此此解决方案仅适用于小型文档。如果这里的情况是这样的(怀疑某个时候有错误),你的文件就会被塞满,所有的数据都会丢失。您可能需要考虑类似上述内容,但将其保存到临时文档中。然后尝试加载或验证它,如果它恢复正常,则将其重命名以保存,否则报告问题。这样,至少只有这个“会话”更改丢失了。

一般来说,我从不调用 XmlDoument.Load("Fred.xml") 或保存。我做类似的事情。

XmlDocument doc = new XmlDocument();
using(FileStream rfs = new FileStream("OldFred.xml",FileMode.Open,FileAccess.Read))
{
   doc.Load(rfs);
   //do my reading stuff)
}
using(FileStream wfs = new FileStream("NewFred.xml",FileMode.Create,FileAccess.Write))
{
   //do my Writing stuff
   doc.Save(wfs);
}

使用 FileStream 的优点是,如果 Oldfred 不存在,或者您没有对 NewFred 所在文件夹的写入权限,您将立即失败。这是我们在处理对文件系统的并发和多用户访问时养成的习惯。这意味着 XmlDocument 读取和写入代码永远不必处理文件系统,处理 FileStreams 的代码会处理这些。

于 2013-09-28T09:29:15.777 回答