views:

515

answers:

2

I am using this method to serialize my object:

public static string XmlSerialize(object o)
{
    var stringWriter = new StringWriter();
    var xmlSerializer = new XmlSerializer(o.GetType());
    xmlSerializer.Serialize(stringWriter, o);
    string xml = stringWriter.ToString();
    stringWriter.Close();
    return xml;
}

It makes XML that starts like this:

<?xml version="1.0" encoding="utf-16"?>
<MyObject xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"&gt;

But I want it to look like this:

<?xml version = "1.0" encoding="Windows-1252" standalone="yes"?>
<MyObject xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&gt;

So, how do I change the encoding to Windows-1252 and set standalone = yes? Additionally, how to I get the object to exclude the xmlns value?

I've seen a couple similar questions, like this one, but I was hoping it might be simpler for me, maybe by setting some attributes somewhere?

Update 2: After looking at John's answer and comments, and thinking about this more, I decided to just make a second method. I don't think that creating this wacky custom xml just for a 3rd party on one occasion should be called something as generic as "XmlSerialize" in the first place.

So, I created a second method that takes an XML document and first, removes the one namespace element like this:

xElement.Attributes().Where(a => a.IsNamespaceDeclaration && a.Value == "http://www.w3.org/2001/XMLSchema").Remove();

then, it it writes it to XML with John's code. Finally it returns that xml, following the output from this:

new XDeclaration("1.0", "Windows-1252", "yes").ToString()

And that's ugly, but it gets me exactly what I need for this 3rd party to understand my XML.

+2  A: 

You can use an XmlTextWriter instead of a StringWriter. Here is an extract from some of my code with your encoding set.

XmlTextWriter textWriter = new XmlTextWriter(stream, Encoding.GetEncoding(1252));
textWriter.Namespaces = false;
Nat Ryall
`XmlTextWriter` should no longer be used, as of .NET 2.0.
John Saunders
+6  A: 

Try this:

public static string XmlSerialize(object o)
{
    using (var stringWriter = new StringWriter())
    {
        var settings = new XmlWriterSettings
                           {
                               Encoding = Encoding.GetEncoding(1252),
                               OmitXmlDeclaration = true
                           };
        using (var writer = XmlWriter.Create(stringWriter, settings))
        {
            var xmlSerializer = new XmlSerializer(o.GetType());
            xmlSerializer.Serialize(writer, o);
        }
        return stringWriter.ToString();
    }
}

This won't get rid of the xsd: namespace, but then, why do you want to?


Update: It seems that whenever you use a StringWriter, you get UTF-16, even if you use an XmlWriter on top of it with encoding set. Next step would be o write out to a MemoryStream. But that raises the question of why you want to return a string. For instance, if you're going to just turn around and output the string to a stream, then we should output directly to this stream. Same for a TextWriter.

John Saunders
I am using an API and they have specified that the xsd thing should not be in there. Why they don't want it and why they can't seem to just ignore it I have no idea.
Chris
John, I do not want to get rid of the xml declaration. I want to keep it and change what is outputted.
Chris
Get rid of the OmitXmlDeclaration = true, and you should have the declaration back. You need to kick your API people **really hard** if they choke on the xsd declaration. It will be necessary if xsi:type needs to be specified. If we don't all follow standards, soon XML will not be standard at all.
John Saunders
Even without OmitXmlDeclaration, the declaration ends up being <?xml version="1.0" encoding="utf-16"?>. I need it to be the windows encoding, with standalone="yes".
Chris
I guess I could just omit the declaration as you originally suggested and prepend:new XDeclaration("1.0", "Windows-1252", "yes").ToString()to the output? This whole thing is ugly anyway.
Chris
Upvoted; but I think your post demonstrates the bad points of the `var` keyword. Seems like you're totally misusing it here.
Noon Silk
Please elaborate. What's your problem with it?
John Saunders
`var` should only be used with LINQ, IMHO. You clearly know what object you're getting back there; I see no reason for `var`, only laziness. But probably pointless arguing. Just an observation.
Noon Silk
My reason for using `var` in most cases is the freedom to change the returned type without having to change the declaration.
John Saunders