The code looks like this:
StringBuilder builder = new StringBuilder();
XmlWriterSettings settings = new XmlWriterSettings();
settings.OmitXmlDeclaration = true;
using (XmlWriter xmlWriter = XmlWriter.Create(builder, settings))
{
XmlSerializer s = new XmlSerializer(objectToSerialize.GetType());
s.Serialize(xmlWriter, objectToSerialize);
}
The resulting serialized document includes namespaces, like so:
<message xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"
xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"
xmlns="urn:something">
...
</message>
To remove the xsi and xsd namespaces, I can follow the answer from How to serialize an object to XML without getting xmlns=”…”?.
I want my message tag as <message>
(without any namespace attributes). How can I do this?
This is the first of my two answers to the question.
If you want fine control over the namespaces - for example if you want to omit some of them but not others, or if you want to replace one namespace with another, you can do this using XmlAttributeOverrides.
Suppose you have this type definition:
And this serialization pseudo-code:
You would get something like this XML:
Notice that there is a default namespace on the root element, and there is also a distinct namespace on the "Label" element. These namespaces were dictated by the attributes decorating the type, in the code above.
The Xml Serialization framework in .NET includes the possibility to explicitly override the attributes that decorate the actual code. You do this with the XmlAttributesOverrides class and friends. Suppose I have the same type, and I serialize it this way:
The result looks like this;
You have stripped the namespaces.
A logical question is, can you strip all namespaces from arbitrary types during serialization, without going through the explicit overrides? The answer is YES, and how to do it is in my next response.
After reading Microsoft's documentation and several solutions online, I have discovered the solution to this problem. It works with both the built-in
XmlSerializer
and custom XML serialization viaIXmlSerialiazble
.To wit, I'll use the same
MyTypeWithNamespaces
XML sample that's been used in the answers to this question so far.That's all to this class. Now, some objected to having an
XmlSerializerNamespaces
object somewhere within their classes; but as you can see, I neatly tucked it away in the default constructor and exposed a public property to return the namespaces.Now, when it comes time to serialize the class, you would use the following code:
Once you have done this, you should get the following output:
I have successfully used this method in a recent project with a deep hierachy of classes that are serialized to XML for web service calls. Microsoft's documentation is not very clear about what to do with the publicly accesible
XmlSerializerNamespaces
member once you've created it, and so many think it's useless. But by following their documentation and using it in the manner shown above, you can customize how the XmlSerializer generates XML for your classes without resorting to unsupported behavior or "rolling your own" serialization by implementingIXmlSerializable
.It is my hope that this answer will put to rest, once and for all, how to get rid of the standard
xsi
andxsd
namespaces generated by theXmlSerializer
.UPDATE: I just want to make sure I answered the OP's question about removing all namespaces. My code above will work for this; let me show you how. Now, in the example above, you really can't get rid of all namespaces (because there are two namespaces in use). Somewhere in your XML document, you're going to need to have something like
xmlns="urn:Abracadabra" xmlns:w="urn:Whoohoo
. If the class in the example is part of a larger document, then somewhere above a namespace must be declared for either one of (or both)Abracadbra
andWhoohoo
. If not, then the element in one or both of the namespaces must be decorated with a prefix of some sort (you can't have two default namespaces, right?). So, for this example,Abracadabra
is the defalt namespace. I could inside myMyTypeWithNamespaces
class add a namespace prefix for theWhoohoo
namespace like so:Now, in my class definition, I indicated that the
<Label/>
element is in the namespace"urn:Whoohoo"
, so I don't need to do anything further. When I now serialize the class using my above serialization code unchanged, this is the output:Because
<Label>
is in a different namespace from the rest of the document, it must, in someway, be "decorated" with a namespace. Notice that there are still noxsi
andxsd
namespaces.This is the 2nd of two answers.
If you want to just strip all namespaces arbitrarily from a document during serialization, you can do this by implementing your own XmlWriter.
The easiest way is to derive from XmlTextWriter and override the StartElement method that emits namespaces. The StartElement method is invoked by the XmlSerializer when emitting any elements, including the root. By overriding the namespace for each element, and replacing it with the empty string, you've stripped the namespaces from the output.
Suppose this is the type:
Here's how you would use such a thing during serialization:
The XmlTextWriter is sort of broken, though. According to the reference doc, when it writes it does not check for the following:
These problems with XmlTextWriter have been around since v1.1 of the .NET Framework, and they will remain, for backward compatibility. If you have no concerns about those problems, then by all means use the XmlTextWriter. But most people would like a bit more reliability.
To get that, while still suppressing namespaces during serialization, instead of deriving from XmlTextWriter, define a concrete implementation of the abstract XmlWriter and its 24 methods.
An example is here:
Then, provide a derived class that overrides the StartElement method, as before:
And then use this writer like so:
Credit for this to Oleg Tkachenko.