views:

2648

answers:

4

Many .NET functions use XmlWriter to output/generate xml. Outputting to a file/string/memory is a very operation:

XmlWriter xw = XmlWriter.Create(PutYourStreamFileWriterEtcHere);
xw.WriteStartElement("root");
...

Sometimes , you need to manipulate the resulting Xml and would therefore like to load it into a XmlDocument or might need an XmlDocument for some other reason but you must generate the XML using an XmlWriter. For example, if you call a function in a 3rd party library that outputs to a XmlWriter only.

One of the things you can do is write the xml to a string and then load it into your XmlDocument:

StringWriter S = new StringWriter();
XmlWriter xw = XmlWriter.Create(S);
/* write away */
XmlDocument xdoc = new XmlDocument();
xdoc.LoadXml(S.ToString());

However this is inefficient - first you serialize all the xml info into a string, then you parse the string again to create the DOM.

How can you point an XmlWriter to build a XmlDocument directly?

+1  A: 

You could do the opposite : build the XmlDocument first using DOM, then write it to a XmlWriter :

XmlDocument xdoc = new XmlDocument();
... // build the document

StringWriter S = new StringWriter();
XmlWriter xw = XmlWriter.Create(S);
xdoc.WriteTo(xw);
Thomas Levesque
Sorry but this doesn't answer the question. I need to use a XmlWriter to generate the XML - not a XmlDocument.
Boaz
XmlWriter isn't designed to write to a XmlDocument, it's designed to write to a Stream or TextWriter. What you're asking is simply not possible, I'm just suggesting another approach...
Thomas Levesque
Anyway, if you can generate the XML with a XmlWriter, I don't see why you couldn't generate it with a XmlDocument...
Thomas Levesque
+1 to counter pointless downvote. This is a decent answer to the question as asked IMHO
Binary Worrier
But XmlDocument can read a Stream, so that solves that.
Seb Nilsson
I don't like the answer either. It's the classic SO-problem: "How can I solve this in Javascript only?" -- "Use jQuery!"
Seb Nilsson
@Seb Nilsson: what's your point ? Loading the XmlDocument from a Stream has the same issue as parsing a string. And I don't see how it compares to jQuery...
Thomas Levesque
@Tomas Levesque: My point is that someone asks a question "How do I solve X" and the answer is "Don't solve X, solve Y instead", when that's not the question. If it's impossible to do, then that's the answer.
Seb Nilsson
@Seb: I strongly disagree. We wouldn't get far as programmers if we stopped every time we needed to get from A to C and there was no direct root. Our profession depends on being able to find the alternative route through B. Thomas is suggesting an alternative approach, honestly I don't understand the vilification of this answer (Yes, I realise this is a community. Yes I have exercised my right to vote on this answer. However I am allowed to express my dissatisfaction with the general response)
Binary Worrier
@Thomas Levesque - apparently it is possible.
Boaz
Yes, I thought I had seen something like that, but couldn't remember what it was exactly...
Thomas Levesque
+4  A: 

The idea behind XmlWriter is to wait until you have finished modifying your data before you start writing.

XmlWriter wasn't built with your situation in mind.

Either

  • Wait until you know what your data is going to be before writing

or

  • Do what you're currently doing
Binary Worrier
I disagree. XmlWriter is a nice example of builder pattern and it makes perfect sense to use it to build DOM (XmlDocument or any other implementation). And I have very real use case:I read XML data and transform it using some XslCompiledTransform, which writes to XmlWriter, which directly constructs XmlDocument, which I can process and then write out (possibly applying some other XSLT on output). What's wrong with that? And writing out to stream and then parsing again is: a) pointless (it doesn't help or make design any clearer), b) unnecessary and c) highly inefficient.
Tomek Szpakowicz
A: 

There is an underlying Stream object that the XmlWriter was writing to, if it was bidirectional (MemoryStream), you could simply re-position it back to -0- and then use the Stream object in the XmlDocument.Load(stream).

HTH,

Z

Zach Bonham
This would result in the same inefficiency - reparsing the stream to build a DOM again.
Boaz
+1 This is the way I would chose to do it over the example given in the question as a string doesn't need to be created as an intermediate.
Stevo3000
Boaz is right, it's basically the same as parsing the XmlDocument from a string
Thomas Levesque
+16  A: 

Here's at least one solution:

XmlDocument doc = new XmlDocument(); 
using (XmlWriter writer = doc.CreateNavigator().AppendChild()) 
{ 
    // Do this directly 
     writer.WriteStartDocument(); 
     writer.WriteStartElement("root"); 
     writer.WriteElementString("foo", "bar"); 
     writer.WriteEndElement(); 
     writer.WriteEndDocument();
    // or anything else you want to with writer, like calling functions etc.
}

Apparently XpathNavigator gives you a XmlWriter when you call AppendChild()

Credits go to Martin Honnen on : http://groups.google.com/group/microsoft.public.dotnet.xml/browse%5Fthread/thread/24e4c8d249ad8299?pli=1

Boaz
Well done, nice find.
Binary Worrier
Thanks! It was obvious to me that you'd be able to use XmlWriter as a builder for XmlDocument but I just couldn't find an easy way to do it so I ended up writing to buffer and parsing again. They could've made it a little easier to find.
Tomek Szpakowicz