如何将XElement写入已包含内容的XmlWriter

本文关键字:包含内 XmlWriter XElement | 更新日期: 2024-10-24 09:34:07

我正在尝试以流式方式编写一个非常大的XML文档。与其写一个可能会消耗太多内存的XDocumentXElement,我的想法是使用XmlWriter写根元素,然后在关闭根元素之前,将许多XElement一个接一个地写到该编写器。然而,我还没有找到这样做的方法。要模拟这个问题,请考虑以下代码:

using System;
using System.Xml;
using System.Xml.Linq;
internal static class Program
{
    private static void Main()
    {
        var settings = new XmlWriterSettings { Encoding = Console.OutputEncoding, Indent = true };
        using (var writer = XmlWriter.Create(Console.Out, settings))
        {
            const string namespaceUri = "http://example.com/";
            writer.WriteStartElement("x", "root", namespaceUri);
            XNamespace x = namespaceUri;
            XElement element = new XElement(x + "test");
            element.Save(writer);
            writer.WriteEndElement();
        }
        Console.WriteLine();
    }
}

程序在element.Save(writer);行失败,出现InvalidOperationException:"状态为Element Start Tag的Token StartDocument将导致无效的XML文档"。

出现此异常的原因很清楚:XElement假设它自己拥有整个XmlWriter,并对其调用WriteStartDocument()。显然,这是失败的,因为文档已经启动,并且其中已经有一个启动元素。

注意,如果我使用XDocument,我会期望这种行为,但我不是,我使用的是XElement

另一种选择是编写

            writer.WriteRaw(element.ToString());

而不是

            element.Save(writer);

从某种意义上说,它是有效的,因为它不会崩溃,而且它生成了正确的XML。

然而,我不喜欢它,因为它不能产生我想要的干净高效的XML(它不必要地重复名称空间声明)。它显然不能,因为XElement是在没有XmlWriter应该提供的上下文的情况下序列化的。它需要一个中介字符串才能工作,这甚至不是最大的问题。

我应该如何以高效的方式将多个XElement实例一个接一个地独立写入XmlWriter,以便生成干净的XML?或者这是不可能的?

如何将XElement写入已包含内容的XmlWriter

如果将element.Save(writer);更改为element.WriteTo(writer);,则不会出现异常,并且它似乎已写入控制台。