XmlWriter to Write to a String Instead of to a File
Asked Answered
K

6

132

I have a WCF service that needs to return a string of XML. But it seems like the writer only wants to build up a file, not a string. I tried:

string nextXMLstring = "";
using (XmlWriter writer = XmlWriter.Create(nextXMLstring))

This generates an error saying nextXMLstring doesnt have a file path. It wants something like:

using (XmlWriter writer = XmlWriter.Create("nextXMLstring.xml"))

How can I build up my XML and then return it as a string??

Thanks!!

Krasnoyarsk answered 5/6, 2009 at 12:33 Comment(0)
G
243

You need to create a StringWriter, and pass that to the XmlWriter.

The string overload of the XmlWriter.Create is for a filename.

E.g.

using (var sw = new StringWriter()) {
  using (var xw = XmlWriter.Create(sw)) {
    // Build Xml with xw.


  }
  return sw.ToString();
}
Giuseppe answered 5/6, 2009 at 12:37 Comment(3)
@Will: Rolled back your change. XmlTextWriter.Close() will flush to the stream, so want that to happen before extracting the string. (Little difference in this case, but prefer to do this consistently because flush semantics of *Writer and Stream classes is not always clearly documented.)Giuseppe
Just a comment for people using this. If you happen to omit the using() and instead declare your XmlWriter normally then make sure to call xw.Flush before you call sw.ToString() or else you may not get all content! (Obviously better to use the using brackets...)Bayless
Keep in mind that the following code gives CA2202 warning during code analysis, beacuse Dispose() method will be called twice on StringWriter objectSchrimsher
S
121

As Richard said, StringWriter is the way forward. There's one snag, however: by default, StringWriter will advertise itself as being in UTF-16. Usually XML is in UTF-8. You can fix this by subclassing StringWriter;

public class Utf8StringWriter : StringWriter
{
    public override Encoding Encoding
    {
         get { return Encoding.UTF8; }
    }
}

This will affect the declaration written by XmlWriter. Of course, if you then write the string out elsewhere in binary form, make sure you use an encoding which matches whichever encoding you fix for the StringWriter. (The above code always assumes UTF-8; it's trivial to make a more general version which accepts an encoding in the constructor.)

You'd then use:

using (TextWriter writer = new Utf8StringWriter())
{
    using (XmlWriter xmlWriter = XmlWriter.Create(writer))
    {
        ...
    }
    return writer.ToString();
}
Scansion answered 5/6, 2009 at 12:57 Comment(2)
Jon, are you sure that writer is not being disposed more than once?Tass
@rasx: It might be - but that won't matter.Scansion
B
33

I know this is old and answered, but here is another way to do it. Particularly if you don't want the UTF8 BOM at the start of your string and you want the text indented:

using (var ms = new MemoryStream())
using (var x = new XmlTextWriter(ms, new UTF8Encoding(false)) 
                   { Formatting = Formatting.Indented })
{
     // ...
     return Encoding.UTF8.GetString(ms.ToArray());
}
Bouffant answered 2/9, 2009 at 20:19 Comment(4)
Encoding.UTF8.GetString(ms.ToArray()) is simplification on your return.Tire
ms.ToArray() returns no items when I tried this. Had to add x.Close() or move the return statement just outside of the inner using statement.Namhoi
Does utf8.GetString(ms.GetBuffer(), 0, (int)ms.Length); work?Bouffant
@Rich C - I suspect this is because your stream was not flushed. The XmlTextWriter would have been disposed outside of its using statement which would cause it to flush.Diamine
O
16

Use StringBuilder:

var sb = new StringBuilder();
    using (XmlWriter xmlWriter = XmlWriter.Create(sb))
    {
        ...
    }
return sb.ToString();
Osteoblast answered 17/12, 2012 at 7:47 Comment(0)
C
5

Guys don't forget to call xmlWriter.Close() and xmlWriter.Dispose() or else your string won't finish creating. It will just be an empty string

Campanulate answered 13/4, 2016 at 21:41 Comment(3)
Don't worry, using statement will handle the disposal of the object.Heterophyte
This is a question from 2009. So, the value in providing an answer now would be for future users who might have similar issues. Consequently, answers to old questions like this should only be provided if they can clearly identify the problem and explain/provide a solution. It is usually fruitless to try to engage the OP in a conversation as they’re likely to have moved on.Sorites
I was going through all these examples and was wonder why do I get empty string. xmlWriter.Close() was the solution.Gerius
L
0

Well I think the simplest and fastest solution here would be just to:

StringBuilder sb = new StringBuilder();

using (var writer = XmlWriter.Create(sb, settings))
{
    ... // Whatever code you have/need :)

    sb = sb.Replace("encoding=\"utf-16\"", "encoding=\"utf-8\""); //Or whatever uft you want/use.
    //Before you finally save it:
    File.WriteAllText("path\\dataName.xml", sb.ToString());
}
Latinist answered 2/8, 2018 at 14:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.