2005-01-31 Zoltan Varga <vargaz@freemail.hu>
[mono.git] / mcs / class / System.XML / System.Xml.Serialization / XmlSchemaExporter.cs
index 5f05894f681c42d188c08450a8a72173eb5d4251..748efe71381c2dbd527c6bd8acb0ca2eca08b0bc 100644 (file)
@@ -8,6 +8,27 @@
 // Copyright (C) Tim Coleman, 2002
 //
 
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
 using System.Xml;
 using System.Xml.Schema;
 using System.Collections;
@@ -19,6 +40,7 @@ namespace System.Xml.Serialization {
 
                XmlSchemas schemas;
                Hashtable exportedMaps = new Hashtable();
+               Hashtable exportedElements = new Hashtable();
                bool encodedFormat = false;
                XmlDocument xmlDoc;
                
@@ -49,15 +71,21 @@ namespace System.Xml.Serialization {
 
                public void ExportMembersMapping (XmlMembersMapping xmlMembersMapping)
                {
-                       XmlSchema schema = GetSchema (xmlMembersMapping.Namespace);
+                       ExportMembersMapping (xmlMembersMapping, true);
+               }
+
+#if NET_2_0
+               public
+#else
+               internal 
+#endif
+               void ExportMembersMapping (XmlMembersMapping xmlMembersMapping, bool exportEnclosingType)
+               {
                        ClassMap cmap = (ClassMap) xmlMembersMapping.ObjectMap;
 
-                       if (xmlMembersMapping.HasWrapperElement)
+                       if (xmlMembersMapping.HasWrapperElement && exportEnclosingType)
                        {
-                               XmlSchemaElement selem = new XmlSchemaElement ();
-                               selem.Name = xmlMembersMapping.ElementName;
-                               schema.Items.Add (selem);
-       
+                               XmlSchema schema = GetSchema (xmlMembersMapping.Namespace);
                                XmlSchemaComplexType stype = new XmlSchemaComplexType ();
        
                                XmlSchemaSequence particle;
@@ -65,8 +93,19 @@ namespace System.Xml.Serialization {
                                ExportMembersMapSchema (schema, cmap, null, stype.Attributes, out particle, out anyAttribute);
                                stype.Particle = particle;
                                stype.AnyAttribute = anyAttribute;
-       
-                               selem.SchemaType = stype;
+                               
+                               if (encodedFormat)
+                               {
+                                       stype.Name = xmlMembersMapping.ElementName;
+                                       schema.Items.Add (stype);
+                               }
+                               else
+                               {
+                                       XmlSchemaElement selem = new XmlSchemaElement ();
+                                       selem.Name = xmlMembersMapping.ElementName;
+                                       selem.SchemaType = stype;
+                                       schema.Items.Add (selem);
+                               }
                        }
                        else
                        {
@@ -75,16 +114,70 @@ namespace System.Xml.Serialization {
                                {
                                        foreach (XmlTypeMapMemberElement member in members)
                                        {
+                                               if (member is XmlTypeMapMemberAnyElement && member.TypeData.IsListType)
+                                               {
+                                                       XmlSchema mschema = GetSchema (xmlMembersMapping.Namespace);
+                                                       XmlSchemaParticle par = GetSchemaArrayElement (mschema, member.ElementInfo);
+                                                       if (par is XmlSchemaAny)
+                                                       {
+                                                               XmlSchemaComplexType ct = FindComplexType (mschema.Items, "any");
+                                                               if (ct != null) continue;
+                                                               
+                                                               ct = new XmlSchemaComplexType ();
+                                                               ct.Name = "any";
+                                                               ct.IsMixed = true;
+                                                               XmlSchemaSequence seq = new XmlSchemaSequence ();
+                                                               ct.Particle = seq;
+                                                               seq.Items.Add (par);
+                                                               mschema.Items.Add (ct);
+                                                               continue;
+                                                       }
+                                               }
+                                               
+                                               
+                                               XmlTypeMapElementInfo einfo = (XmlTypeMapElementInfo) member.ElementInfo [0];
+                                               XmlSchema schema;
+
+                                               if (encodedFormat)
+                                               {
+                                                       schema = GetSchema (xmlMembersMapping.Namespace);
+                                                       ImportNamespace (schema, XmlSerializer.EncodingNamespace);
+                                               }
+                                               else
+                                                       schema = GetSchema (einfo.Namespace);
+                                               
+                                               
+                                               XmlSchemaElement exe = FindElement (schema.Items, einfo.ElementName);
+                                               XmlSchemaElement elem;
+                                               
                                                Type memType = member.GetType();
                                                if (member is XmlTypeMapMemberFlatList)
                                                        throw new InvalidOperationException ("Unwrapped arrays not supported as parameters");
                                                else if (memType == typeof(XmlTypeMapMemberElement))
-                                                       AddSchemaElement (schema.Items, schema, (XmlTypeMapElementInfo) member.ElementInfo [0], member.DefaultValue, false);
+                                                       elem = (XmlSchemaElement) GetSchemaElement (schema, einfo, member.DefaultValue, false);
                                                else
-                                                       AddSchemaElement (schema.Items, schema, (XmlTypeMapElementInfo) member.ElementInfo [0], false);
+                                                       elem = (XmlSchemaElement) GetSchemaElement (schema, einfo, false);
+                                               
+                                               // In encoded format, the schema elements are not needed
+                                               if (!encodedFormat)
+                                                       schema.Items.Add (elem);
+                                               
+                                               if (exe != null)
+                                               {
+                                                       if (exe.SchemaTypeName.Equals (elem.SchemaTypeName))
+                                                               schema.Items.Remove (elem);
+                                                       else
+                                                       {
+                                                               string s = "The XML element named '" + einfo.ElementName + "' ";
+                                                               s += "from namespace '" + schema.TargetNamespace + "' references distinct types " + elem.SchemaTypeName.Name + " and " + exe.SchemaTypeName.Name + ". ";
+                                                               s += "Use XML attributes to specify another XML name or namespace for the element or types.";
+                                                               throw new InvalidOperationException (s);
+                                                       }
+                                               }
                                        }
                                }
                        }
+                       
                        CompileSchemas ();
                }
 
@@ -96,18 +189,28 @@ namespace System.Xml.Serialization {
 
                public void ExportTypeMapping (XmlTypeMapping xmlTypeMapping)
                {
+                       if (!xmlTypeMapping.IncludeInSchema) return;
+                       if (IsElementExported (xmlTypeMapping)) return;
+                       
                        if (encodedFormat)
+                       {
                                ExportClassSchema (xmlTypeMapping);
+                               XmlSchema schema = GetSchema (xmlTypeMapping.XmlTypeNamespace);
+                               ImportNamespace (schema, XmlSerializer.EncodingNamespace);
+                       }
                        else
                        {
                                XmlSchema schema = GetSchema (xmlTypeMapping.Namespace);
                                XmlTypeMapElementInfo einfo = new XmlTypeMapElementInfo (null, xmlTypeMapping.TypeData);
                                einfo.Namespace = xmlTypeMapping.Namespace;
                                einfo.ElementName = xmlTypeMapping.ElementName;
-                               einfo.MappedType = xmlTypeMapping;
+                               if (xmlTypeMapping.TypeData.IsComplexType)
+                                       einfo.MappedType = xmlTypeMapping;
                                einfo.IsNullable = false;
-                               AddSchemaElement (schema.Items, schema, einfo, false);
+                               schema.Items.Add (GetSchemaElement (schema, einfo, false));
+                               SetElementExported (xmlTypeMapping);
                        }
+                       
                        CompileSchemas ();
                }
 
@@ -115,6 +218,13 @@ namespace System.Xml.Serialization {
                {
                        if (IsMapExported (map)) return;
                        SetMapExported (map);
+                       
+                       if (map.TypeData.Type == typeof(object))
+                       {
+                               foreach (XmlTypeMapping dmap in map.DerivedTypes)
+                                       if (dmap.TypeData.SchemaType == SchemaTypes.Class) ExportClassSchema (dmap);
+                               return;
+                       }
 
                        XmlSchema schema = GetSchema (map.XmlTypeNamespace);
                        XmlSchemaComplexType stype = new XmlSchemaComplexType ();
@@ -135,10 +245,13 @@ namespace System.Xml.Serialization {
                                ext.AnyAttribute = anyAttribute;
                                if (map.BaseMap == null)
                                        ext.BaseTypeName = cmap.SimpleContentBaseType;
-                               else
+                               else {
                                        ext.BaseTypeName = new XmlQualifiedName (map.BaseMap.XmlType, map.BaseMap.XmlTypeNamespace);
+                                       ImportNamespace (schema, map.BaseMap.XmlTypeNamespace);
+                                       ExportClassSchema (map.BaseMap);
+                               }
                        }
-                       else if (map.BaseMap != null)
+                       else if (map.BaseMap != null && map.BaseMap.IncludeInSchema)
                        {
                                XmlSchemaComplexContent cstype = new XmlSchemaComplexContent ();
                                XmlSchemaComplexContentExtension ext = new XmlSchemaComplexContentExtension ();
@@ -151,8 +264,10 @@ namespace System.Xml.Serialization {
                                ExportMembersMapSchema (schema, cmap, map.BaseMap, ext.Attributes, out particle, out anyAttribute);
                                ext.Particle = particle;
                                ext.AnyAttribute = anyAttribute;
+                               stype.IsMixed = HasMixedContent (map);
+                               cstype.IsMixed = BaseHasMixedContent (map);
 
-                               ImportNamespace (schema, map.BaseMap.Namespace);
+                               ImportNamespace (schema, map.BaseMap.XmlTypeNamespace);
                                ExportClassSchema (map.BaseMap);
                        }
                        else
@@ -164,6 +279,21 @@ namespace System.Xml.Serialization {
                                stype.AnyAttribute = anyAttribute;
                                stype.IsMixed = cmap.XmlTextCollector != null;
                        }
+                       
+                       foreach (XmlTypeMapping dmap in map.DerivedTypes)
+                               if (dmap.TypeData.SchemaType == SchemaTypes.Class) ExportClassSchema (dmap);
+               }
+               
+               bool BaseHasMixedContent (XmlTypeMapping map)
+               {
+                       ClassMap cmap = (ClassMap)map.ObjectMap;
+                       return (cmap.XmlTextCollector != null && (map.BaseMap != null && DefinedInBaseMap (map.BaseMap, cmap.XmlTextCollector)));
+               }
+
+               bool HasMixedContent (XmlTypeMapping map)
+               {
+                       ClassMap cmap = (ClassMap)map.ObjectMap;
+                       return (cmap.XmlTextCollector != null && (map.BaseMap == null || !DefinedInBaseMap (map.BaseMap, cmap.XmlTextCollector)));
                }
 
                void ExportMembersMapSchema (XmlSchema schema, ClassMap map, XmlTypeMapping baseMap, XmlSchemaObjectCollection outAttributes, out XmlSchemaSequence particle, out XmlSchemaAnyAttribute anyAttribute)
@@ -172,7 +302,7 @@ namespace System.Xml.Serialization {
                        XmlSchemaSequence seq = new XmlSchemaSequence ();
 
                        ICollection members = map.ElementMembers;
-                       if (members != null)
+                       if (members != null && !map.HasSimpleContent)
                        {
                                foreach (XmlTypeMapMemberElement member in members)
                                {
@@ -181,19 +311,22 @@ namespace System.Xml.Serialization {
                                        Type memType = member.GetType();
                                        if (memType == typeof(XmlTypeMapMemberFlatList))
                                        {
-                                               AddSchemaArrayElement (seq.Items, schema, member.ElementInfo);
+                                               XmlSchemaParticle part = GetSchemaArrayElement (schema, member.ElementInfo);
+                                               if (part != null) seq.Items.Add (part);
                                        }
                                        else if (memType == typeof(XmlTypeMapMemberAnyElement))
                                        {
-                                               AddSchemaArrayElement (seq.Items, schema, member.ElementInfo);
+                                               seq.Items.Add (GetSchemaArrayElement (schema, member.ElementInfo));
                                        }
                                        else if (memType == typeof(XmlTypeMapMemberElement))
                                        {
-                                               XmlSchemaElement selem = (XmlSchemaElement) AddSchemaElement (seq.Items, schema, (XmlTypeMapElementInfo) member.ElementInfo [0], member.DefaultValue, true);
+                                               XmlSchemaParticle elem = GetSchemaElement (schema, (XmlTypeMapElementInfo) member.ElementInfo [0], member.DefaultValue, true);
+                                               if (elem != null)
+                                                       seq.Items.Add (elem);
                                        }
                                        else
                                        {
-                                               AddSchemaElement (seq.Items, schema, (XmlTypeMapElementInfo) member.ElementInfo [0], true);
+                                               seq.Items.Add (GetSchemaElement (schema, (XmlTypeMapElementInfo) member.ElementInfo [0], true));
                                        }
                                }
                        }
@@ -208,7 +341,7 @@ namespace System.Xml.Serialization {
                        {
                                foreach (XmlTypeMapMemberAttribute attr in attributes) {
                                        if (baseMap != null && DefinedInBaseMap (baseMap, attr)) continue;
-                                       outAttributes.Add (GetSchemaAttribute (schema, attr));
+                                       outAttributes.Add (GetSchemaAttribute (schema, attr, true));
                                }
                        }
 
@@ -218,18 +351,44 @@ namespace System.Xml.Serialization {
                        else
                                anyAttribute = null;
                }
+               
+               XmlSchemaElement FindElement (XmlSchemaObjectCollection col, string name)
+               {
+                       foreach (XmlSchemaObject ob in col)
+                       {
+                               XmlSchemaElement elem = ob as XmlSchemaElement;
+                               if (elem != null && elem.Name == name) return elem;
+                       }
+                       return null;
+               }
 
-               XmlSchemaAttribute GetSchemaAttribute (XmlSchema currentSchema, XmlTypeMapMemberAttribute attinfo)
+               XmlSchemaComplexType FindComplexType (XmlSchemaObjectCollection col, string name)
+               {
+                       foreach (XmlSchemaObject ob in col)
+                       {
+                               XmlSchemaComplexType ctype = ob as XmlSchemaComplexType;
+                               if (ctype != null && ctype.Name == name) return ctype;
+                       }
+                       return null;
+               }
+
+               XmlSchemaAttribute GetSchemaAttribute (XmlSchema currentSchema, XmlTypeMapMemberAttribute attinfo, bool isTypeMember)
                {
                        XmlSchemaAttribute sat = new XmlSchemaAttribute ();
                        if (attinfo.DefaultValue != System.DBNull.Value) sat.DefaultValue = XmlCustomFormatter.ToXmlString (attinfo.TypeData, attinfo.DefaultValue);
 
                        ImportNamespace (currentSchema, attinfo.Namespace);
 
-                       XmlSchema memberSchema = GetSchema (attinfo.Namespace);
+                       XmlSchema memberSchema;
+                       if (attinfo.Namespace.Length == 0 && attinfo.Form != XmlSchemaForm.Qualified)
+                               memberSchema = currentSchema;
+                       else
+                               memberSchema = GetSchema (attinfo.Namespace);
+
                        if (currentSchema == memberSchema || encodedFormat)
                        {
                                sat.Name = attinfo.AttributeName;
+                               if (isTypeMember) sat.Form = attinfo.Form;
                                if (attinfo.TypeData.SchemaType == SchemaTypes.Enum)
                                {
                                        ImportNamespace (currentSchema, attinfo.DataTypeNamespace);
@@ -246,17 +405,21 @@ namespace System.Xml.Serialization {
                        else
                        {
                                sat.RefName = new XmlQualifiedName (attinfo.AttributeName, attinfo.Namespace);
-                               memberSchema.Items.Add (GetSchemaAttribute (memberSchema, attinfo));
+                               foreach (XmlSchemaObject ob in memberSchema.Items)
+                                       if (ob is XmlSchemaAttribute && ((XmlSchemaAttribute)ob).Name == attinfo.AttributeName)
+                                               return sat;
+                                               
+                               memberSchema.Items.Add (GetSchemaAttribute (memberSchema, attinfo, false));
                        }
                        return sat;
                }
 
-               XmlSchemaParticle AddSchemaElement (XmlSchemaObjectCollection destcol, XmlSchema currentSchema, XmlTypeMapElementInfo einfo, bool isTypeMember)
+               XmlSchemaParticle GetSchemaElement (XmlSchema currentSchema, XmlTypeMapElementInfo einfo, bool isTypeMember)
                {
-                       return AddSchemaElement (destcol, currentSchema, einfo, System.DBNull.Value, isTypeMember);
+                       return GetSchemaElement (currentSchema, einfo, System.DBNull.Value, isTypeMember);
                }
                
-               XmlSchemaParticle AddSchemaElement (XmlSchemaObjectCollection destcol, XmlSchema currentSchema, XmlTypeMapElementInfo einfo, object defaultValue, bool isTypeMember)
+               XmlSchemaParticle GetSchemaElement (XmlSchema currentSchema, XmlTypeMapElementInfo einfo, object defaultValue, bool isTypeMember)
                {
                        if (einfo.IsTextElement) return null;
 
@@ -265,20 +428,17 @@ namespace System.Xml.Serialization {
                                XmlSchemaAny any = new XmlSchemaAny ();
                                any.MinOccurs = 0;
                                any.MaxOccurs = 1;
-                               destcol.Add (any);
                                return any;
                        }
                        
                        XmlSchemaElement selem = new XmlSchemaElement ();
-                       destcol.Add (selem);
 
                        if (isTypeMember)
                        {
                                selem.MaxOccurs = 1;
                                selem.MinOccurs = einfo.IsNullable ? 1 : 0;
                                
-                               if ((einfo.TypeData.Type.IsPrimitive && einfo.TypeData.Type != typeof(string)) ||
-                                       einfo.TypeData.Type.IsEnum || encodedFormat) 
+                               if ((einfo.TypeData.IsValueType && einfo.Member != null && !einfo.Member.IsOptionalValueType) || encodedFormat) 
                                        selem.MinOccurs = 1;
                        }
 
@@ -288,16 +448,18 @@ namespace System.Xml.Serialization {
                        {
                                memberSchema = GetSchema (einfo.Namespace);
                                ImportNamespace (currentSchema, einfo.Namespace);
-                       }               
-
-                       if (currentSchema == memberSchema || encodedFormat)
+                       }
+                       
+                       if (currentSchema == memberSchema || encodedFormat || !isTypeMember)
                        {
                                if (isTypeMember) selem.IsNillable = einfo.IsNullable;
                                selem.Name = einfo.ElementName;
-                               XmlQualifiedName typeName = new XmlQualifiedName (einfo.TypeData.XmlType, einfo.DataTypeNamespace);
 
                                if (defaultValue != System.DBNull.Value)
                                        selem.DefaultValue = XmlCustomFormatter.ToXmlString (einfo.TypeData, defaultValue);
+                                       
+                               if (einfo.Form != XmlSchemaForm.Qualified)
+                                       selem.Form = einfo.Form;
 
                                switch (einfo.TypeData.SchemaType)
                                {
@@ -325,10 +487,11 @@ namespace System.Xml.Serialization {
                                                if (einfo.MappedType.TypeData.Type != typeof(object)) {
                                                        selem.SchemaTypeName = new XmlQualifiedName (einfo.MappedType.XmlType, einfo.MappedType.XmlTypeNamespace);
                                                        ImportNamespace (currentSchema, einfo.MappedType.XmlTypeNamespace);
-                                                       ExportClassSchema (einfo.MappedType);
                                                }
                                                else if (encodedFormat)
                                                        selem.SchemaTypeName = new XmlQualifiedName (einfo.MappedType.XmlType, einfo.MappedType.XmlTypeNamespace);
+                                                       
+                                               ExportClassSchema (einfo.MappedType);
                                                break;
 
                                        case SchemaTypes.Primitive:
@@ -339,7 +502,11 @@ namespace System.Xml.Serialization {
                        else
                        {
                                selem.RefName = new XmlQualifiedName (einfo.ElementName, einfo.Namespace);
-                               AddSchemaElement (memberSchema.Items, memberSchema, einfo, defaultValue, false);
+                               foreach (XmlSchemaObject ob in memberSchema.Items)
+                                       if (ob is XmlSchemaElement && ((XmlSchemaElement)ob).Name == einfo.ElementName)
+                                               return selem;
+                                               
+                               memberSchema.Items.Add (GetSchemaElement (memberSchema, einfo, defaultValue, false));
                        }
                        return selem;
                }
@@ -398,7 +565,7 @@ namespace System.Xml.Serialization {
                        return stype;
                }
 
-               XmlSchemaParticle AddSchemaArrayElement (XmlSchemaObjectCollection destcol, XmlSchema currentSchema, XmlTypeMapElementInfoList infos)
+               XmlSchemaParticle GetSchemaArrayElement (XmlSchema currentSchema, XmlTypeMapElementInfoList infos)
                {
                        int numInfos = infos.Count;
                        if (numInfos > 0 && ((XmlTypeMapElementInfo)infos[0]).IsTextElement) numInfos--;
@@ -406,7 +573,7 @@ namespace System.Xml.Serialization {
 
                        if (numInfos == 1)
                        {
-                               XmlSchemaParticle selem = AddSchemaElement (destcol, currentSchema, (XmlTypeMapElementInfo) infos[infos.Count-1], true);
+                               XmlSchemaParticle selem = GetSchemaElement (currentSchema, (XmlTypeMapElementInfo) infos[infos.Count-1], true);
                                selem.MinOccursString = "0";
                                selem.MaxOccursString = "unbounded";
                                return selem;
@@ -414,13 +581,12 @@ namespace System.Xml.Serialization {
                        else
                        {
                                XmlSchemaChoice schoice = new XmlSchemaChoice ();
-                               destcol.Add (schoice);
                                schoice.MinOccursString = "0";
                                schoice.MaxOccursString = "unbounded";
                                foreach (XmlTypeMapElementInfo einfo in infos)
                                {
                                        if (einfo.IsTextElement) continue;
-                                       AddSchemaElement (schoice.Items, currentSchema, einfo, true);
+                                       schoice.Items.Add (GetSchemaElement (currentSchema, einfo, true));
                                }
                                return schoice;
                        }
@@ -431,7 +597,7 @@ namespace System.Xml.Serialization {
                        if (IsMapExported (map)) return;
                        SetMapExported (map);
 
-                       XmlSchema schema = GetSchema (map.Namespace);
+                       XmlSchema schema = GetSchema (map.XmlTypeNamespace);
                        XmlSchemaSimpleType stype = new XmlSchemaSimpleType ();
                        stype.Name = map.ElementName;
                        schema.Items.Add (stype);
@@ -482,6 +648,24 @@ namespace System.Xml.Serialization {
                                XmlAttribute arrayType = Document.CreateAttribute ("arrayType", XmlSerializer.WsdlNamespace);
                                arrayType.Value = ns + (ns != "" ? ":" : "") + name;
                                at.UnhandledAttributes = new XmlAttribute [] { arrayType };
+                               ImportNamespace (schema, XmlSerializer.WsdlNamespace);
+                       
+                               XmlTypeMapElementInfo einfo = (XmlTypeMapElementInfo) lmap.ItemInfo[0];
+                               if (einfo.MappedType != null)
+                               {
+                                       switch (einfo.TypeData.SchemaType)
+                                       {
+                                               case SchemaTypes.Enum:
+                                                       ExportEnumSchema (einfo.MappedType);
+                                                       break;
+                                               case SchemaTypes.Array: 
+                                                       ExportArraySchema (einfo.MappedType, schemaNs); 
+                                                       break;
+                                               case SchemaTypes.Class:
+                                                       ExportClassSchema (einfo.MappedType);
+                                                       break;
+                                       }
+                               }
                                
                                return new XmlQualifiedName (lmap.GetSchemaArrayName (), schemaNs);
                        }
@@ -490,17 +674,20 @@ namespace System.Xml.Serialization {
                                if (IsMapExported (map)) return new XmlQualifiedName (map.XmlType, map.XmlTypeNamespace);
                                
                                SetMapExported (map);
-                               XmlSchema schema = GetSchema (map.Namespace);
+                               XmlSchema schema = GetSchema (map.XmlTypeNamespace);
                                XmlSchemaComplexType stype = new XmlSchemaComplexType ();
                                stype.Name = map.ElementName;
                                schema.Items.Add (stype);
 
-                               XmlSchemaSequence seq = new XmlSchemaSequence ();
-                               XmlSchemaParticle spart = AddSchemaArrayElement (seq.Items, schema, lmap.ItemInfo);
+                               XmlSchemaParticle spart = GetSchemaArrayElement (schema, lmap.ItemInfo);
                                if (spart is XmlSchemaChoice)
                                        stype.Particle = spart;
                                else
+                               {
+                                       XmlSchemaSequence seq = new XmlSchemaSequence ();
+                                       seq.Items.Add (spart);
                                        stype.Particle = seq;
+                               }
                                        
                                return new XmlQualifiedName (map.XmlType, map.XmlTypeNamespace);
                        }
@@ -517,16 +704,45 @@ namespace System.Xml.Serialization {
 
                bool IsMapExported (XmlTypeMapping map)
                {
-                       if (exportedMaps.Contains (map)) return true;
-                       if (map.TypeData.Type == typeof(object)) return true;
+                       if (exportedMaps.ContainsKey (GetMapKey(map))) return true;
                        return false;
                }
 
                void SetMapExported (XmlTypeMapping map)
                {
-                       exportedMaps.Add (map,map);
+                       exportedMaps [GetMapKey(map)] = map;
                }
 
+               bool IsElementExported (XmlTypeMapping map)
+               {
+                       if (exportedElements.ContainsKey (GetMapKey(map))) return true;
+                       if (map.TypeData.Type == typeof(object)) return true;
+                       return false;
+               }
+
+               void SetElementExported (XmlTypeMapping map)
+               {
+                       exportedElements [GetMapKey(map)] = map;
+               }
+               
+               string GetMapKey (XmlTypeMapping map)
+               {
+                       // Don't use type name for array types, since we can have different
+                       // classes that represent the same array type (for example
+                       // StringCollection and string[]).
+                       
+                       if (map.TypeData.IsListType)
+                               return GetArrayKeyName (map.TypeData) + " " + map.XmlType + " " + map.XmlTypeNamespace;
+                       else
+                               return map.TypeData.FullTypeName + " " + map.XmlType + " " + map.XmlTypeNamespace;
+               }
+               
+               string GetArrayKeyName (TypeData td)
+               {
+                       TypeData etd = td.ListItemTypeData;
+                       return "*arrayof*" + (etd.IsListType ? GetArrayKeyName (etd) : etd.FullTypeName);
+               }
+               
                void CompileSchemas ()
                {
 //                     foreach (XmlSchema sc in schemas)