Fix XML serialization bug
authorLluis Sanchez <lluis@xamarin.com>
Mon, 19 Nov 2012 19:18:01 +0000 (20:18 +0100)
committerLluis Sanchez <lluis@xamarin.com>
Mon, 19 Nov 2012 20:18:14 +0000 (21:18 +0100)
When reflecting a class which inherits serializable members from a
base class, the members of the base class must be serialized using the
namespace set in the subclass unless a namespace has been explicitly
set in the base class. Before the fix, the members were always
serialized using the namespace of the base class, even when not set
(in which case it was using the default empty namespace).

Fixes bug 8468 - XML serialization problem.

mcs/class/System.XML/System.Xml.Serialization/XmlReflectionImporter.cs
mcs/class/System.XML/System.Xml.Serialization/XmlTypeMapping.cs

index e9888f114846eb2810678365ab9a6c7fb75419d6..63c87fe7df4cecba306a7d7042e963b475294e2a 100644 (file)
@@ -247,7 +247,8 @@ namespace System.Xml.Serialization {
 
                XmlTypeMapping CreateTypeMapping (TypeData typeData, XmlRootAttribute root, string defaultXmlType, string defaultNamespace)
                {
-                       string rootNamespace = defaultNamespace;
+                       bool hasTypeNamespace = !string.IsNullOrEmpty (defaultNamespace);
+                       string rootNamespace = null;
                        string typeNamespace = null;
                        string elementName;
                        bool includeInSchema = true;
@@ -273,8 +274,10 @@ namespace System.Xml.Serialization {
 
                        if (atts.XmlType != null)
                        {
-                               if (atts.XmlType.Namespace != null)
+                               if (atts.XmlType.Namespace != null) {
                                        typeNamespace = atts.XmlType.Namespace;
+                                       hasTypeNamespace = true;
+                               }
 
                                if (atts.XmlType.TypeName != null && atts.XmlType.TypeName != string.Empty)
                                        defaultXmlType = XmlConvert.EncodeLocalName (atts.XmlType.TypeName);
@@ -288,13 +291,15 @@ namespace System.Xml.Serialization {
                        {
                                if (root.ElementName.Length != 0)
                                        elementName = XmlConvert.EncodeLocalName(root.ElementName);
-                               if (root.Namespace != null)
+                               if (root.Namespace != null) {
                                        rootNamespace = root.Namespace;
+                                       hasTypeNamespace = true;
+                               }
                                nullable = root.IsNullable;
                        }
 
-                       if (rootNamespace == null) rootNamespace = "";
-                       if (typeNamespace == null) typeNamespace = rootNamespace;
+                       rootNamespace = rootNamespace ?? defaultNamespace ?? string.Empty;
+                       typeNamespace = typeNamespace ?? rootNamespace;
                        
                        XmlTypeMapping map;
                        switch (typeData.SchemaType) {
@@ -310,7 +315,7 @@ namespace System.Xml.Serialization {
                                                        typeData, defaultXmlType, typeNamespace);
                                        break;
                                default:
-                                       map = new XmlTypeMapping (elementName, rootNamespace, typeData, defaultXmlType, typeNamespace);
+                                       map = new XmlTypeMapping (elementName, rootNamespace, typeData, defaultXmlType, hasTypeNamespace ? typeNamespace : null);
                                        break;
                        }
 
@@ -368,7 +373,8 @@ namespace System.Xml.Serialization {
                                if (rmember.XmlAttributes.XmlIgnore) continue;
                                if (rmember.DeclaringType != null && rmember.DeclaringType != type) {
                                        XmlTypeMapping bmap = ImportClassMapping (rmember.DeclaringType, root, defaultNamespace);
-                                       ns = bmap.XmlTypeNamespace;
+                                       if (bmap.HasXmlTypeNamespace)
+                                               ns = bmap.XmlTypeNamespace;
                                }
 
                                try {
index fc29513df6d545fb69fd8da3a47bba8881e2b3eb..859042fd7e34d404f8bcc489a1cd91c5b3fc500a 100644 (file)
@@ -107,10 +107,15 @@ namespace System.Xml.Serialization
 
                internal string XmlTypeNamespace
                {
-                       get { return xmlTypeNamespace; }
+                       get { return xmlTypeNamespace ?? string.Empty; }
                        set { xmlTypeNamespace = value; }
                }
 
+               internal bool HasXmlTypeNamespace
+               {
+                       get { return xmlTypeNamespace != null; }
+               }
+
                internal ArrayList DerivedTypes
                {
                        get { return _derivedTypes; }
@@ -170,9 +175,9 @@ namespace System.Xml.Serialization
 
                internal XmlTypeMapping GetRealElementMap (string name, string ens)
                {
-                       if (xmlType == name && xmlTypeNamespace == ens) return this;
+                       if (xmlType == name && XmlTypeNamespace == ens) return this;
                        foreach (XmlTypeMapping map in _derivedTypes)
-                               if (map.xmlType == name && map.xmlTypeNamespace == ens) return map;
+                               if (map.xmlType == name && map.XmlTypeNamespace == ens) return map;
                        
                        return null;
                }