tags:

views:

2796

answers:

4

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!!

+17  A: 

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();
}
Richard
@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.)
Richard
+1  A: 

The other question is why do you want to return the XML as a string? It would be better to return it as an XmlDocument or XDocument. This way, the calling code can manipulate XML as XML, instead of as a string. Manipulating XML as a string is usually not a good idea.

In particular, WCF can return the XmlDocument type (XDocument, too, probably).


private XmlDocument WriteDocument()
{
    XmlDocument xdoc = new XmlDocument();
    using (var writer=xdoc.CreateNavigator().AppendChild())
    {
        WriteXml(writer);
    }
    return xdoc;
}
John Saunders
Reason for the downvote?
John Saunders
Its the client request. But thank you for the additional suggestions.
Blaze
What's the client request? Returning a string? Tell the client I said he should use XML if at all possible.
John Saunders
How would my original code be set up to return an XmlDocument rather than an xml file such as return.xml?
Blaze
+9  A: 

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();
}
Jon Skeet
+1 This is often overlooked and important to know.
Andrew Hare
That would be 'public override Encoding Encoding'.
Einar
@Einar: Thanks, fixed.
Jon Skeet
+1  A: 

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.GetBuffer(), 0, (int)ms.Length);
}
brianary