23

This example uses a StringWriter to hold the serialized data, then calling ToString() gives the actual string value:

Person john = new Person();
XmlSerializer xmlSerializer = new XmlSerializer(typeof(Person));
StringWriter stringWriter = new StringWriter();
xmlSerializer.Serialize(stringWriter, john);
string serializedXML = stringWriter.ToString();

Is there any easier/Cleaner way to do this? All of the Serialize() overloads seem to use a Stream or Writer.

UPDATE: Asked a similar question about serializing an IEnumerable via an Extension Method .

Community
  • 1
  • 1
John B
  • 20,062
  • 35
  • 120
  • 170

4 Answers4

44

Fun with extension methods...

var ret = john.ToXmlString()

public static class XmlTools
{
    public static string ToXmlString<T>(this T input)
    {
        using (var writer = new StringWriter())
        {
            input.ToXml(writer);
            return writer.ToString();
        }
    }
    public static void ToXml<T>(this T objectToSerialize, Stream stream)
    {
        new XmlSerializer(typeof(T)).Serialize(stream, objectToSerialize);
    }

    public static void ToXml<T>(this T objectToSerialize, StringWriter writer)
    {
        new XmlSerializer(typeof(T)).Serialize(writer, objectToSerialize);
    }
}
Matthew Whited
  • 22,160
  • 4
  • 52
  • 69
  • 1
    beaten... by... 9... seconds... aaarrrggghhh! – Paolo Tedesco Jul 16 '09 at 15:39
  • Ah yes! Totally forgot about that! – John B Jul 16 '09 at 15:40
  • yay... I am normally the late poster for making sure my code works before I submit it. – Matthew Whited Jul 16 '09 at 15:43
  • 2
    me too, but it's an attitude that doesn't pay off :) – Paolo Tedesco Jul 16 '09 at 15:46
  • Is this really an appropriate use of extension methods? I personally believe it is not, but such an opinion wouldn't warrant a vote down so I didn't (just so you don't think so if someone else did). – Sam Harwell Jul 16 '09 at 15:57
  • Extension methods allow for easier to read code. You can do somethings like faking duck/dynamic typing and multiple base classes. If people want to deal with calling factory/converter classes then do it way way. You could always just use this as "string ret = XmlTools.ToXmlString(john)" but that just doesn't read as nice. – Matthew Whited Jul 16 '09 at 16:14
  • Using a generic method, in this case, wouldn't give a problem in case you serialize an object through a base reference? – Paolo Tedesco Jul 17 '09 at 07:43
  • you could provide the generic paramater if you wanted to serialize as a baseclass. But you will most probably lose information if you do that. – Matthew Whited Jul 17 '09 at 14:04
  • My point was that in this case it woulb be better to rely on the GetType method... – Paolo Tedesco Jul 27 '09 at 11:24
  • Why do you say that? You don't need to provide the type to the generic and it will automatically be the type of the object provided. Only if you explicitly provided a generic parameter would you have to worry. – Matthew Whited Jul 27 '09 at 13:47
  • ugh ...and this is why we now use JSON – nothingisnecessary Oct 06 '17 at 14:50
7

More or less your same solution, just using an extension method:

static class XmlExtensions {

    // serialize an object to an XML string
    public static string ToXml(this object obj) {
        // remove the default namespaces
        XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
        ns.Add(string.Empty, string.Empty);
        // serialize to string
        XmlSerializer xs = new XmlSerializer(obj.GetType());
        StringWriter sw = new StringWriter();
        xs.Serialize(sw, obj, ns);
        return sw.GetStringBuilder().ToString();
    }

}

[XmlType("Element")]
public class Element {
    [XmlAttribute("name")]
    public string name;
}

class Program {
    static void Main(string[] args) {
        Element el = new Element();
        el.name = "test";
        Console.WriteLine(el.ToXml());
    }
}
Paolo Tedesco
  • 55,237
  • 33
  • 144
  • 193
  • +1 for a different way of doing things, and a complete example! – John B Jul 16 '09 at 15:50
  • This is missing `using` around `StringWriter`, it might not cause any issue in this case, but it should always be there just in case it is changed to take a stream. – NiKiZe Jul 03 '17 at 06:48
5

I created this helper method, but I haven't tested it yet. Updated the code per orsogufo's comments (twice):

private string ConvertObjectToXml(object objectToSerialize)
{
    XmlSerializer xmlSerializer = new XmlSerializer(objectToSerialize.GetType());
    StringWriter stringWriter = new StringWriter();

    xmlSerializer.Serialize(stringWriter, objectToSerialize);

    return stringWriter.ToString();
}
John B
  • 20,062
  • 35
  • 120
  • 170
  • What are you using Convert.ChangeType for? – Paolo Tedesco Jul 16 '09 at 15:30
  • For some reason I had it in my head that I needed to cast it back to the right type... but I think you're right, there is no need. Code will be updated. – John B Jul 16 '09 at 15:39
  • Infact no, the serializer takes a generic object as parameter (therefore your extra conversion is wasted). Also note that you don't need to pass the type explicitly, you can ask the object which is its type. Unless, of course, you want to serialize an object as an object of a different type (cannot see why you would want that, but you never know). – Paolo Tedesco Jul 16 '09 at 15:45
  • Trying to serialize an object as another type probably wouldn't work, unless it was a base class or interface I would assume. Going to update my code to remove the type reference then. – John B Jul 16 '09 at 15:52
4

Seems like no body actually answered his question, which is no, there is no way to generate an XML string without using a stream or writer object.

Necromancer
  • 390
  • 5
  • 15
  • 2
    Since the `Serializer` uses write internally it can't take a `String` or `StringBuilder` directly, the `StringWriter` has essentially no overhead, so don't see any issue with this. – NiKiZe Jul 03 '17 at 06:51