I try to serialize an object with custom namespaces. This is how the class looks like:
[XmlRoot("Root", Namespace = "myNamespace")]
public partial class MyClass
{
public MyClass()
{
this.Xmlns = new XmlSerializerNamespaces();
this.Xmlns.Add(string.Empty, "myNamespace");
}
[XmlNamespaceDeclarations()]
public XmlSerializerNamespaces Xmlns = null;
}
And here is the code to serialize it:
XmlSerializer serializer = new XmlSerializer(typeof(MyClass));
serializer.Serialize(xmlWriter, obj);
The expected result is
<Root xmlns="myNamespace" />
However it still has xmlns:xsi and xmlns:xsd attributes:
<Root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="myNamespace" />
When I serialize using serializer.Serialize(xmlWriter, obj, obj.Xmlns)
, the result is correct.
Why does serializer ignore that XmlNamespaceDeclarations
attribute? Shouldn't it automatically take the namespace declarations from it? How can I define namespaces inside serialized class?
Thanks in advance!
Why does serializer ignore that XmlNamespaceDeclarations attribute? Shouldn't it automatically take the namespace declarations from it?
Actually, what the Serializer
does is not ignoring your XmlNamespaceDeclarations
but adding them into the default, internal, XmlWriter namespaces
.
By default, there are already some prefixes-namespaces pairs
(or I would simply call namespaces
for simplicity for the rests of this answer) embedded to the XmlWriter
. They are what you see:
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" //note the lovely pairs here
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
Thus, if you use XmlWriter
, you got to bear with its default namespaces
which unfortunately are not exposed to the outside user. And, to make things "worse" (actually, not that worse, but I try to put this in context), it somehow does not allow you to do anything with it.
The only XmlWriter
property that got something to do with namespace
is NamespaceHandling, which can only be set to either removing duplicate namespaces
or retaining them. Which means, the property would only be of any use if you have somehow - rather magically - declared duplicate namespaces
for your serializable class
:
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
Nevertheless, XmlWriter
still have some "good" things that you can omit the XmlDeclaration
by setting:
OmitXmlDeclaration = true;
when you create your XmlWriterSettings
and use the settings to initialize your XmlWriter
In short, we cannot hope XmlWriter
to do good things to us by removing its default namespaces
- it simply can't.
And thus, we must to the Serializer
to get the solution
How can I define namespaces inside serialized class?
Believe it or not, it is exactly like what you already did!
The overloading method Serialize(XmlWriter, Object, XmlSerializerNamespaces) is designed just for that purpose. When you call it:
serializer.Serialize(xmlWriter, obj, obj.Xmlns);
It replaces the default namespaces + your namespaces
with only your namespaces
If you use Serialize(XmlWriter, Object)
overload, what the Serializer
does is to take all the namespaces
in the XmlWriter
as well as in the Object
and then write XML file. Thus you got all the namespaces
there: the default and yours.
This is probably because XmlWriter
also (internally) apply XmlNamespaceScope to be XmlNamespaceScope.All
which you - again - can do nothing about it.
But when you use Serialize(XmlWriter, Object, XmlSerializerNamespaces)
, you actually tell the Serializer
to only use XmlSerializerNamespaces
that you specify. And so, it does the right thing!
In other words, what you did is already an "official" way for getting the namespaces that you want in the Xml
file.
That note aside, you could also put multiple namespaces
to your XML file as you wish by simply using as many times Xmlns.Add(prefix, ns)
as you want.
Thus, you already did the right thing for your purpose. I merely trying to explain why it is so.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With