Attribute XmlNamespaceDeclarations is ignored during XML serialization

假如想象 提交于 2019-11-29 14:59:31

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.

You wont be able to do anything special to your serialized class - its a known issue. Various workarounds have been suggested here:

XmlSerializer: remove unnecessary xsi and xsd namespaces

How to serialize an object to XML without getting xmlns="..."?

xml serialization - remove namespace

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!