使用 XmlWriter 迭代构建 XML 文件

发布于 2024-10-09 17:30:41 字数 609 浏览 1 评论 0原文

我希望能够使用 XmlWriter(C#、.NET)创建 XML 文档,其中多次调用生成 XML 的方法,然后调用一次最终方法来关闭所有内容。当我尝试多次调用此方法时:

private void SiblingGenerator(List<XmlNode> XMLList, XmlWriter textWriter,
    string newPath, FileInfo fi)
{
    if (fi.Length == 0)
    {
        MessageBox.Show("file doesn't exist");

        textWriter.WriteStartDocument();
        textWriter.WriteStartElement("batch");
        //...
    }

    // ...
}

...它返回一个错误,指出 WriteStartDocument 需要是第一次调用

似乎对 textWriter 的调用实际上并未被写入,因为在每次后续调用中,文档都会重新开始。

谁能告诉我为什么会发生这种情况?

I want to be able to use XmlWriter (C#, .NET) to create an XML document with multiple calls to a method that generates XML and then a single call to a final method that closes everything off. When I try to call this method multiple times:

private void SiblingGenerator(List<XmlNode> XMLList, XmlWriter textWriter,
    string newPath, FileInfo fi)
{
    if (fi.Length == 0)
    {
        MessageBox.Show("file doesn't exist");

        textWriter.WriteStartDocument();
        textWriter.WriteStartElement("batch");
        //...
    }

    // ...
}

...it returns an error saying that WriteStartDocument needs to be the first call.

It seems like the calls to the textWriter aren't actually being written because on each subsequent call the document starts over again.

Can anyone tell me why this is happening?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

逆光下的微笑 2024-10-16 17:30:41

XmlWriter 只能转发,不能重复使用。您不应在此类的同一实例上多次调用 WriteStartDocument。因为它是方法的参数,所以调用者必须负责处理编写器的生命周期。

using (var writer = XmlWriter.Create("foo.xml"))
{
    SiblingGenerator(XMLList, writer, newPath, fi);
}

如果您需要多次重用 SiblingGenerator 函数,那么您可能需要外部化 WriteStartDocument 方法的调用:

using (var writer = XmlWriter.Create("foo.xml"))
{
    writer.WriteStartDocument();
    SiblingGenerator(XMLList, writer, newPath, fi);
    SiblingGenerator(XMLList, writer, newPath, fi);
    ...
    writer.WriteEndDocument();
}

A XmlWriter is forward only and cannot be reused. You shouldn't call WriteStartDocument multiple times on the same instance of this class. Because it is an argument of your method it is the caller that must take care of handling the life-cycle of the writer.

using (var writer = XmlWriter.Create("foo.xml"))
{
    SiblingGenerator(XMLList, writer, newPath, fi);
}

If you need to reuse the SiblingGenerator function multiple times then you might want to externalize the call of the WriteStartDocument method:

using (var writer = XmlWriter.Create("foo.xml"))
{
    writer.WriteStartDocument();
    SiblingGenerator(XMLList, writer, newPath, fi);
    SiblingGenerator(XMLList, writer, newPath, fi);
    ...
    writer.WriteEndDocument();
}
子栖 2024-10-16 17:30:41

任何类型的“编写器”对象(如 TextWriter、XmlWriter 等)都会进行某种程度的缓冲,就像完全不受其控制的底层流一样。换句话说,您不能依赖基础文件的长度来确定是否已对编写器进行了先前的调用。

但具体来说,有一个 Flush 方法System.IO 中的许多类(例如 Stream 和 TextWriter)都可用,它们可用于将缓冲内容推送到磁盘,但在我看来,这会导致代码非常脆弱。

您应该维护某种其他类型的状态来确定您是否已经编写了文档的开头。

Any kind of "writer" object like TextWriter, XmlWriter, etc do some level of buffering as does the underlying stream which is entirely out of its control. In other words, you can't rely on the length of the underlying file to determine whether or not prior calls to the writer have been made.

But specifically speaking, there is a Flush method available on many of the classes in System.IO such as Stream and TextWriter that can be used to push the buffered contents to disk but this makes for pretty fragile code, in my opinion.

You should maintain some other kind of state to determine whether or not you have already written the start of the document.

梦萦几度 2024-10-16 17:30:41

有几个因素会导致该方法无法发挥作用。 XmlWriter 可能不会直接将代码写入流,FileStream 可能不会直接将数据写入文件,并且 FileInfo 对象会缓存它是信息,因此您必须使其自行更新才能获取最新信息。

您可以只使用布尔变量来跟踪它是否是第一项,而不是使用 FileInfo 对象来检查这一点。

或者,只需在进入调用此方法的循环之前编写文档的开头即可。

There are several things that can keep that method from working. The XmlWriter might not write the code to the stream directly, the FileStream might not write the data to the file directly, and the FileInfo object caches it's information, so you would have to make it update itself to get information that is up to date.

Instead of using a FileInfo object to check for this, you could just use a boolean variable to keep track of whether it's the first item or not.

Alternatively, just write the start of the document before going into the loop that calls this method.

§普罗旺斯的薰衣草 2024-10-16 17:30:41

我猜想还有其他问题,该代码应该可以工作。您可能正在重用 XmlWriter。如果您在方法中本地声明 XmlWriter,您还会收到错误吗?

I would guess that something else is wrong, that code should work. You're probably reusing a XmlWriter. If you declare the XmlWriter locally in the method do you still get the error?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文