4

I need to generate a huge xml file from different sources (functions). I decide to use XmlTextWriter since it uses less memory than XmlDocument.

First, initiate an XmlWriter with underlying MemoryStream

MemoryStream ms = new MemoryStream();
XmlTextWriter xmlWriter = new XmlTextWriter(ms, new UTF8Encoding(false, false));
xmlWriter.Formatting = Formatting.Indented;

Then I pass the XmlWriter (note xml writer is kept open until the very end) to a function to generate the beginning of the XML file:

xmlWriter.WriteStartDocument();

xmlWriter.WriteStartElement();

// xmlWriter.WriteEndElement(); // Do not write the end of root element in first function, to add more xml elements in following functions

xmlWriter.WriteEndDocument();
xmlWriter.Flush();

But I found that underlying memory stream is empty (by converting byte array to string and output string). Any ideas why?

Also, I have a general question about how to generate a huge xml file from different sources (functions). What I do now is keeping the XmlWriter open (I assume the underlying memory stream should open as well) to each function and write. In the first function, I do not write the end of root element. After the last function, I manually add the end of root element by:

string endRoot = "</Root>";
byte[] byteEndRoot = Encoding.ASCII.GetBytes(endRoot);
ms.Write(byteEndRoot, 0, byteEndRoot.Length); 

Not sure if this works or not.

Thanks a lot!

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Summer
  • 161
  • 1
  • 7
  • 13
  • 1
    You should break this question in 2 and then link them, if they are relevant to each other – Adriano Carneiro May 25 '11 at 20:35
  • 2
    Please note that the MemoryStream completely undermines "I decide to use XmlTextWriter since it uses less memory" – H H May 25 '11 at 20:43
  • 2
    For anything under 10 MB just use XmlDocument or XDocument. To save memory, write to a FileStream. – H H May 25 '11 at 20:45
  • @Henk, Can you please illustrate more on preference of XmlTextWriter and XmlDocument. I actually used XmlDocument previously. But my research suggested me that XmlTextWriter is preferred in terms of memory usage. See http://support.softartisans.com/kbview_673.aspx and http://msdn.microsoft.com/en-us/library/ff647804.aspx. My boss says we do not need to manipulate xml document and he wants me to write in XmlTextWriter again.... – Summer May 26 '11 at 13:22
  • A writer _only_ saves memory when you write to file. If you write to a MS you will use about the same mem as a Document, but w/o the benefits. – H H May 26 '11 at 13:27

3 Answers3

8

Technically you should only ask one question per question, so I'm only going to answer the first one because this is just a quick visit to SO for me at the moment.

You need to call Flush before attempting to read from the Stream I think.

Edit Just bubbling up my second hunch from the comments below to justify the accepted answer here.

In addition to the call to Flush, if reading from the Stream is done using the Read method and its brethren, then the position in the stream must first be reset back to the start. Otherwise no bytes will be read.

ms.Position = 0; /*reset Position to start*/
StreamReader reader = new StreamReader(ms); 
string text = reader.ReadToEnd(); 
Console.WriteLine(text); 
Martin Smith
  • 438,706
  • 87
  • 741
  • 845
Andras Zoltan
  • 41,961
  • 13
  • 104
  • 160
  • I added xmlWriter.Flush(); But still get empty memory stream. After I pass xmlWriter to a function like: public void Function(XmlTextWriter xmlWriter), will the underlying memory stream be written by xmlWriter.WriteStartElement and so on? – Summer May 25 '11 at 20:39
  • Post the code where you test the memory stream - maybe the stream is good and your test is wrong – Ray May 25 '11 at 20:45
  • @Summer - Long shot - are you getting the bytes by doing the standard read loop back from the Stream? If so, then the current position will be the end of the stream and you will read nothing from it. Make sure you use `ToArray()` if you're not already – Andras Zoltan May 26 '11 at 07:37
  • you are absolutely right! I forgot to set ms.Position=0 before testing ms. So the correct test should be ms.Position = 0; StreamReader reader = new StreamReader(ms); string text = reader.ReadToEnd(); Console.WriteLine(text); – Summer May 26 '11 at 13:01
1

Perhaps you need to call Flush() on the xml stream before checking the memory streazm.

Ray
  • 21,485
  • 5
  • 48
  • 64
1

Make sure you call Flush on the XmlTextWriter before checking the memory stream.