2 // System.Xml.Serialization.XmlSchemaImporter
5 // Tim Coleman (tim@timcoleman.com)
6 // Lluis Sanchez Gual (lluis@ximian.com)
8 // Copyright (C) Tim Coleman, 2002
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 #if !TARGET_JVM && !MONOTOUCH
34 using System
.CodeDom
.Compiler
;
36 using System
.Xml
.Schema
;
37 using System
.Collections
;
38 #if NET_2_0 && CONFIGURATION_DEP
39 using System
.Configuration
;
40 using System
.Xml
.Serialization
.Configuration
;
43 namespace System
.Xml
.Serialization
45 public class XmlSchemaImporter
46 #if NET_2_0 && !MONOTOUCH
53 CodeIdentifiers typeIdentifiers
;
54 CodeIdentifiers elemIdentifiers
= new CodeIdentifiers ();
55 Hashtable mappedTypes
= new Hashtable ();
56 Hashtable primitiveDerivedMappedTypes
= new Hashtable ();
57 Hashtable dataMappedTypes
= new Hashtable ();
58 Queue pendingMaps
= new Queue ();
59 Hashtable sharedAnonymousTypes
= new Hashtable ();
60 bool encodedFormat
= false;
61 XmlReflectionImporter auxXmlRefImporter
;
62 SoapReflectionImporter auxSoapRefImporter
;
66 CodeGenerationOptions options
;
69 static readonly XmlQualifiedName anyType
= new XmlQualifiedName ("anyType",XmlSchema
.Namespace
);
70 static readonly XmlQualifiedName arrayType
= new XmlQualifiedName ("Array",XmlSerializer
.EncodingNamespace
);
71 static readonly XmlQualifiedName arrayTypeRefName
= new XmlQualifiedName ("arrayType",XmlSerializer
.EncodingNamespace
);
73 const string XmlNamespace
= "http://www.w3.org/XML/1998/namespace";
75 XmlSchemaElement anyElement
= null;
79 public XmlTypeMapping Map
;
80 public XmlSchemaComplexType SchemaType
;
81 public XmlQualifiedName TypeName
;
88 public XmlSchemaImporter (XmlSchemas schemas
)
90 this.schemas
= schemas
;
91 typeIdentifiers
= new CodeIdentifiers ();
93 InitializeExtensions ();
96 public XmlSchemaImporter (XmlSchemas schemas
, CodeIdentifiers typeIdentifiers
)
99 this.typeIdentifiers
= typeIdentifiers
;
103 #if !TARGET_JVM && !MONOTOUCH
105 public XmlSchemaImporter (XmlSchemas schemas
, CodeGenerationOptions options
, CodeDomProvider codeProvider
, ImportContext context
)
107 this.schemas
= schemas
;
108 this.options
= options
;
109 if (context
!= null) {
110 typeIdentifiers
= context
.TypeIdentifiers
;
111 InitSharedData (context
);
114 typeIdentifiers
= new CodeIdentifiers ();
116 InitializeExtensions ();
120 public XmlSchemaImporter (XmlSchemas schemas
, CodeGenerationOptions options
, ImportContext context
)
122 this.schemas
= schemas
;
123 this.options
= options
;
124 if (context
!= null) {
125 typeIdentifiers
= context
.TypeIdentifiers
;
126 InitSharedData (context
);
129 typeIdentifiers
= new CodeIdentifiers ();
131 InitializeExtensions ();
135 public XmlSchemaImporter (XmlSchemas schemas
, CodeIdentifiers typeIdentifiers
, CodeGenerationOptions options
)
137 this.typeIdentifiers
= typeIdentifiers
;
138 this.schemas
= schemas
;
139 this.options
= options
;
141 InitializeExtensions ();
144 void InitSharedData (ImportContext context
)
146 if (context
.ShareTypes
) {
147 mappedTypes
= context
.MappedTypes
;
148 dataMappedTypes
= context
.DataMappedTypes
;
149 sharedAnonymousTypes
= context
.SharedAnonymousTypes
;
154 internal bool UseEncodedFormat
156 get { return encodedFormat; }
157 set { encodedFormat = value; }
160 #endregion // Constructors
164 void InitializeExtensions ()
166 #if NET_2_0 && CONFIGURATION_DEP
167 SerializationSectionGroup root
= ConfigurationManager
.GetSection ("system.xml.serialization") as SerializationSectionGroup
;
171 foreach (SchemaImporterExtensionElement element
in
172 root
.SchemaImporterExtensions
.SchemaImporterExtensions
)
173 Extensions
.Add (element
.Name
, element
.Type
);
177 public XmlMembersMapping
ImportAnyType (XmlQualifiedName typeName
, string elementName
)
179 if (typeName
== XmlQualifiedName
.Empty
)
181 XmlTypeMapMemberAnyElement mapMem
= new XmlTypeMapMemberAnyElement ();
182 mapMem
.Name
= typeName
.Name
;
183 mapMem
.TypeData
= TypeTranslator
.GetTypeData(typeof(XmlNode
));
184 mapMem
.ElementInfo
.Add (CreateElementInfo (typeName
.Namespace
, mapMem
, typeName
.Name
, mapMem
.TypeData
, true, XmlSchemaForm
.None
));
186 XmlMemberMapping
[] mm
= new XmlMemberMapping
[1];
187 mm
[0] = new XmlMemberMapping (typeName
.Name
, typeName
.Namespace
, mapMem
, encodedFormat
);
188 return new XmlMembersMapping (mm
);
192 XmlSchemaComplexType stype
= (XmlSchemaComplexType
) schemas
.Find (typeName
, typeof (XmlSchemaComplexType
));
194 throw new InvalidOperationException ("Referenced type '" + typeName
+ "' not found");
196 if (!CanBeAnyElement (stype
))
197 throw new InvalidOperationException ("The type '" + typeName
+ "' is not valid for a collection of any elements");
199 ClassMap cmap
= new ClassMap ();
200 CodeIdentifiers classIds
= new CodeIdentifiers ();
201 bool isMixed
= stype
.IsMixed
;
202 ImportSequenceContent (typeName
, cmap
, ((XmlSchemaSequence
) stype
.Particle
).Items
, classIds
, false, ref isMixed
);
203 XmlTypeMapMemberAnyElement mapMem
= (XmlTypeMapMemberAnyElement
) cmap
.AllMembers
[0];
204 mapMem
.Name
= typeName
.Name
;
206 XmlMemberMapping
[] mm
= new XmlMemberMapping
[1];
207 mm
[0] = new XmlMemberMapping (typeName
.Name
, typeName
.Namespace
, mapMem
, encodedFormat
);
208 return new XmlMembersMapping (mm
);
212 public XmlTypeMapping
ImportDerivedTypeMapping (XmlQualifiedName name
, Type baseType
)
214 return ImportDerivedTypeMapping (name
, baseType
, true);
217 public XmlTypeMapping
ImportDerivedTypeMapping (XmlQualifiedName name
, Type baseType
, bool baseTypeCanBeIndirect
)
219 XmlQualifiedName qname
;
225 stype
= schemas
.Find (name
, typeof (XmlSchemaComplexType
)) as XmlSchemaComplexType
;
226 if (stype
== null) throw new InvalidOperationException ("Schema type '" + name
+ "' not found or not valid");
230 if (!LocateElement (name
, out qname
, out stype
))
234 XmlTypeMapping map
= GetRegisteredTypeMapping (qname
, baseType
);
237 // If the type has already been imported, make sure that the map
238 // has the requested base type
240 SetMapBaseType (map
, baseType
);
241 map
.UpdateRoot (name
);
245 map
= CreateTypeMapping (qname
, SchemaTypes
.Class
, name
);
247 map
.Documentation
= GetDocumentation (stype
);
248 RegisterMapFixup (map
, qname
, (XmlSchemaComplexType
)stype
);
250 ClassMap cmap
= new ClassMap ();
251 CodeIdentifiers classIds
= new CodeIdentifiers ();
252 map
.ObjectMap
= cmap
;
253 AddTextMember (qname
, cmap
, classIds
);
257 SetMapBaseType (map
, baseType
);
262 void SetMapBaseType (XmlTypeMapping map
, Type baseType
)
264 // This method sets the base type for a given map.
265 // If the map already inherits from this type, it does nothing.
267 // Fiirst of all, check if the map already inherits from baseType
269 XmlTypeMapping topMap
= null;
272 if (map
.TypeData
.Type
== baseType
)
278 // Does not have the requested base type.
279 // Then, get/create a map for that base type.
281 XmlTypeMapping baseMap
= ReflectType (baseType
);
283 // Add this map as a derived map of the base map
285 topMap
.BaseMap
= baseMap
;
286 baseMap
.DerivedTypes
.Add (topMap
);
287 baseMap
.DerivedTypes
.AddRange (topMap
.DerivedTypes
);
289 // Now add the base type fields to all derived maps
291 ClassMap baseClassMap
= (ClassMap
)baseMap
.ObjectMap
;
293 ClassMap cmap
= (ClassMap
)topMap
.ObjectMap
;
294 foreach (XmlTypeMapMember member
in baseClassMap
.AllMembers
)
295 cmap
.AddMember (member
);
297 foreach (XmlTypeMapping derivedMap
in topMap
.DerivedTypes
)
299 cmap
= (ClassMap
)derivedMap
.ObjectMap
;
300 foreach (XmlTypeMapMember member
in baseClassMap
.AllMembers
)
301 cmap
.AddMember (member
);
305 public XmlMembersMapping
ImportMembersMapping (XmlQualifiedName name
)
307 XmlSchemaElement elem
= (XmlSchemaElement
) schemas
.Find (name
, typeof (XmlSchemaElement
));
308 if (elem
== null) throw new InvalidOperationException ("Schema element '" + name
+ "' not found or not valid");
310 XmlSchemaComplexType stype
;
311 if (elem
.SchemaType
!= null)
313 stype
= elem
.SchemaType
as XmlSchemaComplexType
;
317 if (elem
.SchemaTypeName
.IsEmpty
) return null;
318 object type
= schemas
.Find (elem
.SchemaTypeName
, typeof (XmlSchemaComplexType
));
320 if (IsPrimitiveTypeNamespace (elem
.SchemaTypeName
.Namespace
)) return null;
321 throw new InvalidOperationException ("Schema type '" + elem
.SchemaTypeName
+ "' not found");
323 stype
= type
as XmlSchemaComplexType
;
327 throw new InvalidOperationException ("Schema element '" + name
+ "' not found or not valid");
329 XmlMemberMapping
[] mapping
= ImportMembersMappingComposite (stype
, name
);
330 return new XmlMembersMapping (name
.Name
, name
.Namespace
, mapping
);
333 public XmlMembersMapping
ImportMembersMapping (XmlQualifiedName
[] names
)
335 XmlMemberMapping
[] mapping
= new XmlMemberMapping
[names
.Length
];
336 for (int n
=0; n
<names
.Length
; n
++)
338 XmlSchemaElement elem
= (XmlSchemaElement
) schemas
.Find (names
[n
], typeof (XmlSchemaElement
));
339 if (elem
== null) throw new InvalidOperationException ("Schema element '" + names
[n
] + "' not found");
341 XmlQualifiedName typeQName
= new XmlQualifiedName ("Message", names
[n
].Namespace
);
343 TypeData td
= GetElementTypeData (typeQName
, elem
, names
[n
], out tmap
);
345 mapping
[n
] = ImportMemberMapping (elem
.Name
, typeQName
.Namespace
, elem
.IsNillable
, td
, tmap
);
348 return new XmlMembersMapping (mapping
);
353 public XmlMembersMapping
ImportMembersMapping (string name
, string ns
, SoapSchemaMember
[] members
)
355 throw new NotImplementedException ();
358 public XmlTypeMapping
ImportSchemaType (XmlQualifiedName typeName
)
360 return ImportSchemaType (typeName
, typeof (object));
363 public XmlTypeMapping
ImportSchemaType (XmlQualifiedName typeName
, Type baseType
)
365 return ImportSchemaType (typeName
, typeof (object), false);
368 [MonoTODO ("baseType and baseTypeCanBeIndirect are ignored")]
369 public XmlTypeMapping
ImportSchemaType (XmlQualifiedName typeName
, Type baseType
, bool baseTypeCanBeIndirect
)
371 XmlSchemaType stype
=
372 (XmlSchemaType
) schemas
.Find (typeName
, typeof (XmlSchemaComplexType
)) ??
373 (XmlSchemaType
) schemas
.Find (typeName
, typeof (XmlSchemaSimpleType
));
374 return ImportTypeCommon (typeName
, typeName
, stype
, true);
378 internal XmlMembersMapping
ImportEncodedMembersMapping (string name
, string ns
, SoapSchemaMember
[] members
, bool hasWrapperElement
)
380 XmlMemberMapping
[] mapping
= new XmlMemberMapping
[members
.Length
];
381 for (int n
=0; n
<members
.Length
; n
++)
383 TypeData td
= GetTypeData (members
[n
].MemberType
, null, false); // FIXME: isNullable could be true?
384 XmlTypeMapping tmap
= GetTypeMapping (td
);
385 mapping
[n
] = ImportMemberMapping (members
[n
].MemberName
, members
[n
].MemberType
.Namespace
, true, td
, tmap
);
388 return new XmlMembersMapping (name
, ns
, hasWrapperElement
, false, mapping
);
391 internal XmlMembersMapping
ImportEncodedMembersMapping (string name
, string ns
, SoapSchemaMember member
)
393 XmlSchemaComplexType stype
= schemas
.Find (member
.MemberType
, typeof (XmlSchemaComplexType
)) as XmlSchemaComplexType
;
394 if (stype
== null) throw new InvalidOperationException ("Schema type '" + member
.MemberType
+ "' not found or not valid");
396 XmlMemberMapping
[] mapping
= ImportMembersMappingComposite (stype
, member
.MemberType
);
397 return new XmlMembersMapping (name
, ns
, mapping
);
400 XmlMemberMapping
[] ImportMembersMappingComposite (XmlSchemaComplexType stype
, XmlQualifiedName refer
)
402 if (stype
.Particle
== null)
403 return new XmlMemberMapping
[0];
405 ClassMap cmap
= new ClassMap ();
407 XmlSchemaSequence seq
= stype
.Particle
as XmlSchemaSequence
;
408 if (seq
== null) throw new InvalidOperationException ("Schema element '" + refer
+ "' cannot be imported as XmlMembersMapping");
410 CodeIdentifiers classIds
= new CodeIdentifiers ();
411 ImportParticleComplexContent (refer
, cmap
, seq
, classIds
, false);
412 ImportAttributes (refer
, cmap
, stype
.Attributes
, stype
.AnyAttribute
, classIds
);
417 XmlMemberMapping
[] mapping
= new XmlMemberMapping
[cmap
.AllMembers
.Count
];
418 foreach (XmlTypeMapMember mapMem
in cmap
.AllMembers
)
419 mapping
[n
++] = new XmlMemberMapping (mapMem
.Name
, refer
.Namespace
, mapMem
, encodedFormat
);
424 XmlMemberMapping
ImportMemberMapping (string name
, string ns
, bool isNullable
, TypeData type
, XmlTypeMapping emap
)
426 XmlTypeMapMemberElement mapMem
;
429 mapMem
= new XmlTypeMapMemberList ();
431 mapMem
= new XmlTypeMapMemberElement ();
434 mapMem
.TypeData
= type
;
435 mapMem
.ElementInfo
.Add (CreateElementInfo (ns
, mapMem
, name
, type
, isNullable
, XmlSchemaForm
.None
, emap
));
436 return new XmlMemberMapping (name
, ns
, mapMem
, encodedFormat
);
440 public XmlMembersMapping
ImportMembersMapping (XmlQualifiedName
[] names
, Type baseType
, bool baseTypeCanBeIndirect
)
442 throw new NotImplementedException ();
445 public XmlTypeMapping
ImportTypeMapping (XmlQualifiedName name
)
447 XmlQualifiedName qname
;
450 XmlSchemaElement elem
= (XmlSchemaElement
) schemas
.Find (name
, typeof (XmlSchemaElement
));
451 if (!LocateElement (elem
, out qname
, out stype
))
452 throw new InvalidOperationException (String
.Format ("'{0}' is missing.", name
));
453 return ImportTypeCommon (name
, qname
, stype
, elem
.IsNillable
);
456 // FIXME: name and qname are confusing. Rename one either
457 // (name is in schema itself, qname is for actual processing.
458 // For example simple types have qname as in xsd namespace.)
459 private XmlTypeMapping
ImportTypeCommon (XmlQualifiedName name
, XmlQualifiedName qname
, XmlSchemaType stype
, bool isNullable
)
462 if (qname
== anyType
) {
463 // Importing anyType.
464 XmlTypeMapping xmap
= GetTypeMapping (TypeTranslator
.GetTypeData (typeof (object)));
465 // This also means, all complexTypes
466 // are imported as well.
470 // Importing a primitive type
471 TypeData td
= TypeTranslator
.GetPrimitiveTypeData (qname
.Name
);
472 return ReflectType (td
, name
.Namespace
);
476 XmlTypeMapping map
= GetRegisteredTypeMapping (qname
);
477 if (map
!= null) return map
;
479 if (stype
is XmlSchemaSimpleType
)
480 return ImportClassSimpleType (stype
.QualifiedName
, (XmlSchemaSimpleType
) stype
, name
);
482 map
= CreateTypeMapping (qname
, SchemaTypes
.Class
, name
);
483 map
.Documentation
= GetDocumentation (stype
);
484 map
.IsNullable
= isNullable
;
485 RegisterMapFixup (map
, qname
, (XmlSchemaComplexType
)stype
);
491 bool LocateElement (XmlQualifiedName name
, out XmlQualifiedName qname
, out XmlSchemaType stype
)
493 XmlSchemaElement elem
= (XmlSchemaElement
) schemas
.Find (name
, typeof (XmlSchemaElement
));
494 return LocateElement (elem
, out qname
, out stype
);
497 bool LocateElement (XmlSchemaElement elem
, out XmlQualifiedName qname
, out XmlSchemaType stype
)
502 if (elem
== null) return false;
504 // The root element must be an element with complex type
506 if (elem
.SchemaType
!= null)
508 stype
= elem
.SchemaType
;
509 qname
= elem
.QualifiedName
;
511 else if (elem
.ElementType
== XmlSchemaComplexType
.AnyType
)
518 if (elem
.SchemaTypeName
.IsEmpty
) return false;
520 object type
= schemas
.Find (elem
.SchemaTypeName
, typeof (XmlSchemaComplexType
));
521 if (type
== null) type
= schemas
.Find (elem
.SchemaTypeName
, typeof (XmlSchemaSimpleType
));
523 if (IsPrimitiveTypeNamespace (elem
.SchemaTypeName
.Namespace
)) {
524 qname
= elem
.SchemaTypeName
;
527 throw new InvalidOperationException ("Schema type '" + elem
.SchemaTypeName
+ "' not found");
529 stype
= (XmlSchemaType
) type
;
530 qname
= stype
.QualifiedName
;
532 XmlSchemaType btype
= stype
.BaseSchemaType
as XmlSchemaType
;
533 if (btype
!= null && btype
.QualifiedName
== elem
.SchemaTypeName
)
534 throw new InvalidOperationException ("Cannot import schema for type '" + elem
.SchemaTypeName
.Name
+ "' from namespace '" + elem
.SchemaTypeName
.Namespace
+ "'. Redefine not supported");
537 //if (stype is XmlSchemaSimpleType) return false;
541 XmlTypeMapping
ImportType (XmlQualifiedName name
, XmlQualifiedName root
, bool throwOnError
)
543 XmlTypeMapping map
= GetRegisteredTypeMapping (name
);
545 map
.UpdateRoot (root
);
549 XmlSchemaType type
= (XmlSchemaType
) schemas
.Find (name
, typeof (XmlSchemaComplexType
));
550 if (type
== null) type
= (XmlSchemaType
) schemas
.Find (name
, typeof (XmlSchemaSimpleType
));
555 if (name
.Namespace
== XmlSerializer
.EncodingNamespace
)
556 throw new InvalidOperationException ("Referenced type '" + name
+ "' valid only for encoded SOAP.");
558 throw new InvalidOperationException ("Referenced type '" + name
+ "' not found.");
563 return ImportType (name
, type
, root
);
566 XmlTypeMapping
ImportClass (XmlQualifiedName name
)
568 XmlTypeMapping map
= ImportType (name
, null, true);
569 if (map
.TypeData
.SchemaType
== SchemaTypes
.Class
) return map
;
570 XmlSchemaComplexType stype
= schemas
.Find (name
, typeof (XmlSchemaComplexType
)) as XmlSchemaComplexType
;
571 return CreateClassMap (name
, stype
, new XmlQualifiedName (map
.ElementName
, map
.Namespace
));
574 XmlTypeMapping
ImportType (XmlQualifiedName name
, XmlSchemaType stype
, XmlQualifiedName root
)
576 XmlTypeMapping map
= GetRegisteredTypeMapping (name
);
578 XmlSchemaComplexType ct
= stype
as XmlSchemaComplexType
;
579 if (map
.TypeData
.SchemaType
!= SchemaTypes
.Class
|| ct
== null || !CanBeArray (name
, ct
)) {
580 map
.UpdateRoot (root
);
584 // The map was initially imported as a class, but it turns out that it is an
585 // array. It has to be imported now as array.
588 if (stype
is XmlSchemaComplexType
)
589 return ImportClassComplexType (name
, (XmlSchemaComplexType
) stype
, root
);
590 else if (stype
is XmlSchemaSimpleType
)
591 return ImportClassSimpleType (name
, (XmlSchemaSimpleType
) stype
, root
);
593 throw new NotSupportedException ("Schema type not supported: " + stype
.GetType ());
596 XmlTypeMapping
ImportClassComplexType (XmlQualifiedName typeQName
, XmlSchemaComplexType stype
, XmlQualifiedName root
)
598 // The need for fixups: If the complex type is an array, then to get the type of the
599 // array we need first to get the type of the items of the array.
600 // But if one of the item types or its children has a referece to this type array,
601 // then we enter in an infinite loop. This does not happen with class types because
602 // the class map is registered before parsing the children. We can't do the same
603 // with the array type because to register the array map we need the type of the array.
605 Type anyType
= GetAnyElementType (stype
);
607 return GetTypeMapping (TypeTranslator
.GetTypeData(anyType
));
609 if (CanBeArray (typeQName
, stype
))
612 ListMap listMap
= BuildArrayMap (typeQName
, stype
, out typeData
);
615 XmlTypeMapping map
= CreateArrayTypeMapping (typeQName
, typeData
);
616 map
.ObjectMap
= listMap
;
620 // After all, it is not an array. Create a class map then.
622 else if (CanBeIXmlSerializable (stype
))
624 return ImportXmlSerializableMapping (typeQName
.Namespace
);
627 // Register the map right now but do not build it,
628 // This will avoid loops.
630 return CreateClassMap (typeQName
, stype
, root
);
633 XmlTypeMapping
CreateClassMap (XmlQualifiedName typeQName
, XmlSchemaComplexType stype
, XmlQualifiedName root
)
635 XmlTypeMapping map
= CreateTypeMapping (typeQName
, SchemaTypes
.Class
, root
);
636 map
.Documentation
= GetDocumentation (stype
);
637 RegisterMapFixup (map
, typeQName
, stype
);
641 void RegisterMapFixup (XmlTypeMapping map
, XmlQualifiedName typeQName
, XmlSchemaComplexType stype
)
643 MapFixup fixup
= new MapFixup ();
645 fixup
.SchemaType
= stype
;
646 fixup
.TypeName
= typeQName
;
647 pendingMaps
.Enqueue (fixup
);
650 void BuildPendingMaps ()
652 while (pendingMaps
.Count
> 0) {
653 MapFixup fixup
= (MapFixup
) pendingMaps
.Dequeue ();
654 if (fixup
.Map
.ObjectMap
== null) {
655 BuildClassMap (fixup
.Map
, fixup
.TypeName
, fixup
.SchemaType
);
656 if (fixup
.Map
.ObjectMap
== null) pendingMaps
.Enqueue (fixup
);
661 void BuildPendingMap (XmlTypeMapping map
)
663 if (map
.ObjectMap
!= null) return;
665 foreach (MapFixup fixup
in pendingMaps
)
667 if (fixup
.Map
== map
) {
668 BuildClassMap (fixup
.Map
, fixup
.TypeName
, fixup
.SchemaType
);
672 throw new InvalidOperationException ("Can't complete map of type " + map
.XmlType
+ " : " + map
.Namespace
);
675 void BuildClassMap (XmlTypeMapping map
, XmlQualifiedName typeQName
, XmlSchemaComplexType stype
)
677 CodeIdentifiers classIds
= new CodeIdentifiers();
678 classIds
.AddReserved (map
.TypeData
.TypeName
);
680 ClassMap cmap
= new ClassMap ();
681 map
.ObjectMap
= cmap
;
682 bool isMixed
= stype
.IsMixed
;
684 if (stype
.Particle
!= null)
685 ImportParticleComplexContent (typeQName
, cmap
, stype
.Particle
, classIds
, isMixed
);
688 if (stype
.ContentModel
is XmlSchemaSimpleContent
) {
689 ImportSimpleContent (typeQName
, map
, (XmlSchemaSimpleContent
)stype
.ContentModel
, classIds
, isMixed
);
691 else if (stype
.ContentModel
is XmlSchemaComplexContent
) {
692 ImportComplexContent (typeQName
, map
, (XmlSchemaComplexContent
)stype
.ContentModel
, classIds
, isMixed
);
696 ImportAttributes (typeQName
, cmap
, stype
.Attributes
, stype
.AnyAttribute
, classIds
);
697 ImportExtensionTypes (typeQName
);
699 if (isMixed
) AddTextMember (typeQName
, cmap
, classIds
);
701 AddObjectDerivedMap (map
);
704 void ImportAttributes (XmlQualifiedName typeQName
, ClassMap cmap
, XmlSchemaObjectCollection atts
, XmlSchemaAnyAttribute anyat
, CodeIdentifiers classIds
)
706 atts
= CollectAttributeUsesNonOverlap (atts
, cmap
);
710 XmlTypeMapMemberAnyAttribute member
= new XmlTypeMapMemberAnyAttribute ();
711 member
.Name
= classIds
.AddUnique ("AnyAttribute", member
);
712 member
.TypeData
= TypeTranslator
.GetTypeData (typeof(XmlAttribute
[]));
713 cmap
.AddMember (member
);
716 foreach (XmlSchemaObject at
in atts
)
718 if (at
is XmlSchemaAttribute
)
721 XmlSchemaAttribute attr
= (XmlSchemaAttribute
)at
;
722 XmlSchemaAttribute refAttr
= GetRefAttribute (typeQName
, attr
, out ns
);
723 XmlTypeMapMemberAttribute member
= new XmlTypeMapMemberAttribute ();
724 member
.Name
= classIds
.AddUnique (CodeIdentifier
.MakeValid (refAttr
.Name
), member
);
725 member
.Documentation
= GetDocumentation (attr
);
726 member
.AttributeName
= refAttr
.Name
;
727 member
.Namespace
= ns
;
728 member
.Form
= refAttr
.Form
;
729 member
.TypeData
= GetAttributeTypeData (typeQName
, attr
);
731 if (refAttr
.DefaultValue
!= null)
732 member
.DefaultValue
= ImportDefaultValue (member
.TypeData
, refAttr
.DefaultValue
);
733 else if (member
.TypeData
.IsValueType
)
734 member
.IsOptionalValueType
= (refAttr
.ValidatedUse
!= XmlSchemaUse
.Required
);
736 if (member
.TypeData
.IsComplexType
)
737 member
.MappedType
= GetTypeMapping (member
.TypeData
);
738 cmap
.AddMember (member
);
740 else if (at
is XmlSchemaAttributeGroupRef
)
742 XmlSchemaAttributeGroupRef gref
= (XmlSchemaAttributeGroupRef
)at
;
743 XmlSchemaAttributeGroup grp
= FindRefAttributeGroup (gref
.RefName
);
744 ImportAttributes (typeQName
, cmap
, grp
.Attributes
, grp
.AnyAttribute
, classIds
);
749 // Attributes might be redefined, so there is an existing attribute for the same name, skip it.
750 // FIXME: this is nothing more than just a hack.
751 // Basically it should use
752 // XmlSchemaComplexType.AttributeUses.
753 XmlSchemaObjectCollection
CollectAttributeUsesNonOverlap (
754 XmlSchemaObjectCollection src
, ClassMap map
)
756 XmlSchemaObjectCollection atts
= new XmlSchemaObjectCollection ();
757 foreach (XmlSchemaAttribute a
in src
)
758 if (map
.GetAttribute (a
.QualifiedName
.Name
, a
.QualifiedName
.Namespace
) == null)
763 ListMap
BuildArrayMap (XmlQualifiedName typeQName
, XmlSchemaComplexType stype
, out TypeData arrayTypeData
)
767 XmlSchemaComplexContent content
= stype
.ContentModel
as XmlSchemaComplexContent
;
768 XmlSchemaComplexContentRestriction rest
= content
.Content
as XmlSchemaComplexContentRestriction
;
769 XmlSchemaAttribute arrayTypeAt
= FindArrayAttribute (rest
.Attributes
);
771 if (arrayTypeAt
!= null)
773 XmlAttribute
[] uatts
= arrayTypeAt
.UnhandledAttributes
;
774 if (uatts
== null || uatts
.Length
== 0) throw new InvalidOperationException ("arrayType attribute not specified in array declaration: " + typeQName
);
776 XmlAttribute xat
= null;
777 foreach (XmlAttribute at
in uatts
)
778 if (at
.LocalName
== "arrayType" && at
.NamespaceURI
== XmlSerializer
.WsdlNamespace
)
782 throw new InvalidOperationException ("arrayType attribute not specified in array declaration: " + typeQName
);
784 string name
, ns
, dims
;
785 TypeTranslator
.ParseArrayType (xat
.Value
, out name
, out ns
, out dims
);
786 return BuildEncodedArrayMap (name
+ dims
, ns
, out arrayTypeData
);
790 XmlSchemaElement elem
= null;
791 XmlSchemaSequence seq
= rest
.Particle
as XmlSchemaSequence
;
792 if (seq
!= null && seq
.Items
.Count
== 1)
793 elem
= seq
.Items
[0] as XmlSchemaElement
;
795 XmlSchemaAll all
= rest
.Particle
as XmlSchemaAll
;
796 if (all
!= null && all
.Items
.Count
== 1)
797 elem
= all
.Items
[0] as XmlSchemaElement
;
800 throw new InvalidOperationException ("Unknown array format");
802 return BuildEncodedArrayMap (elem
.SchemaTypeName
.Name
+ "[]", elem
.SchemaTypeName
.Namespace
, out arrayTypeData
);
807 ClassMap cmap
= new ClassMap ();
808 CodeIdentifiers classIds
= new CodeIdentifiers();
809 ImportParticleComplexContent (typeQName
, cmap
, stype
.Particle
, classIds
, stype
.IsMixed
);
811 XmlTypeMapMemberFlatList list
= (cmap
.AllMembers
.Count
== 1) ? cmap
.AllMembers
[0] as XmlTypeMapMemberFlatList
: null;
812 if (list
!= null && list
.ChoiceMember
== null)
814 arrayTypeData
= list
.TypeData
;
819 arrayTypeData
= null;
825 ListMap
BuildEncodedArrayMap (string type
, string ns
, out TypeData arrayTypeData
)
827 ListMap map
= new ListMap ();
829 int i
= type
.LastIndexOf ("[");
830 if (i
== -1) throw new InvalidOperationException ("Invalid arrayType value: " + type
);
831 if (type
.IndexOf (",",i
) != -1) throw new InvalidOperationException ("Multidimensional arrays are not supported");
833 string itemType
= type
.Substring (0,i
);
835 TypeData itemTypeData
;
836 if (itemType
.IndexOf ("[") != -1)
838 ListMap innerListMap
= BuildEncodedArrayMap (itemType
, ns
, out itemTypeData
);
840 int dims
= itemType
.Split ('[').Length
- 1;
841 string name
= TypeTranslator
.GetArrayName (type
, dims
);
842 XmlQualifiedName qname
= new XmlQualifiedName (name
, ns
);
843 XmlTypeMapping tmap
= CreateArrayTypeMapping (qname
, itemTypeData
);
844 tmap
.ObjectMap
= innerListMap
;
848 itemTypeData
= GetTypeData (new XmlQualifiedName (itemType
, ns
), null, false);
851 arrayTypeData
= itemTypeData
.ListTypeData
;
853 map
.ItemInfo
= new XmlTypeMapElementInfoList();
854 map
.ItemInfo
.Add (CreateElementInfo ("", null, "Item", itemTypeData
, true, XmlSchemaForm
.None
));
858 XmlSchemaAttribute
FindArrayAttribute (XmlSchemaObjectCollection atts
)
860 foreach (object ob
in atts
)
862 XmlSchemaAttribute att
= ob
as XmlSchemaAttribute
;
863 if (att
!= null && att
.RefName
== arrayTypeRefName
) return att
;
865 XmlSchemaAttributeGroupRef gref
= ob
as XmlSchemaAttributeGroupRef
;
868 XmlSchemaAttributeGroup grp
= FindRefAttributeGroup (gref
.RefName
);
869 att
= FindArrayAttribute (grp
.Attributes
);
870 if (att
!= null) return att
;
876 void ImportParticleComplexContent (XmlQualifiedName typeQName
, ClassMap cmap
, XmlSchemaParticle particle
, CodeIdentifiers classIds
, bool isMixed
)
878 ImportParticleContent (typeQName
, cmap
, particle
, classIds
, false, ref isMixed
);
879 if (isMixed
) AddTextMember (typeQName
, cmap
, classIds
);
882 void AddTextMember (XmlQualifiedName typeQName
, ClassMap cmap
, CodeIdentifiers classIds
)
884 if (cmap
.XmlTextCollector
== null)
886 XmlTypeMapMemberFlatList member
= new XmlTypeMapMemberFlatList ();
887 member
.Name
= classIds
.AddUnique ("Text", member
);
888 member
.TypeData
= TypeTranslator
.GetTypeData (typeof(string[]));
889 member
.ElementInfo
.Add (CreateTextElementInfo (typeQName
.Namespace
, member
, member
.TypeData
.ListItemTypeData
));
890 member
.IsXmlTextCollector
= true;
891 member
.ListMap
= new ListMap ();
892 member
.ListMap
.ItemInfo
= member
.ElementInfo
;
893 cmap
.AddMember (member
);
897 void ImportParticleContent (XmlQualifiedName typeQName
, ClassMap cmap
, XmlSchemaParticle particle
, CodeIdentifiers classIds
, bool multiValue
, ref bool isMixed
)
899 if (particle
== null) return;
901 if (particle
is XmlSchemaGroupRef
)
902 particle
= GetRefGroupParticle ((XmlSchemaGroupRef
)particle
);
904 if (particle
.MaxOccurs
> 1) multiValue
= true;
906 if (particle
is XmlSchemaSequence
) {
907 ImportSequenceContent (typeQName
, cmap
, ((XmlSchemaSequence
)particle
).Items
, classIds
, multiValue
, ref isMixed
);
909 else if (particle
is XmlSchemaChoice
) {
910 if (((XmlSchemaChoice
)particle
).Items
.Count
== 1)
911 ImportSequenceContent (typeQName
, cmap
, ((XmlSchemaChoice
)particle
).Items
, classIds
, multiValue
, ref isMixed
);
913 ImportChoiceContent (typeQName
, cmap
, (XmlSchemaChoice
)particle
, classIds
, multiValue
);
915 else if (particle
is XmlSchemaAll
) {
916 ImportSequenceContent (typeQName
, cmap
, ((XmlSchemaAll
)particle
).Items
, classIds
, multiValue
, ref isMixed
);
920 void ImportSequenceContent (XmlQualifiedName typeQName
, ClassMap cmap
, XmlSchemaObjectCollection items
, CodeIdentifiers classIds
, bool multiValue
, ref bool isMixed
)
922 foreach (XmlSchemaObject item
in items
)
924 if (item
is XmlSchemaElement
)
927 XmlSchemaElement elem
= (XmlSchemaElement
) item
;
929 TypeData typeData
= GetElementTypeData (typeQName
, elem
, null, out emap
);
930 XmlSchemaElement refElem
= GetRefElement (typeQName
, elem
, out ns
);
932 if (elem
.MaxOccurs
== 1 && !multiValue
)
934 XmlTypeMapMemberElement member
= null;
935 if (typeData
.SchemaType
!= SchemaTypes
.Array
)
937 member
= new XmlTypeMapMemberElement ();
938 if (refElem
.DefaultValue
!= null) member
.DefaultValue
= ImportDefaultValue (typeData
, refElem
.DefaultValue
);
940 else if (GetTypeMapping (typeData
).IsSimpleType
)
942 // It is a simple list (space separated list).
943 // Since this is not supported, map as a single item value
944 member
= new XmlTypeMapMemberElement ();
946 // In MS.NET those types are mapped to a string
947 typeData
= TypeTranslator
.GetTypeData(typeof(string));
949 typeData
= typeData
.ListItemTypeData
;
953 member
= new XmlTypeMapMemberList ();
955 if (elem
.MinOccurs
== 0 && typeData
.IsValueType
)
956 member
.IsOptionalValueType
= true;
958 member
.Name
= classIds
.AddUnique(CodeIdentifier
.MakeValid(refElem
.Name
), member
);
959 member
.Documentation
= GetDocumentation (elem
);
960 member
.TypeData
= typeData
;
961 member
.ElementInfo
.Add (CreateElementInfo (ns
, member
, refElem
.Name
, typeData
, refElem
.IsNillable
, refElem
.Form
, emap
));
962 cmap
.AddMember (member
);
966 XmlTypeMapMemberFlatList member
= new XmlTypeMapMemberFlatList ();
967 member
.ListMap
= new ListMap ();
968 member
.Name
= classIds
.AddUnique(CodeIdentifier
.MakeValid(refElem
.Name
), member
);
969 member
.Documentation
= GetDocumentation (elem
);
970 member
.TypeData
= typeData
.ListTypeData
;
971 member
.ElementInfo
.Add (CreateElementInfo (ns
, member
, refElem
.Name
, typeData
, refElem
.IsNillable
, refElem
.Form
, emap
));
972 member
.ListMap
.ItemInfo
= member
.ElementInfo
;
973 cmap
.AddMember (member
);
976 else if (item
is XmlSchemaAny
)
978 XmlSchemaAny elem
= (XmlSchemaAny
) item
;
979 XmlTypeMapMemberAnyElement member
= new XmlTypeMapMemberAnyElement ();
980 member
.Name
= classIds
.AddUnique ("Any", member
);
981 member
.Documentation
= GetDocumentation (elem
);
984 if (elem
.MaxOccurs
!= 1 || multiValue
)
985 ctype
= isMixed
? typeof(XmlNode
[]) : typeof(XmlElement
[]);
987 ctype
= isMixed
? typeof(XmlNode
) : typeof(XmlElement
);
989 member
.TypeData
= TypeTranslator
.GetTypeData (ctype
);
990 XmlTypeMapElementInfo einfo
= new XmlTypeMapElementInfo (member
, member
.TypeData
);
991 einfo
.IsUnnamedAnyElement
= true;
992 member
.ElementInfo
.Add (einfo
);
996 einfo
= CreateTextElementInfo (typeQName
.Namespace
, member
, member
.TypeData
);
997 member
.ElementInfo
.Add (einfo
);
998 member
.IsXmlTextCollector
= true;
999 isMixed
= false; //Allow only one XmlTextAttribute
1002 cmap
.AddMember (member
);
1004 else if (item
is XmlSchemaParticle
) {
1005 ImportParticleContent (typeQName
, cmap
, (XmlSchemaParticle
)item
, classIds
, multiValue
, ref isMixed
);
1010 object ImportDefaultValue (TypeData typeData
, string value)
1012 if (typeData
.SchemaType
== SchemaTypes
.Enum
) {
1013 XmlTypeMapping map
= GetTypeMapping (typeData
);
1014 EnumMap emap
= (EnumMap
) map
.ObjectMap
;
1015 string res
= emap
.GetEnumName (map
.TypeFullName
, value);
1016 if (res
== null) throw new InvalidOperationException ("'" + value + "' is not a valid enumeration value");
1019 return XmlCustomFormatter
.FromXmlString (typeData
, value);
1022 void ImportChoiceContent (XmlQualifiedName typeQName
, ClassMap cmap
, XmlSchemaChoice choice
, CodeIdentifiers classIds
, bool multiValue
)
1024 XmlTypeMapElementInfoList choices
= new XmlTypeMapElementInfoList ();
1025 multiValue
= ImportChoices (typeQName
, null, choices
, choice
.Items
) || multiValue
;
1026 if (choices
.Count
== 0) return;
1028 if (choice
.MaxOccurs
> 1) multiValue
= true;
1030 XmlTypeMapMemberElement member
;
1033 member
= new XmlTypeMapMemberFlatList ();
1034 member
.Name
= classIds
.AddUnique ("Items", member
);
1035 ListMap listMap
= new ListMap ();
1036 listMap
.ItemInfo
= choices
;
1037 ((XmlTypeMapMemberFlatList
)member
).ListMap
= listMap
;
1041 member
= new XmlTypeMapMemberElement ();
1042 member
.Name
= classIds
.AddUnique ("Item", member
);
1045 // If all choices have the same type, use that type for the member.
1046 // If not use System.Object.
1047 // If there are at least two choices with the same type, use a choice
1048 // identifier attribute
1050 TypeData typeData
= null;
1051 bool twoEqual
= false;
1052 bool allEqual
= true;
1053 Hashtable types
= new Hashtable ();
1055 for (int n
= choices
.Count
- 1; n
>= 0; n
--)
1057 XmlTypeMapElementInfo einfo
= (XmlTypeMapElementInfo
) choices
[n
];
1059 // In some complex schemas, we may end up with several options
1060 // with the same name. It is better to ignore the extra options
1061 // than to crash. It's the best we can do, and btw it works
1062 // better than in MS.NET.
1064 if (cmap
.GetElement (einfo
.ElementName
, einfo
.Namespace
) != null ||
1065 choices
.IndexOfElement (einfo
.ElementName
, einfo
.Namespace
) != n
)
1067 choices
.RemoveAt (n
);
1071 if (types
.ContainsKey (einfo
.TypeData
)) twoEqual
= true;
1072 else types
.Add (einfo
.TypeData
, einfo
);
1074 TypeData choiceType
= einfo
.TypeData
;
1075 if (choiceType
.SchemaType
== SchemaTypes
.Class
)
1077 // When comparing class types, use the most generic class in the
1078 // inheritance hierarchy
1080 XmlTypeMapping choiceMap
= GetTypeMapping (choiceType
);
1081 BuildPendingMap (choiceMap
);
1082 while (choiceMap
.BaseMap
!= null) {
1083 choiceMap
= choiceMap
.BaseMap
;
1084 BuildPendingMap (choiceMap
);
1085 choiceType
= choiceMap
.TypeData
;
1089 if (typeData
== null) typeData
= choiceType
;
1090 else if (typeData
!= choiceType
) allEqual
= false;
1094 typeData
= TypeTranslator
.GetTypeData (typeof(object));
1098 // Create the choice member
1099 XmlTypeMapMemberElement choiceMember
= new XmlTypeMapMemberElement ();
1100 choiceMember
.Ignore
= true;
1101 choiceMember
.Name
= classIds
.AddUnique (member
.Name
+ "ElementName", choiceMember
);
1102 member
.ChoiceMember
= choiceMember
.Name
;
1104 // Create the choice enum
1105 XmlTypeMapping enumMap
= CreateTypeMapping (new XmlQualifiedName (member
.Name
+ "ChoiceType", typeQName
.Namespace
), SchemaTypes
.Enum
, null);
1106 enumMap
.IncludeInSchema
= false;
1108 CodeIdentifiers codeIdents
= new CodeIdentifiers ();
1109 EnumMap
.EnumMapMember
[] members
= new EnumMap
.EnumMapMember
[choices
.Count
];
1110 for (int n
=0; n
<choices
.Count
; n
++)
1112 XmlTypeMapElementInfo it
=(XmlTypeMapElementInfo
) choices
[n
];
1113 bool extraNs
= (it
.Namespace
!= null && it
.Namespace
!= "" && it
.Namespace
!= typeQName
.Namespace
);
1114 string xmlName
= extraNs
? it
.Namespace
+ ":" + it
.ElementName
: it
.ElementName
;
1115 string enumName
= codeIdents
.AddUnique (CodeIdentifier
.MakeValid (it
.ElementName
), it
);
1116 members
[n
] = new EnumMap
.EnumMapMember (xmlName
, enumName
);
1118 enumMap
.ObjectMap
= new EnumMap (members
, false);
1120 choiceMember
.TypeData
= multiValue
? enumMap
.TypeData
.ListTypeData
: enumMap
.TypeData
;
1121 choiceMember
.ElementInfo
.Add (CreateElementInfo (typeQName
.Namespace
, choiceMember
, choiceMember
.Name
, choiceMember
.TypeData
, false, XmlSchemaForm
.None
));
1122 cmap
.AddMember (choiceMember
);
1125 if (typeData
== null)
1129 typeData
= typeData
.ListTypeData
;
1131 member
.ElementInfo
= choices
;
1132 member
.Documentation
= GetDocumentation (choice
);
1133 member
.TypeData
= typeData
;
1134 cmap
.AddMember (member
);
1137 bool ImportChoices (XmlQualifiedName typeQName
, XmlTypeMapMember member
, XmlTypeMapElementInfoList choices
, XmlSchemaObjectCollection items
)
1139 bool multiValue
= false;
1140 foreach (XmlSchemaObject titem
in items
)
1142 XmlSchemaObject item
= titem
;
1143 if (item
is XmlSchemaGroupRef
)
1144 item
= GetRefGroupParticle ((XmlSchemaGroupRef
)item
);
1146 if (item
is XmlSchemaElement
)
1149 XmlSchemaElement elem
= (XmlSchemaElement
) item
;
1150 XmlTypeMapping emap
;
1151 TypeData typeData
= GetElementTypeData (typeQName
, elem
, null, out emap
);
1152 XmlSchemaElement refElem
= GetRefElement (typeQName
, elem
, out ns
);
1153 choices
.Add (CreateElementInfo (ns
, member
, refElem
.Name
, typeData
, refElem
.IsNillable
, refElem
.Form
, emap
));
1154 if (elem
.MaxOccurs
> 1) multiValue
= true;
1156 else if (item
is XmlSchemaAny
)
1158 XmlTypeMapElementInfo einfo
= new XmlTypeMapElementInfo (member
, TypeTranslator
.GetTypeData(typeof(XmlElement
)));
1159 einfo
.IsUnnamedAnyElement
= true;
1160 choices
.Add (einfo
);
1162 else if (item
is XmlSchemaChoice
) {
1163 multiValue
= ImportChoices (typeQName
, member
, choices
, ((XmlSchemaChoice
)item
).Items
) || multiValue
;
1165 else if (item
is XmlSchemaSequence
) {
1166 multiValue
= ImportChoices (typeQName
, member
, choices
, ((XmlSchemaSequence
)item
).Items
) || multiValue
;
1172 void ImportSimpleContent (XmlQualifiedName typeQName
, XmlTypeMapping map
, XmlSchemaSimpleContent content
, CodeIdentifiers classIds
, bool isMixed
)
1174 XmlSchemaSimpleContentExtension ext
= content
.Content
as XmlSchemaSimpleContentExtension
;
1175 ClassMap cmap
= (ClassMap
)map
.ObjectMap
;
1176 XmlQualifiedName qname
= GetContentBaseType (content
.Content
);
1177 TypeData simpleType
= null;
1179 if (!IsPrimitiveTypeNamespace (qname
.Namespace
))
1181 // Add base map members to this map
1183 XmlTypeMapping baseMap
= ImportType (qname
, null, true);
1184 BuildPendingMap (baseMap
);
1186 if (baseMap
.IsSimpleType
) {
1187 simpleType
= baseMap
.TypeData
;
1189 ClassMap baseClassMap
= (ClassMap
)baseMap
.ObjectMap
;
1191 foreach (XmlTypeMapMember member
in baseClassMap
.AllMembers
)
1192 cmap
.AddMember (member
);
1194 map
.BaseMap
= baseMap
;
1195 baseMap
.DerivedTypes
.Add (map
);
1199 simpleType
= FindBuiltInType (qname
);
1201 if (simpleType
!= null) {
1202 XmlTypeMapMemberElement member
= new XmlTypeMapMemberElement ();
1203 member
.Name
= classIds
.AddUnique("Value", member
);
1204 member
.TypeData
= simpleType
;
1205 member
.ElementInfo
.Add (CreateTextElementInfo (typeQName
.Namespace
, member
, member
.TypeData
));
1206 member
.IsXmlTextCollector
= true;
1207 cmap
.AddMember (member
);
1211 ImportAttributes (typeQName
, cmap
, ext
.Attributes
, ext
.AnyAttribute
, classIds
);
1214 TypeData
FindBuiltInType (XmlQualifiedName qname
)
1216 XmlSchemaComplexType ct
= (XmlSchemaComplexType
) schemas
.Find (qname
, typeof(XmlSchemaComplexType
));
1219 XmlSchemaSimpleContent sc
= ct
.ContentModel
as XmlSchemaSimpleContent
;
1220 if (sc
== null) throw new InvalidOperationException ("Invalid schema");
1221 return FindBuiltInType (GetContentBaseType (sc
.Content
));
1224 XmlSchemaSimpleType st
= (XmlSchemaSimpleType
) schemas
.Find (qname
, typeof(XmlSchemaSimpleType
));
1226 return FindBuiltInType (qname
, st
);
1228 if (IsPrimitiveTypeNamespace (qname
.Namespace
))
1229 return TypeTranslator
.GetPrimitiveTypeData (qname
.Name
);
1231 throw new InvalidOperationException ("Definition of type '" + qname
+ "' not found");
1234 TypeData
FindBuiltInType (XmlQualifiedName qname
, XmlSchemaSimpleType st
)
1236 if (CanBeEnum (st
) && qname
!= null)
1237 return ImportType (qname
, null, true).TypeData
;
1239 if (st
.Content
is XmlSchemaSimpleTypeRestriction
) {
1240 XmlSchemaSimpleTypeRestriction rest
= (XmlSchemaSimpleTypeRestriction
) st
.Content
;
1241 XmlQualifiedName bn
= GetContentBaseType (rest
);
1242 if (bn
== XmlQualifiedName
.Empty
&& rest
.BaseType
!= null)
1243 return FindBuiltInType (qname
, rest
.BaseType
);
1245 return FindBuiltInType (bn
);
1247 else if (st
.Content
is XmlSchemaSimpleTypeList
) {
1248 return FindBuiltInType (GetContentBaseType (st
.Content
)).ListTypeData
;
1250 else if (st
.Content
is XmlSchemaSimpleTypeUnion
) {
1251 // MS.NET always import simple unions as string
1252 return FindBuiltInType (new XmlQualifiedName ("string", XmlSchema
.Namespace
));
1258 XmlQualifiedName
GetContentBaseType (XmlSchemaObject ob
)
1260 if (ob
is XmlSchemaSimpleContentExtension
)
1261 return ((XmlSchemaSimpleContentExtension
)ob
).BaseTypeName
;
1262 else if (ob
is XmlSchemaSimpleContentRestriction
)
1263 return ((XmlSchemaSimpleContentRestriction
)ob
).BaseTypeName
;
1264 else if (ob
is XmlSchemaSimpleTypeRestriction
)
1265 return ((XmlSchemaSimpleTypeRestriction
)ob
).BaseTypeName
;
1266 else if (ob
is XmlSchemaSimpleTypeList
)
1267 return ((XmlSchemaSimpleTypeList
)ob
).ItemTypeName
;
1272 void ImportComplexContent (XmlQualifiedName typeQName
, XmlTypeMapping map
, XmlSchemaComplexContent content
, CodeIdentifiers classIds
, bool isMixed
)
1274 ClassMap cmap
= (ClassMap
)map
.ObjectMap
;
1275 XmlQualifiedName qname
;
1277 XmlSchemaComplexContentExtension ext
= content
.Content
as XmlSchemaComplexContentExtension
;
1278 if (ext
!= null) qname
= ext
.BaseTypeName
;
1279 else qname
= ((XmlSchemaComplexContentRestriction
)content
.Content
).BaseTypeName
;
1281 if (qname
== typeQName
)
1282 throw new InvalidOperationException ("Cannot import schema for type '" + typeQName
.Name
+ "' from namespace '" + typeQName
.Namespace
+ "'. Redefine not supported");
1284 // Add base map members to this map
1286 XmlTypeMapping baseMap
= ImportClass (qname
);
1287 BuildPendingMap (baseMap
);
1288 ClassMap baseClassMap
= (ClassMap
)baseMap
.ObjectMap
;
1290 foreach (XmlTypeMapMember member
in baseClassMap
.AllMembers
)
1291 cmap
.AddMember (member
);
1293 if (baseClassMap
.XmlTextCollector
!= null) isMixed
= false;
1294 else if (content
.IsMixed
) isMixed
= true;
1296 map
.BaseMap
= baseMap
;
1297 baseMap
.DerivedTypes
.Add (map
);
1300 // Add the members of this map
1301 ImportParticleComplexContent (typeQName
, cmap
, ext
.Particle
, classIds
, isMixed
);
1302 ImportAttributes (typeQName
, cmap
, ext
.Attributes
, ext
.AnyAttribute
, classIds
);
1305 if (isMixed
) ImportParticleComplexContent (typeQName
, cmap
, null, classIds
, true);
1309 void ImportExtensionTypes (XmlQualifiedName qname
)
1311 foreach (XmlSchema schema
in schemas
) {
1312 foreach (XmlSchemaObject sob
in schema
.Items
)
1314 XmlSchemaComplexType sct
= sob
as XmlSchemaComplexType
;
1315 if (sct
!= null && sct
.ContentModel
is XmlSchemaComplexContent
) {
1316 XmlQualifiedName exqname
;
1317 XmlSchemaComplexContentExtension ext
= sct
.ContentModel
.Content
as XmlSchemaComplexContentExtension
;
1318 if (ext
!= null) exqname
= ext
.BaseTypeName
;
1319 else exqname
= ((XmlSchemaComplexContentRestriction
)sct
.ContentModel
.Content
).BaseTypeName
;
1320 if (exqname
== qname
)
1321 ImportType (new XmlQualifiedName (sct
.Name
, schema
.TargetNamespace
), sct
, null);
1327 XmlTypeMapping
ImportClassSimpleType (XmlQualifiedName typeQName
, XmlSchemaSimpleType stype
, XmlQualifiedName root
)
1329 if (CanBeEnum (stype
))
1331 // Create an enum map
1333 CodeIdentifiers codeIdents
= new CodeIdentifiers ();
1334 XmlTypeMapping enumMap
= CreateTypeMapping (typeQName
, SchemaTypes
.Enum
, root
);
1335 enumMap
.Documentation
= GetDocumentation (stype
);
1337 bool isFlags
= false;
1338 if (stype
.Content
is XmlSchemaSimpleTypeList
) {
1339 stype
= ((XmlSchemaSimpleTypeList
)stype
.Content
).ItemType
;
1342 XmlSchemaSimpleTypeRestriction rest
= (XmlSchemaSimpleTypeRestriction
)stype
.Content
;
1344 codeIdents
.AddReserved (enumMap
.TypeData
.TypeName
);
1346 EnumMap
.EnumMapMember
[] members
= new EnumMap
.EnumMapMember
[rest
.Facets
.Count
];
1347 for (int n
=0; n
<rest
.Facets
.Count
; n
++)
1349 XmlSchemaEnumerationFacet enu
= (XmlSchemaEnumerationFacet
) rest
.Facets
[n
];
1350 string enumName
= codeIdents
.AddUnique(CodeIdentifier
.MakeValid (enu
.Value
), enu
);
1351 members
[n
] = new EnumMap
.EnumMapMember (enu
.Value
, enumName
);
1352 members
[n
].Documentation
= GetDocumentation (enu
);
1354 enumMap
.ObjectMap
= new EnumMap (members
, isFlags
);
1355 enumMap
.IsSimpleType
= true;
1359 if (stype
.Content
is XmlSchemaSimpleTypeList
)
1361 XmlSchemaSimpleTypeList slist
= (XmlSchemaSimpleTypeList
)stype
.Content
;
1362 TypeData arrayTypeData
= FindBuiltInType (slist
.ItemTypeName
, stype
);
1364 ListMap listMap
= new ListMap ();
1366 listMap
.ItemInfo
= new XmlTypeMapElementInfoList ();
1367 listMap
.ItemInfo
.Add (CreateElementInfo (typeQName
.Namespace
, null, "Item", arrayTypeData
.ListItemTypeData
, false, XmlSchemaForm
.None
));
1369 XmlTypeMapping map
= CreateArrayTypeMapping (typeQName
, arrayTypeData
);
1370 map
.ObjectMap
= listMap
;
1371 map
.IsSimpleType
= true;
1375 // It is an extension of a primitive or known type
1377 TypeData typeData
= FindBuiltInType (typeQName
, stype
);
1378 XmlTypeMapping rmap
= GetTypeMapping (typeData
);
1380 // The resulting map must be a simple type. It needs to be explicitely set for arrays
1381 rmap
.IsSimpleType
= true;
1385 bool CanBeEnum (XmlSchemaSimpleType stype
)
1387 if (stype
.Content
is XmlSchemaSimpleTypeRestriction
)
1389 XmlSchemaSimpleTypeRestriction rest
= (XmlSchemaSimpleTypeRestriction
)stype
.Content
;
1390 if (rest
.Facets
.Count
== 0) return false;
1391 foreach (object ob
in rest
.Facets
)
1392 if (!(ob
is XmlSchemaEnumerationFacet
)) return false;
1395 else if (stype
.Content
is XmlSchemaSimpleTypeList
)
1397 XmlSchemaSimpleTypeList list
= (XmlSchemaSimpleTypeList
) stype
.Content
;
1398 return (list
.ItemType
!= null && CanBeEnum (list
.ItemType
));
1403 bool CanBeArray (XmlQualifiedName typeQName
, XmlSchemaComplexType stype
)
1407 XmlSchemaComplexContent content
= stype
.ContentModel
as XmlSchemaComplexContent
;
1408 if (content
== null) return false;
1409 XmlSchemaComplexContentRestriction rest
= content
.Content
as XmlSchemaComplexContentRestriction
;
1410 if (rest
== null) return false;
1411 return rest
.BaseTypeName
== arrayType
;
1415 if (stype
.Attributes
.Count
> 0 || stype
.AnyAttribute
!= null) return false;
1416 else return !stype
.IsMixed
&& CanBeArray (typeQName
, stype
.Particle
, false);
1420 bool CanBeArray (XmlQualifiedName typeQName
, XmlSchemaParticle particle
, bool multiValue
)
1422 // To be an array, there can't be a direct child of type typeQName
1424 if (particle
== null) return false;
1426 multiValue
= multiValue
|| particle
.MaxOccurs
> 1;
1428 if (particle
is XmlSchemaGroupRef
)
1429 return CanBeArray (typeQName
, GetRefGroupParticle ((XmlSchemaGroupRef
)particle
), multiValue
);
1431 if (particle
is XmlSchemaElement
)
1433 XmlSchemaElement elem
= (XmlSchemaElement
)particle
;
1434 if (!elem
.RefName
.IsEmpty
)
1435 return CanBeArray (typeQName
, FindRefElement (elem
), multiValue
);
1437 return multiValue
&& !typeQName
.Equals (((XmlSchemaElement
)particle
).SchemaTypeName
);
1440 if (particle
is XmlSchemaAny
)
1443 if (particle
is XmlSchemaSequence
)
1445 XmlSchemaSequence seq
= particle
as XmlSchemaSequence
;
1446 if (seq
.Items
.Count
!= 1) return false;
1447 return CanBeArray (typeQName
, (XmlSchemaParticle
)seq
.Items
[0], multiValue
);
1450 if (particle
is XmlSchemaChoice
)
1452 // Can be array if all choices have different types
1453 ArrayList types
= new ArrayList ();
1454 if(!CheckChoiceType (typeQName
, particle
, types
, ref multiValue
)) return false;
1461 bool CheckChoiceType (XmlQualifiedName typeQName
, XmlSchemaParticle particle
, ArrayList types
, ref bool multiValue
)
1463 XmlQualifiedName type
= null;
1465 multiValue
= multiValue
|| particle
.MaxOccurs
> 1;
1467 if (particle
is XmlSchemaGroupRef
)
1468 return CheckChoiceType (typeQName
, GetRefGroupParticle ((XmlSchemaGroupRef
)particle
), types
, ref multiValue
);
1470 if (particle
is XmlSchemaElement
) {
1472 XmlSchemaElement elem
= (XmlSchemaElement
)particle
;
1473 XmlSchemaElement refElem
= GetRefElement (typeQName
, elem
, out ns
);
1474 if (refElem
.SchemaType
!= null) return true;
1475 type
= refElem
.SchemaTypeName
;
1477 else if (particle
is XmlSchemaAny
) {
1480 else if (particle
is XmlSchemaSequence
)
1482 XmlSchemaSequence seq
= particle
as XmlSchemaSequence
;
1483 foreach (XmlSchemaParticle par
in seq
.Items
)
1484 if (!CheckChoiceType (typeQName
, par
, types
, ref multiValue
)) return false;
1487 else if (particle
is XmlSchemaChoice
)
1489 foreach (XmlSchemaParticle choice
in ((XmlSchemaChoice
)particle
).Items
)
1490 if (!CheckChoiceType (typeQName
, choice
, types
, ref multiValue
)) return false;
1494 if (typeQName
.Equals (type
)) return false;
1496 // For primitive types, compare using CLR types, since several
1497 // xml types can be mapped to a single CLR type
1500 if (IsPrimitiveTypeNamespace (type
.Namespace
))
1501 t
= TypeTranslator
.GetPrimitiveTypeData (type
.Name
).FullTypeName
+ ":" + type
.Namespace
;
1504 t
= type
.Name
+ ":" + type
.Namespace
;
1506 if (types
.Contains (t
)) return false;
1511 bool CanBeAnyElement (XmlSchemaComplexType stype
)
1513 XmlSchemaSequence seq
= stype
.Particle
as XmlSchemaSequence
;
1514 return (seq
!= null) && (seq
.Items
.Count
== 1) && (seq
.Items
[0] is XmlSchemaAny
);
1517 Type
GetAnyElementType (XmlSchemaComplexType stype
)
1519 XmlSchemaSequence seq
= stype
.Particle
as XmlSchemaSequence
;
1521 if ((seq
== null) || (seq
.Items
.Count
!= 1) || !(seq
.Items
[0] is XmlSchemaAny
))
1525 return typeof(object);
1527 XmlSchemaAny any
= seq
.Items
[0] as XmlSchemaAny
;
1528 if (any
.MaxOccurs
== 1)
1531 return typeof(XmlNode
);
1533 return typeof(XmlElement
);
1538 return typeof(XmlNode
[]);
1540 return typeof(XmlElement
[]);
1544 bool CanBeIXmlSerializable (XmlSchemaComplexType stype
)
1546 XmlSchemaSequence seq
= stype
.Particle
as XmlSchemaSequence
;
1547 if (seq
== null) return false;
1548 if (seq
.Items
.Count
!= 2) return false;
1549 XmlSchemaElement elem
= seq
.Items
[0] as XmlSchemaElement
;
1550 if (elem
== null) return false;
1551 if (elem
.RefName
!= new XmlQualifiedName ("schema",XmlSchema
.Namespace
)) return false;
1552 return (seq
.Items
[1] is XmlSchemaAny
);
1555 XmlTypeMapping
ImportXmlSerializableMapping (string ns
)
1557 XmlQualifiedName qname
= new XmlQualifiedName ("System.Data.DataSet",ns
);
1558 XmlTypeMapping map
= GetRegisteredTypeMapping (qname
);
1559 if (map
!= null) return map
;
1561 TypeData typeData
= new TypeData ("System.Data.DataSet", "System.Data.DataSet", "System.Data.DataSet", SchemaTypes
.XmlSerializable
, null);
1562 map
= new XmlTypeMapping ("System.Data.DataSet", "", typeData
, "System.Data.DataSet", ns
);
1563 map
.IncludeInSchema
= true;
1564 RegisterTypeMapping (qname
, typeData
, map
);
1568 XmlTypeMapElementInfo
CreateElementInfo (string ns
, XmlTypeMapMember member
, string name
, TypeData typeData
, bool isNillable
, XmlSchemaForm form
)
1570 if (typeData
.IsComplexType
)
1571 return CreateElementInfo (ns
, member
, name
, typeData
, isNillable
, form
, GetTypeMapping (typeData
));
1573 return CreateElementInfo (ns
, member
, name
, typeData
, isNillable
, form
, null);
1576 XmlTypeMapElementInfo
CreateElementInfo (string ns
, XmlTypeMapMember member
, string name
, TypeData typeData
, bool isNillable
, XmlSchemaForm form
, XmlTypeMapping emap
)
1578 XmlTypeMapElementInfo einfo
= new XmlTypeMapElementInfo (member
, typeData
);
1579 einfo
.ElementName
= name
;
1580 einfo
.Namespace
= ns
;
1581 einfo
.IsNullable
= isNillable
;
1583 if (typeData
.IsComplexType
)
1584 einfo
.MappedType
= emap
;
1588 XmlTypeMapElementInfo
CreateTextElementInfo (string ns
, XmlTypeMapMember member
, TypeData typeData
)
1590 XmlTypeMapElementInfo einfo
= new XmlTypeMapElementInfo (member
, typeData
);
1591 einfo
.IsTextElement
= true;
1592 einfo
.WrappedElement
= false;
1593 if (typeData
.IsComplexType
)
1594 einfo
.MappedType
= GetTypeMapping (typeData
);
1598 XmlTypeMapping
CreateTypeMapping (XmlQualifiedName typeQName
, SchemaTypes schemaType
, XmlQualifiedName root
)
1600 string typeName
= CodeIdentifier
.MakeValid (typeQName
.Name
);
1601 typeName
= typeIdentifiers
.AddUnique (typeName
, null);
1603 TypeData typeData
= new TypeData (typeName
, typeName
, typeName
, schemaType
, null);
1608 rootElem
= root
.Name
;
1609 rootNs
= root
.Namespace
;
1612 rootElem
= typeQName
.Name
;
1616 XmlTypeMapping map
= new XmlTypeMapping (rootElem
, rootNs
, typeData
, typeQName
.Name
, typeQName
.Namespace
);
1617 map
.IncludeInSchema
= true;
1618 RegisterTypeMapping (typeQName
, typeData
, map
);
1623 XmlTypeMapping
CreateArrayTypeMapping (XmlQualifiedName typeQName
, TypeData arrayTypeData
)
1626 if (encodedFormat
) map
= new XmlTypeMapping ("Array", XmlSerializer
.EncodingNamespace
, arrayTypeData
, "Array", XmlSerializer
.EncodingNamespace
);
1627 else map
= new XmlTypeMapping (arrayTypeData
.XmlType
, typeQName
.Namespace
, arrayTypeData
, arrayTypeData
.XmlType
, typeQName
.Namespace
);
1629 map
.IncludeInSchema
= true;
1630 RegisterTypeMapping (typeQName
, arrayTypeData
, map
);
1635 XmlSchemaElement
GetRefElement (XmlQualifiedName typeQName
, XmlSchemaElement elem
, out string ns
)
1638 if (!elem
.RefName
.IsEmpty
)
1640 ns
= elem
.RefName
.Namespace
;
1641 return FindRefElement (elem
);
1645 ns
= typeQName
.Namespace
;
1650 XmlSchemaAttribute
GetRefAttribute (XmlQualifiedName typeQName
, XmlSchemaAttribute attr
, out string ns
)
1652 if (!attr
.RefName
.IsEmpty
)
1654 ns
= attr
.RefName
.Namespace
;
1655 XmlSchemaAttribute at
= FindRefAttribute (attr
.RefName
);
1656 if (at
== null) throw new InvalidOperationException ("The attribute " + attr
.RefName
+ " is missing");
1661 ns
= attr
.ParentIsSchema
? typeQName
.Namespace
: String
.Empty
;
1666 TypeData
GetElementTypeData (XmlQualifiedName typeQName
, XmlSchemaElement elem
, XmlQualifiedName root
, out XmlTypeMapping map
)
1668 bool sharedAnnType
= false;
1671 if (!elem
.RefName
.IsEmpty
) {
1672 XmlSchemaElement refElem
= FindRefElement (elem
);
1673 if (refElem
== null) throw new InvalidOperationException ("Global element not found: " + elem
.RefName
);
1674 root
= elem
.RefName
;
1676 sharedAnnType
= true;
1680 if (!elem
.SchemaTypeName
.IsEmpty
) {
1681 td
= GetTypeData (elem
.SchemaTypeName
, root
, elem
.IsNillable
);
1682 map
= GetRegisteredTypeMapping (td
);
1684 else if (elem
.SchemaType
== null)
1685 td
= TypeTranslator
.GetTypeData (typeof(object));
1687 td
= GetTypeData (elem
.SchemaType
, typeQName
, elem
.Name
, sharedAnnType
, root
);
1689 if (map
== null && td
.IsComplexType
)
1690 map
= GetTypeMapping (td
);
1695 TypeData
GetAttributeTypeData (XmlQualifiedName typeQName
, XmlSchemaAttribute attr
)
1697 bool sharedAnnType
= false;
1699 if (!attr
.RefName
.IsEmpty
) {
1700 XmlSchemaAttribute refAtt
= FindRefAttribute (attr
.RefName
);
1701 if (refAtt
== null) throw new InvalidOperationException ("Global attribute not found: " + attr
.RefName
);
1703 sharedAnnType
= true;
1706 if (!attr
.SchemaTypeName
.IsEmpty
) return GetTypeData (attr
.SchemaTypeName
, null, false);
1707 if (attr
.SchemaType
== null) return TypeTranslator
.GetTypeData (typeof(string));
1708 else return GetTypeData (attr
.SchemaType
, typeQName
, attr
.Name
, sharedAnnType
, null);
1711 TypeData
GetTypeData (XmlQualifiedName typeQName
, XmlQualifiedName root
, bool isNullable
)
1713 if (IsPrimitiveTypeNamespace (typeQName
.Namespace
)) {
1714 XmlTypeMapping map
= ImportType (typeQName
, root
, false);
1715 if (map
!= null) return map
.TypeData
;
1716 else return TypeTranslator
.GetPrimitiveTypeData (typeQName
.Name
, isNullable
);
1719 if (encodedFormat
&& typeQName
.Namespace
== "")
1720 return TypeTranslator
.GetPrimitiveTypeData (typeQName
.Name
);
1722 return ImportType (typeQName
, root
, true).TypeData
;
1725 TypeData
GetTypeData (XmlSchemaType stype
, XmlQualifiedName typeQNname
, string propertyName
, bool sharedAnnType
, XmlQualifiedName root
)
1731 // Anonymous types defined in root elements or attributes can be shared among all elements that
1732 // reference this root element or attribute
1733 TypeData std
= sharedAnonymousTypes
[stype
] as TypeData
;
1734 if (std
!= null) return std
;
1735 baseName
= propertyName
;
1738 baseName
= typeQNname
.Name
+ typeIdentifiers
.MakeRightCase (propertyName
);
1740 baseName
= elemIdentifiers
.AddUnique (baseName
, stype
);
1742 XmlQualifiedName newName
;
1743 newName
= new XmlQualifiedName (baseName
, typeQNname
.Namespace
);
1745 XmlTypeMapping map
= ImportType (newName
, stype
, root
);
1746 if (sharedAnnType
) sharedAnonymousTypes
[stype
] = map
.TypeData
;
1748 return map
.TypeData
;
1751 XmlTypeMapping
GetTypeMapping (TypeData typeData
)
1753 if (typeData
.Type
== typeof(object) && !anyTypeImported
)
1754 ImportAllObjectTypes ();
1756 XmlTypeMapping map
= GetRegisteredTypeMapping (typeData
);
1757 if (map
!= null) return map
;
1759 if (typeData
.IsListType
)
1761 // Create an array map for the type
1763 XmlTypeMapping itemMap
= GetTypeMapping (typeData
.ListItemTypeData
);
1765 map
= new XmlTypeMapping (typeData
.XmlType
, itemMap
.Namespace
, typeData
, typeData
.XmlType
, itemMap
.Namespace
);
1766 map
.IncludeInSchema
= true;
1768 ListMap listMap
= new ListMap ();
1769 listMap
.ItemInfo
= new XmlTypeMapElementInfoList();
1770 listMap
.ItemInfo
.Add (CreateElementInfo (itemMap
.Namespace
, null, typeData
.ListItemTypeData
.XmlType
, typeData
.ListItemTypeData
, false, XmlSchemaForm
.None
));
1771 map
.ObjectMap
= listMap
;
1773 RegisterTypeMapping (new XmlQualifiedName(map
.ElementName
, map
.Namespace
), typeData
, map
);
1776 else if (typeData
.SchemaType
== SchemaTypes
.Primitive
|| typeData
.Type
== typeof(object) || typeof(XmlNode
).IsAssignableFrom(typeData
.Type
))
1778 return CreateSystemMap (typeData
);
1781 throw new InvalidOperationException ("Map for type " + typeData
.TypeName
+ " not found");
1784 void AddObjectDerivedMap (XmlTypeMapping map
)
1786 TypeData typeData
= TypeTranslator
.GetTypeData (typeof(object));
1787 XmlTypeMapping omap
= GetRegisteredTypeMapping (typeData
);
1789 omap
= CreateSystemMap (typeData
);
1790 omap
.DerivedTypes
.Add (map
);
1793 XmlTypeMapping
CreateSystemMap (TypeData typeData
)
1795 XmlTypeMapping map
= new XmlTypeMapping (typeData
.XmlType
, XmlSchema
.Namespace
, typeData
, typeData
.XmlType
, XmlSchema
.Namespace
);
1796 map
.IncludeInSchema
= false;
1797 map
.ObjectMap
= new ClassMap ();
1798 dataMappedTypes
[typeData
] = map
;
1802 void ImportAllObjectTypes ()
1804 // All complex types are subtypes of anyType, so all of them
1805 // must also be imported
1807 anyTypeImported
= true;
1808 foreach (XmlSchema schema
in schemas
) {
1809 foreach (XmlSchemaObject sob
in schema
.Items
)
1811 XmlSchemaComplexType sct
= sob
as XmlSchemaComplexType
;
1813 ImportType (new XmlQualifiedName (sct
.Name
, schema
.TargetNamespace
), sct
, null);
1818 XmlTypeMapping
GetRegisteredTypeMapping (XmlQualifiedName typeQName
, Type baseType
)
1820 // Primitive types with a forced base class are stored in a different table.
1821 // In this way it is possible to have two maps for primitive types: one with
1822 // the forced base class (returned by ImportDerivedTypeMapping) and one
1823 // with the regular primitive map.
1825 if (IsPrimitiveTypeNamespace (typeQName
.Namespace
))
1826 return (XmlTypeMapping
) primitiveDerivedMappedTypes
[typeQName
];
1828 return (XmlTypeMapping
) mappedTypes
[typeQName
];
1831 XmlTypeMapping
GetRegisteredTypeMapping (XmlQualifiedName typeQName
)
1833 return (XmlTypeMapping
) mappedTypes
[typeQName
];
1836 XmlTypeMapping
GetRegisteredTypeMapping (TypeData typeData
)
1838 return (XmlTypeMapping
) dataMappedTypes
[typeData
];
1841 void RegisterTypeMapping (XmlQualifiedName qname
, TypeData typeData
, XmlTypeMapping map
)
1843 // Primitive types with a forced base class are stored in a different table.
1844 // In this way it is possible to have two maps for primitive types: one with
1845 // the forced base class (returned by ImportDerivedTypeMapping) and one
1846 // with the regular primitive map.
1848 dataMappedTypes
[typeData
] = map
;
1849 if (IsPrimitiveTypeNamespace (qname
.Namespace
) && !map
.IsSimpleType
)
1850 primitiveDerivedMappedTypes
[qname
] = map
;
1852 mappedTypes
[qname
] = map
;
1855 XmlSchemaParticle
GetRefGroupParticle (XmlSchemaGroupRef refGroup
)
1857 XmlSchemaGroup grp
= (XmlSchemaGroup
) schemas
.Find (refGroup
.RefName
, typeof (XmlSchemaGroup
));
1858 return grp
.Particle
;
1861 XmlSchemaElement
FindRefElement (XmlSchemaElement elem
)
1863 XmlSchemaElement refelem
= (XmlSchemaElement
) schemas
.Find (elem
.RefName
, typeof(XmlSchemaElement
));
1864 if (refelem
!= null) return refelem
;
1866 if (IsPrimitiveTypeNamespace (elem
.RefName
.Namespace
))
1868 if (anyElement
!= null) return anyElement
;
1869 anyElement
= new XmlSchemaElement ();
1870 anyElement
.Name
= "any";
1871 anyElement
.SchemaTypeName
= anyType
;
1877 XmlSchemaAttribute
FindRefAttribute (XmlQualifiedName refName
)
1879 if (refName
.Namespace
== XmlNamespace
)
1881 XmlSchemaAttribute at
= new XmlSchemaAttribute ();
1882 at
.Name
= refName
.Name
;
1883 at
.SchemaTypeName
= new XmlQualifiedName ("string",XmlSchema
.Namespace
);
1886 return (XmlSchemaAttribute
) schemas
.Find (refName
, typeof(XmlSchemaAttribute
));
1889 XmlSchemaAttributeGroup
FindRefAttributeGroup (XmlQualifiedName refName
)
1891 XmlSchemaAttributeGroup grp
= (XmlSchemaAttributeGroup
) schemas
.Find (refName
, typeof(XmlSchemaAttributeGroup
));
1892 foreach (XmlSchemaObject at
in grp
.Attributes
)
1894 if (at
is XmlSchemaAttributeGroupRef
&& ((XmlSchemaAttributeGroupRef
)at
).RefName
== refName
)
1895 throw new InvalidOperationException ("Cannot import attribute group '" + refName
.Name
+ "' from namespace '" + refName
.Namespace
+ "'. Redefine not supported");
1901 XmlTypeMapping
ReflectType (Type type
)
1903 TypeData typeData
= TypeTranslator
.GetTypeData (type
);
1904 return ReflectType (typeData
, (string) null);
1907 XmlTypeMapping
ReflectType (TypeData typeData
, string ns
)
1911 if (auxXmlRefImporter
== null) auxXmlRefImporter
= new XmlReflectionImporter ();
1912 return auxXmlRefImporter
.ImportTypeMapping (typeData
, ns
);
1916 if (auxSoapRefImporter
== null) auxSoapRefImporter
= new SoapReflectionImporter ();
1917 return auxSoapRefImporter
.ImportTypeMapping (typeData
, ns
);
1922 string GetDocumentation (XmlSchemaAnnotated elem
)
1925 XmlSchemaAnnotation anot
= elem
.Annotation
;
1926 if (anot
== null || anot
.Items
== null) return null;
1928 foreach (object ob
in anot
.Items
)
1930 XmlSchemaDocumentation doc
= ob
as XmlSchemaDocumentation
;
1931 if (doc
!= null && doc
.Markup
!= null && doc
.Markup
.Length
> 0) {
1932 if (res
!= string.Empty
) res
+= "\n";
1933 foreach (XmlNode node
in doc
.Markup
)
1940 bool IsPrimitiveTypeNamespace (string ns
)
1942 return (ns
== XmlSchema
.Namespace
) || (encodedFormat
&& ns
== XmlSerializer
.EncodingNamespace
);
1945 #endregion // Methods