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();
}

などのためKundenNrNachname、ファイルの最後にいくつかのクラスを作成しました。コードが多すぎないことを願っています。

まず、通常の右上の「×」ボタンを押しても反応がないので使えません。Exitというわけでボタンを作りました。

2番目:プログラムを終了するために終了ボタンを押すたびに、次の行にエラーが発生します:

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 ドキュメントには 1 つのルート要素が必要であるという規則を適用しています。

コードが何をしているのか正確にはわかりませんが、次のような XML を作成していると思われます。

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

...次のようにする必要があります。

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

つまり、ドキュメントに直接追加する要素を 1 つだけ作成し (これがルート要素になります)、その中に他のすべての要素を追加する必要があります。

于 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;
}

だから今あなたがすることは、あなたが今持っているダフのものを削除することだけです. ただし、潜在的な問題がいくつか見られます。変更があるかどうかにかかわらず、ファイルは書き込まれています。 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 に答える