如何递归使用XmlWriter?

时间:2012-12-05 15:35:20

标签: c# .net

我的代码在使用XmlWriter时崩溃,说它被另一个进程使用。

    private void generateXml(Control receivedControl)
    {
        foreach (Control subCtrl in receivedControl.Controls)
        {
            using (XmlWriter writer = XmlWriter.Create("C:\\ui.xml"))
            {
                writer.WriteStartElement(subCtrl.Name);
                generateXml(subCtrl);
                writer.WriteEndElement();
            }
        }
    }

    private void button2_Click(object sender, EventArgs e)
    {
        foreach (Control c in this.Controls)
        {
            generateXml(c);
        }
    }

这是我调试的错误:

  

其他信息:该进程无法访问文件' C:\ ui.xml'因为它正被另一个进程使用。

编辑:非常感谢你,我设法让递归工作,但它只写了xml文件中的最后一个对象,有人知道为什么吗?这是更新后的代码:

    private void generateXml(XmlWriter receivedWriter, Control receivedControl)
    {
        receivedWriter.WriteStartElement(receivedControl.Name);
        foreach (Control subCtrl in receivedControl.Controls)
        {
            generateXml(receivedWriter, subCtrl);
        }
        receivedWriter.WriteEndElement();
    }
    private void button2_Click(object sender, EventArgs e)
    {
        foreach (Control c in this.Controls)
        {
            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Indent = true;

            using(XmlWriter writer = XmlWriter.Create("c:\\ui.xml", settings))
            {
                writer.WriteStartDocument();
                writer.WriteStartElement("Form");
                generateXml(writer, c);
                writer.WriteEndElement();
                writer.WriteEndDocument();
            }
        }
    }

3 个答案:

答案 0 :(得分:3)

XmlWriter访问时的文件将被锁定,因此后续尝试读取它会导致错误。

您可以更改函数以将编写器作为参数传递,从而拥有一个副本并希望避免此问题。

private void generateXml(XmlWriter writer, Control receivedControl)
{
    foreach (Control subCtrl in receivedControl.Controls)
    {
            writer.WriteStartElement(subCtrl.Name);
            generateXml(writer, subCtrl);
            writer.WriteEndElement();
    }
}

private void button2_Click(object sender, EventArgs e)
{
    using (XmlWriter writer = XmlWriter.Create("C:\\ui.xml"))
    {
        writer.WriteStartDocument();
        writer.WriteStartElement(this.Name); // This is the document element
        foreach (Control c in this.Controls)
        {
            generateXml(writer, c);
        }
        writer.WriteEndDocument(); // Close any open tags
    }
}

以上是一个样本 - 未经测试。

编辑:已更新以包含根元素

答案 1 :(得分:0)

那是因为您一次打开了XmlWriter writer的多个实例。

你应该做的是,将你的using语句放在递归函数之外,然后将XmlWriter传递给

using (XmlWriter writer = XmlWriter.Create("C:\\ui.xml"))
{
    generateXml(c, writer);

答案 2 :(得分:0)

您还可以使用共享写访问权限的文件

        using (var f = new FileStream("C:\\ui.xml",      FileMode.Append,FileAccess.Write,FileShare.Write))
            {
                using (XmlWriter writer = XmlWriter.Create(f))                 
                {
                    writer.WriteStartElement(subCtrl.Name);
                    generateXml(subCtrl);
                    writer.WriteEndElement();
                }
            }