52

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?

0

5 Answers 5

93

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_thread/thread/24e4c8d249ad8299?pli=1

Sign up to request clarification or add additional context in comments.

7 Comments

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.
Anyone know if the same is possible using xdocument/xelement (using .NET 3.5 so cant load directly from the memorystream)
Also note that, as written, the resulting XmlWriter will have a conformance level of Document, so if you do send it as the input to an XSL transform as input (and you're not creating a complete document), you can use new XmlDocument().CreateFragment().CreateNavigator() instead.
Note one drawback to this is that WriteRaw behaves differently for an XmlWriter based on XPathNavigator — namely, it escapes output.
This is totally great.So speedy and elegant to build an XmlDocument without going through String or Stream. A useful example: convert arbitrary WPF runtime instance directly into an XmlDocument representation of the XAML object graph it roots: var xd = new XmlDocument(); var w = xd.CreateNavigator().AppendChild(); XamlWriter.Save(inst, new XamlDesignerSerializationManager(w) { XamlWriterMode = XamlWriterMode.Expression }); (Make sure to use the XamlWriter from System.Windows.Markup) This obviously makes the alternatives look very clunky. Fantastic!
|
11

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);

13 Comments

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...
+1 to counter pointless downvote. This is a decent answer to the question as asked IMHO
I don't like the answer either. It's the classic SO-problem: "How can I solve this in Javascript only?" -- "Use jQuery!"
@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: 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)
|
8

You can write xml file using XMLWriter class. Here is example for this.

    XmlWriterSettings objSetting = new XmlWriterSettings();
    objSetting.Indent = true;
    objSetting.NewLineOnAttributes = true;

    System.Text.StringBuilder sb = new System.Text.StringBuilder();


    using (XmlWriter objWriter = XmlWriter.Create(sb, objSetting))
    {
        //Note the artificial, but useful, indenting
        objWriter.WriteStartDocument();

        objWriter.WriteStartElement("books");

        ////////Start Book Element///////

        objWriter.WriteStartElement("book");

        objWriter.WriteStartAttribute("ISBN");
        objWriter.WriteValue("asp1");
        objWriter.WriteEndAttribute();

        objWriter.WriteStartElement("Title");
        objWriter.WriteValue("ASP.NET");
        objWriter.WriteEndElement();

        objWriter.WriteElementString("ReleaseDate", "11/11/2010");

        objWriter.WriteStartElement("Pages");
        objWriter.WriteValue(200);
        objWriter.WriteEndElement(); //price

        objWriter.WriteEndElement(); //book
        ////////End Book Element///////


        ////////Another Element

        ////////Start Book Element///////

        objWriter.WriteStartElement("book");

        objWriter.WriteStartAttribute("ISBN");
        objWriter.WriteValue("c#2");
        objWriter.WriteEndAttribute();

        objWriter.WriteStartElement("Title");
        objWriter.WriteValue("C#.NET");
        objWriter.WriteEndElement();

        objWriter.WriteElementString("ReleaseDate", "10/11/2010");

        objWriter.WriteStartElement("Pages");
        objWriter.WriteValue(500);
        objWriter.WriteEndElement(); 

        objWriter.WriteEndElement(); //book
        ////////End Book Element///////



        objWriter.WriteEndElement(); //books
        objWriter.WriteEndDocument();

    }

    File.WriteAllText(Server.MapPath("BooksList.xml"), sb.ToString());

Comments

4

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

1 Comment

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.
1

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

3 Comments

This would result in the same inefficiency - reparsing the stream to build a DOM again.
+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.
Boaz is right, it's basically the same as parsing the XmlDocument from a string

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.