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

Kri*_*ten 6 c# xml linq-to-xml

我正在尝试以流方式编写一个非常大的XML文档.而不是写一个XDocument或者XElement可能消耗太多内存的想法是,我在使用a之前编写根元素XmlWriter,然后在关闭根元素之前一个接一个地向该编写器写入许多XElements.但是,我还没有找到办法.要模拟问题,请考虑以下代码:

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

该程序element.Save(writer);在行上失败,其中包括InvalidOperationException:"状态元素开始标记中的标记StartDocument将导致无效的XML文档".

这个异常的原因很明显:XElement假设它拥有整个XmlWriter,并调用WriteStartDocument()它.显然失败了,因为文档已经启动,并且已经有一个启动元素.

请注意,如果我使用XDocument,我会期待这种行为,但我不是,我正在使用XElement.

另一种方法是写作

            writer.WriteRaw(element.ToString());
Run Code Online (Sandbox Code Playgroud)

代替

            element.Save(writer);
Run Code Online (Sandbox Code Playgroud)

它的工作原理是它不会崩溃,从某种意义上说它可以生成正确的XML.

但是,我不喜欢它,因为它不会产生我正在寻找的干净和高效的XML(它不必要地重复命名空间声明).它显然不能,因为XElement是在没有XmlWriter应该提供的上下文的情况下序列化的.需要中间字符串才能工作的事实甚至不是最大的问题.

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

Las*_*oke 12

如果更改element.Save(writer);element.WriteTo(writer);有没有例外,它似乎写到控制台.