Im am trying to write a very large XML document in a streaming manner. Instead of writing one XDocument
or XElement
, which might consume too much memory, the idea is that I write the root element using an XmlWriter
, and then write many XElements to that writer, one after the other, before closing the root element. However, I have not found a way to do so. To simulate the problem, consider the following code:
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();
}
}
The program fails on the element.Save(writer);
line, with an InvalidOperationException
: "Token StartDocument in state Element Start Tag would result in an invalid XML document".
The reason for this exception is clear: the XElement is assuming it has the entire XmlWriter all for itself, and calls WriteStartDocument()
on it. Obviously that fails, as the document was already started, and already has a start element in it.
Note that I would expect this behavior if I were to use XDocument
, but I'm not, I'm using XElement
.
An alternative would be to write
writer.WriteRaw(element.ToString());
instead of
element.Save(writer);
It works, in the sense that it doesn't crash, and in the sense that it produces correct XML.
However, I don't like it, because it doesn't produce the clean and efficient XML I am looking for (it needlessly repeats the namespace declarations). It obviously couldn't, as the XElement is serialized without the context that the XmlWriter should provide. The fact that it needs an intermediary string to work is not even the biggest problem.
How should I write many XElement
instances independently, one after the other, to an XmlWriter
, in an efficient way, so that clean XML is produced? Or is this not possible?
If you change element.Save(writer);
to element.WriteTo(writer);
there is no exception and it seems written to the console.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With