C# XMLDocument:缺少根元素

C# XMLDocument:缺少根元素,c#,xml,C#,Xml,我正在制定一个计划来管理我们公司的所有客户。我想使用一个XML文件来保存客户。因此,我创建了一个XML文件(如果不存在的话)并用元素填充它。在这里你可以看到我是如何做到的: string path = "C:\\Users\\Römel\\Desktop\\Save"; List<Kunde> kunde = new List<Kunde>(); private void Form1_Load(object sender, EventArgs e) { XmlD

我正在制定一个计划来管理我们公司的所有客户。我想使用一个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();
}
“根元素丢失”出现。有人知道这个错误并能给我一个提示吗

编辑:对于
btnExit\u,单击
I使用此代码:

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

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

不确定您的代码到底在做什么,但我怀疑它正在创建XML,它可能看起来像:

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

。。。它需要看起来像:

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


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

您可以从一个对象加载
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;
}

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

为什么在表单关闭时要加载数据?你不想保存它吗?是的,但我必须先加载它。在那之后,我会保存它。请参见
表单1\u FormClosing
:)末尾的
.Save
),或者我完全错了吗?啊,我在看你的代码片段,它显示了异常的位置,而不是完整的代码。加载时,
save.xml
中有什么内容?用记事本加载xml,我怀疑在某个时候文件已被填满,而您没有根节点。在加载文件、擦除所有子文件并重写它们时,为什么不每次创建一个新文件呢?Mh,
save.xml
是空的。所以每次我用
file.create创建一个新文件时,我必须编辑xml并手动添加一个根元素?有没有办法在没有任何错误的情况下快速地包装根元素?当然,您可以通过编程来完成。只是不确定您所编写的代码是否符合要求。基本上,当您创建一个新的XmlDocument时,您需要创建一个XmlElement作为您的“根”,并将其添加到XmlDocument中。然后,在创建内容的XmlElements时,将它们添加到“根”XmlElement中(或其下),而不是直接添加到XmlDocument本身。顺便说一句我开始使用XmlDocument,但最终改用XDocument(LINQXML)。如果你正在为.NET 4或更高版本开发,你也应该考虑切换——写起来要容易得多。好的,我想我要写另一个程序来测试它,然后我会用它:谢谢YouPS,如果你想用XMLReald/XMLMeX处理大文档,你可以有两个文件。如果我是你,我会考虑使用FielestRAMs而不是Load并用字符串保存,这样你就可以知道文件系统问题,而不是仅仅将字符串传递给XMLDoice。加载、保存和交叉手指。使用
FileStream
是否完全是另一种方式?我必须告诉你:你是老板!非常感谢!它工作得很好!一个问题:使用
XmlDocument
,最多200个客户是否太多了?不应该这么认为。特别是考虑到它是一次点击加载和一次保存。只需注意文档的大小。FileStream只是一个小小的改进。例如,除非你已经阻止了它,否则如果你的两个应用程序同时运行并关闭,会发生什么?
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;
}
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);
}