2 // System.Xml.Serialization.XmlSchemaImporter
\r
5 // Tim Coleman (tim@timcoleman.com)
\r
6 // Lluis Sanchez Gual (lluis@ximian.com)
\r
8 // Copyright (C) Tim Coleman, 2002
\r
12 using System.Xml.Schema;
\r
13 using System.Collections;
\r
15 namespace System.Xml.Serialization {
\r
16 public class XmlSchemaImporter {
\r
21 CodeIdentifiers typeIdentifiers;
\r
22 CodeIdentifiers elemIdentifiers = new CodeIdentifiers ();
\r
23 Hashtable mappedTypes = new Hashtable ();
\r
24 Hashtable dataMappedTypes = new Hashtable ();
\r
25 Queue pendingMaps = new Queue ();
\r
26 Hashtable sharedAnonymousTypes = new Hashtable ();
\r
27 bool encodedFormat = false;
\r
28 XmlReflectionImporter auxXmlRefImporter;
\r
29 SoapReflectionImporter auxSoapRefImporter;
\r
30 Hashtable forcedBaseTypes;
\r
32 static readonly XmlQualifiedName anyType = new XmlQualifiedName ("anyType",XmlSchema.Namespace);
\r
33 static readonly XmlQualifiedName arrayType = new XmlQualifiedName ("Array",XmlSerializer.EncodingNamespace);
\r
34 static readonly XmlQualifiedName arrayTypeRefName = new XmlQualifiedName ("arrayType",XmlSerializer.EncodingNamespace);
\r
36 const string XmlNamespace = "http://www.w3.org/XML/1998/namespace";
\r
38 XmlSchemaElement anyElement = null;
\r
42 public XmlTypeMapping Map;
\r
43 public XmlSchemaComplexType SchemaType;
\r
44 public XmlQualifiedName TypeName;
\r
49 #region Constructors
\r
51 public XmlSchemaImporter (XmlSchemas schemas)
\r
53 this.schemas = schemas;
\r
54 typeIdentifiers = new CodeIdentifiers ();
\r
57 public XmlSchemaImporter (XmlSchemas schemas, CodeIdentifiers typeIdentifiers)
\r
60 this.typeIdentifiers = typeIdentifiers;
\r
63 internal bool UseEncodedFormat
\r
65 get { return encodedFormat; }
\r
66 set { encodedFormat = value; }
\r
69 #endregion // Constructors
\r
73 public XmlMembersMapping ImportAnyType (XmlQualifiedName typeName, string elementName)
\r
75 XmlTypeMapMemberAnyElement mapMem = new XmlTypeMapMemberAnyElement ();
\r
76 mapMem.Name = typeName.Name;
\r
77 mapMem.TypeData = TypeTranslator.GetTypeData(typeof(XmlNode));
\r
78 mapMem.ElementInfo.Add (CreateElementInfo (typeName.Namespace, mapMem, typeName.Name, mapMem.TypeData, true));
\r
80 XmlMemberMapping[] mm = new XmlMemberMapping [1];
\r
81 mm[0] = new XmlMemberMapping (typeName.Name, typeName.Namespace, mapMem, encodedFormat);
\r
82 return new XmlMembersMapping (mm);
\r
85 public XmlTypeMapping ImportDerivedTypeMapping (XmlQualifiedName name, Type baseType)
\r
87 return ImportDerivedTypeMapping (name, baseType, true);
\r
90 public XmlTypeMapping ImportDerivedTypeMapping (XmlQualifiedName name, Type baseType, bool baseTypeCanBeIndirect)
\r
92 XmlQualifiedName qname;
\r
93 XmlSchemaType stype;
\r
98 stype = schemas.Find (name, typeof (XmlSchemaComplexType)) as XmlSchemaComplexType;
\r
99 if (stype == null) throw new InvalidOperationException ("Schema type '" + name + "' not found or not valid");
\r
103 if (!LocateElement (name, out qname, out stype)) return null;
\r
106 XmlTypeMapping map = GetRegisteredTypeMapping (qname);
\r
107 if (map != null) return map;
\r
109 RegisterForcedBaseType (qname, baseType);
\r
111 map = CreateTypeMapping (qname, SchemaTypes.Class, name);
\r
112 map.Documentation = GetDocumentation (stype);
\r
113 RegisterMapFixup (map, qname, (XmlSchemaComplexType)stype);
\r
115 BuildPendingMaps ();
\r
120 public XmlTypeMapping ImportDerivedTypeMapping (XmlQualifiedName name, bool baseTypeCanBeIndirect)
\r
122 throw new NotImplementedException ();
\r
125 public XmlMembersMapping ImportMembersMapping (XmlQualifiedName name)
\r
127 XmlSchemaElement elem = (XmlSchemaElement) schemas.Find (name, typeof (XmlSchemaElement));
\r
128 if (elem == null) throw new InvalidOperationException ("Schema element '" + name + "' not found or not valid");
\r
130 XmlSchemaComplexType stype;
\r
131 if (elem.SchemaType != null)
\r
133 stype = elem.SchemaType as XmlSchemaComplexType;
\r
137 if (elem.SchemaTypeName.IsEmpty) return null;
\r
138 if (elem.SchemaTypeName.Namespace == XmlSchema.Namespace) return null;
\r
139 object type = schemas.Find (elem.SchemaTypeName, typeof (XmlSchemaComplexType));
\r
140 if (type == null) throw new InvalidOperationException ("Schema type '" + elem.SchemaTypeName + "' not found");
\r
141 stype = type as XmlSchemaComplexType;
\r
144 if (stype == null)
\r
145 throw new InvalidOperationException ("Schema element '" + name + "' not found or not valid");
\r
147 XmlMemberMapping[] mapping = ImportMembersMappingComposite (stype, name);
\r
148 return new XmlMembersMapping (name.Name, name.Namespace, mapping);
\r
151 public XmlMembersMapping ImportMembersMapping (XmlQualifiedName[] names)
\r
153 XmlMemberMapping[] mapping = new XmlMemberMapping [names.Length];
\r
154 for (int n=0; n<names.Length; n++)
\r
156 XmlSchemaElement elem = (XmlSchemaElement) schemas.Find (names[n], typeof (XmlSchemaElement));
\r
157 if (elem == null) throw new InvalidOperationException ("Schema element '" + names[n] + "' not found");
\r
159 XmlQualifiedName typeQName = new XmlQualifiedName ("Message", names[n].Namespace);
\r
160 TypeData td = GetElementTypeData (typeQName, elem);
\r
162 mapping[n] = ImportMemberMapping (elem.Name, typeQName.Namespace, td);
\r
164 BuildPendingMaps ();
\r
165 return new XmlMembersMapping (mapping);
\r
168 public XmlMembersMapping ImportEncodedMembersMapping (string name, string ns, SoapSchemaMember[] members, bool hasWrapperElement)
\r
170 XmlMemberMapping[] mapping = new XmlMemberMapping [members.Length];
\r
171 for (int n=0; n<members.Length; n++)
\r
173 TypeData td = GetTypeData (members[n].MemberType, null);
\r
174 mapping[n] = ImportMemberMapping (members[n].MemberName, members[n].MemberType.Namespace, td);
\r
176 BuildPendingMaps ();
\r
177 return new XmlMembersMapping (name, ns, hasWrapperElement, false, mapping);
\r
180 public XmlMembersMapping ImportEncodedMembersMapping (string name, string ns, SoapSchemaMember member)
\r
182 XmlSchemaComplexType stype = schemas.Find (member.MemberType, typeof (XmlSchemaComplexType)) as XmlSchemaComplexType;
\r
183 if (stype == null) throw new InvalidOperationException ("Schema type '" + member.MemberType + "' not found or not valid");
\r
185 XmlMemberMapping[] mapping = ImportMembersMappingComposite (stype, member.MemberType);
\r
186 return new XmlMembersMapping (name, ns, mapping);
\r
189 public XmlMemberMapping[] ImportMembersMappingComposite (XmlSchemaComplexType stype, XmlQualifiedName refer)
\r
191 if (stype.Particle == null)
\r
192 return new XmlMemberMapping [0];
\r
194 ClassMap cmap = new ClassMap ();
\r
196 XmlSchemaSequence seq = stype.Particle as XmlSchemaSequence;
\r
197 if (seq == null) throw new InvalidOperationException ("Schema element '" + refer + "' cannot be imported as XmlMembersMapping");
\r
199 CodeIdentifiers classIds = new CodeIdentifiers ();
\r
200 ImportParticleComplexContent (refer, cmap, seq, classIds, false);
\r
202 BuildPendingMaps ();
\r
205 XmlMemberMapping[] mapping = new XmlMemberMapping [cmap.AllMembers.Count];
\r
206 foreach (XmlTypeMapMember mapMem in cmap.AllMembers)
\r
207 mapping[n++] = new XmlMemberMapping (mapMem.Name, refer.Namespace, mapMem, encodedFormat);
\r
212 XmlMemberMapping ImportMemberMapping (string name, string ns, TypeData type)
\r
214 XmlTypeMapMemberElement mapMem = new XmlTypeMapMemberElement ();
\r
215 mapMem.Name = name;
\r
216 mapMem.TypeData = type;
\r
217 mapMem.ElementInfo.Add (CreateElementInfo (ns, mapMem, name, type, true));
\r
218 return new XmlMemberMapping (name, ns, mapMem, encodedFormat);
\r
222 public XmlMembersMapping ImportMembersMapping (XmlQualifiedName[] names, Type baseType, bool baseTypeCanBeIndirect)
\r
224 throw new NotImplementedException ();
\r
227 public XmlTypeMapping ImportTypeMapping (XmlQualifiedName name)
\r
229 XmlQualifiedName qname;
\r
230 XmlSchemaType stype;
\r
231 if (!LocateElement (name, out qname, out stype)) return null;
\r
233 XmlTypeMapping map = GetRegisteredTypeMapping (qname);
\r
234 if (map != null) return map;
\r
236 map = CreateTypeMapping (qname, SchemaTypes.Class, name);
\r
237 map.Documentation = GetDocumentation (stype);
\r
238 RegisterMapFixup (map, qname, (XmlSchemaComplexType)stype);
\r
240 BuildPendingMaps ();
\r
244 bool LocateElement (XmlQualifiedName name, out XmlQualifiedName qname, out XmlSchemaType stype)
\r
249 XmlSchemaElement elem = (XmlSchemaElement) schemas.Find (name, typeof (XmlSchemaElement));
\r
250 if (elem == null) return false;
\r
252 // The root element must be an element with complex type
\r
254 if (elem.SchemaType != null)
\r
256 stype = elem.SchemaType;
\r
261 if (elem.SchemaTypeName.IsEmpty) return false;
\r
262 if (elem.SchemaTypeName.Namespace == XmlSchema.Namespace) return false;
\r
263 object type = schemas.Find (elem.SchemaTypeName, typeof (XmlSchemaComplexType));
\r
264 if (type == null) type = schemas.Find (elem.SchemaTypeName, typeof (XmlSchemaSimpleType));
\r
265 if (type == null) throw new InvalidOperationException ("Schema type '" + elem.SchemaTypeName + "' not found");
\r
266 stype = (XmlSchemaType) type;
\r
267 qname = stype.QualifiedName;
\r
270 if (stype is XmlSchemaSimpleType) return false;
\r
274 XmlTypeMapping ImportType (XmlQualifiedName name, XmlQualifiedName root)
\r
276 XmlTypeMapping map = GetRegisteredTypeMapping (name);
\r
277 if (map != null) return map;
\r
279 XmlSchemaType type = (XmlSchemaType) schemas.Find (name, typeof (XmlSchemaComplexType));
\r
280 if (type == null) type = (XmlSchemaType) schemas.Find (name, typeof (XmlSchemaSimpleType));
\r
284 if (name.Namespace == XmlSerializer.EncodingNamespace)
\r
285 throw new InvalidOperationException ("Referenced type '" + name + "' valid only for encoded SOAP");
\r
287 throw new InvalidOperationException ("Referenced type '" + name + "' not found");
\r
290 return ImportType (name, type, root);
\r
293 XmlTypeMapping ImportType (XmlQualifiedName name, XmlSchemaType stype, XmlQualifiedName root)
\r
295 XmlTypeMapping map = GetRegisteredTypeMapping (name);
\r
296 if (map != null) return map;
\r
298 if (stype is XmlSchemaComplexType)
\r
299 return ImportClassComplexType (name, (XmlSchemaComplexType) stype, root);
\r
300 else if (stype is XmlSchemaSimpleType)
\r
301 return ImportClassSimpleType (name, (XmlSchemaSimpleType) stype, root);
\r
303 throw new NotSupportedException ("Schema type not supported: " + stype.GetType ());
\r
306 XmlTypeMapping ImportClassComplexType (XmlQualifiedName typeQName, XmlSchemaComplexType stype, XmlQualifiedName root)
\r
308 XmlTypeMapping map;
\r
310 // The need for fixups: If the complex type is an array, then to get the type of the
\r
311 // array we need first to get the type of the items of the array.
\r
312 // But if one of the item types or its children has a referece to this type array,
\r
313 // then we enter in an infinite loop. This does not happen with class types because
\r
314 // the class map is registered before parsing the children. We can't do the same
\r
315 // with the array type because to register the array map we need the type of the array.
\r
317 if (CanBeArray (typeQName, stype))
\r
320 ListMap listMap = BuildArrayMap (typeQName, stype, out typeData);
\r
321 if (listMap != null)
\r
323 map = CreateArrayTypeMapping (typeQName, typeData);
\r
324 map.ObjectMap = listMap;
\r
328 // After all, it is not an array. Create a class map then.
\r
330 else if (CanBeAnyElement (stype))
\r
332 return GetTypeMapping (TypeTranslator.GetTypeData(typeof(XmlElement)));
\r
334 else if (CanBeIXmlSerializable (stype))
\r
336 return GetTypeMapping (TypeTranslator.GetTypeData(typeof(object)));
\r
339 // Register the map right now but do not build it,
\r
340 // This will avoid loops.
\r
342 map = CreateTypeMapping (typeQName, SchemaTypes.Class, root);
\r
343 map.Documentation = GetDocumentation (stype);
\r
344 RegisterMapFixup (map, typeQName, stype);
\r
348 void RegisterMapFixup (XmlTypeMapping map, XmlQualifiedName typeQName, XmlSchemaComplexType stype)
\r
350 MapFixup fixup = new MapFixup ();
\r
352 fixup.SchemaType = stype;
\r
353 fixup.TypeName = typeQName;
\r
354 pendingMaps.Enqueue (fixup);
\r
357 void BuildPendingMaps ()
\r
359 while (pendingMaps.Count > 0) {
\r
360 MapFixup fixup = (MapFixup) pendingMaps.Dequeue ();
\r
361 if (fixup.Map.ObjectMap == null) {
\r
362 BuildClassMap (fixup.Map, fixup.TypeName, fixup.SchemaType);
\r
363 if (fixup.Map.ObjectMap == null) pendingMaps.Enqueue (fixup);
\r
368 void BuildPendingMap (XmlTypeMapping map)
\r
370 if (map.ObjectMap != null) return;
\r
372 foreach (MapFixup fixup in pendingMaps)
\r
374 if (fixup.Map == map) {
\r
375 BuildClassMap (fixup.Map, fixup.TypeName, fixup.SchemaType);
\r
379 throw new InvalidOperationException ("Can't complete map of type " + map.XmlType + " : " + map.Namespace);
\r
382 void BuildClassMap (XmlTypeMapping map, XmlQualifiedName typeQName, XmlSchemaComplexType stype)
\r
384 CodeIdentifiers classIds = new CodeIdentifiers();
\r
385 classIds.AddReserved (map.TypeData.TypeName);
\r
387 ClassMap cmap = new ClassMap ();
\r
388 map.ObjectMap = cmap;
\r
389 bool isMixed = stype.IsMixed;
\r
391 if (stype.Particle != null)
\r
393 if (HasForcedBaseType (typeQName))
\r
394 ImportForcedDerivedType (map, typeQName, ref isMixed);
\r
396 ImportParticleComplexContent (typeQName, cmap, stype.Particle, classIds, isMixed);
\r
400 if (stype.ContentModel is XmlSchemaSimpleContent) {
\r
401 ImportSimpleContent (typeQName, map, (XmlSchemaSimpleContent)stype.ContentModel, classIds, isMixed);
\r
403 else if (stype.ContentModel is XmlSchemaComplexContent) {
\r
404 ImportComplexContent (typeQName, map, (XmlSchemaComplexContent)stype.ContentModel, classIds, isMixed);
\r
408 ImportAttributes (typeQName, cmap, stype.Attributes, stype.AnyAttribute, classIds);
\r
409 ImportExtensionTypes (typeQName);
\r
412 void ImportAttributes (XmlQualifiedName typeQName, ClassMap cmap, XmlSchemaObjectCollection atts, XmlSchemaAnyAttribute anyat, CodeIdentifiers classIds)
\r
416 XmlTypeMapMemberAnyAttribute member = new XmlTypeMapMemberAnyAttribute ();
\r
417 member.Name = classIds.AddUnique ("AnyAttribute", member);
\r
418 member.TypeData = TypeTranslator.GetTypeData (typeof(XmlAttribute[]));
\r
419 cmap.AddMember (member);
\r
422 foreach (XmlSchemaObject at in atts)
\r
424 if (at is XmlSchemaAttribute)
\r
427 XmlSchemaAttribute attr = (XmlSchemaAttribute)at;
\r
428 XmlSchemaAttribute refAttr = GetRefAttribute (typeQName, attr, out ns);
\r
429 XmlTypeMapMemberAttribute member = new XmlTypeMapMemberAttribute ();
\r
430 member.Name = classIds.AddUnique (CodeIdentifier.MakeValid (refAttr.Name), member);
\r
431 member.Documentation = GetDocumentation (attr);
\r
432 member.AttributeName = refAttr.Name;
\r
433 member.Namespace = ns;
\r
434 member.Form = refAttr.Form;
\r
435 member.TypeData = GetAttributeTypeData (typeQName, attr);
\r
437 if (refAttr.DefaultValue != null)
\r
438 member.DefaultValue = XmlCustomFormatter.FromXmlString (member.TypeData, refAttr.DefaultValue);
\r
439 else if (member.TypeData.IsValueType)
\r
440 member.IsOptionalValueType = true;
\r
442 if (member.TypeData.IsComplexType)
\r
443 member.MappedType = GetTypeMapping (member.TypeData);
\r
444 cmap.AddMember (member);
\r
446 else if (at is XmlSchemaAttributeGroupRef)
\r
448 XmlSchemaAttributeGroupRef gref = (XmlSchemaAttributeGroupRef)at;
\r
449 XmlSchemaAttributeGroup grp = (XmlSchemaAttributeGroup) schemas.Find (gref.RefName, typeof(XmlSchemaAttributeGroup));
\r
450 ImportAttributes (typeQName, cmap, grp.Attributes, grp.AnyAttribute, classIds);
\r
455 ListMap BuildArrayMap (XmlQualifiedName typeQName, XmlSchemaComplexType stype, out TypeData arrayTypeData)
\r
459 XmlSchemaComplexContent content = stype.ContentModel as XmlSchemaComplexContent;
\r
460 XmlSchemaComplexContentRestriction rest = content.Content as XmlSchemaComplexContentRestriction;
\r
461 XmlSchemaAttribute arrayTypeAt = FindArrayAttribute (rest.Attributes);
\r
463 if (arrayTypeAt != null)
\r
465 XmlAttribute[] uatts = arrayTypeAt.UnhandledAttributes;
\r
466 if (uatts == null || uatts.Length == 0) throw new InvalidOperationException ("arrayType attribute not specified in array declaration: " + typeQName);
\r
468 XmlAttribute xat = null;
\r
469 foreach (XmlAttribute at in uatts)
\r
470 if (at.LocalName == "arrayType" && at.NamespaceURI == XmlSerializer.WsdlNamespace)
\r
471 { xat = at; break; }
\r
474 throw new InvalidOperationException ("arrayType attribute not specified in array declaration: " + typeQName);
\r
476 string name, ns, dims;
\r
477 TypeTranslator.ParseArrayType (xat.Value, out name, out ns, out dims);
\r
478 return BuildEncodedArrayMap (name + dims, ns, out arrayTypeData);
\r
482 XmlSchemaElement elem = null;
\r
483 XmlSchemaSequence seq = rest.Particle as XmlSchemaSequence;
\r
484 if (seq != null && seq.Items.Count == 1)
\r
485 elem = seq.Items[0] as XmlSchemaElement;
\r
487 XmlSchemaAll all = rest.Particle as XmlSchemaAll;
\r
488 if (all != null && all.Items.Count == 1)
\r
489 elem = all.Items[0] as XmlSchemaElement;
\r
492 throw new InvalidOperationException ("Unknown array format");
\r
494 return BuildEncodedArrayMap (elem.SchemaTypeName.Name + "[]", elem.SchemaTypeName.Namespace, out arrayTypeData);
\r
499 ClassMap cmap = new ClassMap ();
\r
500 CodeIdentifiers classIds = new CodeIdentifiers();
\r
501 ImportParticleComplexContent (typeQName, cmap, stype.Particle, classIds, false);
\r
503 XmlTypeMapMemberFlatList list = (cmap.AllMembers.Count == 1) ? cmap.AllMembers[0] as XmlTypeMapMemberFlatList : null;
\r
504 if (list != null && list.ChoiceMember == null)
\r
506 arrayTypeData = list.TypeData;
\r
507 return list.ListMap;
\r
511 arrayTypeData = null;
\r
517 ListMap BuildEncodedArrayMap (string type, string ns, out TypeData arrayTypeData)
\r
519 ListMap map = new ListMap ();
\r
521 int i = type.LastIndexOf ("[");
\r
522 if (i == -1) throw new InvalidOperationException ("Invalid arrayType value: " + type);
\r
523 if (type.IndexOf (",",i) != -1) throw new InvalidOperationException ("Multidimensional arrays are not supported");
\r
525 string itemType = type.Substring (0,i);
\r
527 TypeData itemTypeData;
\r
528 if (itemType.IndexOf ("[") != -1)
\r
530 ListMap innerListMap = BuildEncodedArrayMap (itemType, ns, out itemTypeData);
\r
532 int dims = itemType.Split ('[').Length - 1;
\r
533 string name = TypeTranslator.GetArrayName (type, dims);
\r
534 XmlQualifiedName qname = new XmlQualifiedName (name, ns);
\r
535 XmlTypeMapping tmap = CreateArrayTypeMapping (qname, itemTypeData);
\r
536 tmap.ObjectMap = innerListMap;
\r
540 itemTypeData = GetTypeData (new XmlQualifiedName (itemType, ns), null);
\r
543 arrayTypeData = itemTypeData.ListTypeData;
\r
545 map.ItemInfo = new XmlTypeMapElementInfoList();
\r
546 map.ItemInfo.Add (CreateElementInfo ("", null, "Item", itemTypeData, true));
\r
550 XmlSchemaAttribute FindArrayAttribute (XmlSchemaObjectCollection atts)
\r
552 foreach (object ob in atts)
\r
554 XmlSchemaAttribute att = ob as XmlSchemaAttribute;
\r
555 if (att != null && att.RefName == arrayTypeRefName) return att;
\r
557 XmlSchemaAttributeGroupRef gref = ob as XmlSchemaAttributeGroupRef;
\r
560 XmlSchemaAttributeGroup grp = (XmlSchemaAttributeGroup) schemas.Find (gref.RefName, typeof(XmlSchemaAttributeGroup));
\r
561 att = FindArrayAttribute (grp.Attributes);
\r
562 if (att != null) return att;
\r
568 void ImportParticleComplexContent (XmlQualifiedName typeQName, ClassMap cmap, XmlSchemaParticle particle, CodeIdentifiers classIds, bool isMixed)
\r
570 ImportParticleContent (typeQName, cmap, particle, classIds, false, ref isMixed);
\r
573 XmlTypeMapMemberFlatList member = new XmlTypeMapMemberFlatList ();
\r
574 member.Name = classIds.AddUnique ("Text", member);
\r
575 member.TypeData = TypeTranslator.GetTypeData (typeof(string[]));
\r
576 member.ElementInfo.Add (CreateTextElementInfo (typeQName.Namespace, member, member.TypeData.ListItemTypeData));
\r
577 member.IsXmlTextCollector = true;
\r
578 member.ListMap = new ListMap ();
\r
579 member.ListMap.ItemInfo = member.ElementInfo;
\r
580 cmap.AddMember (member);
\r
584 void ImportParticleContent (XmlQualifiedName typeQName, ClassMap cmap, XmlSchemaParticle particle, CodeIdentifiers classIds, bool multiValue, ref bool isMixed)
\r
586 if (particle is XmlSchemaGroupRef)
\r
587 particle = GetRefGroupParticle ((XmlSchemaGroupRef)particle);
\r
589 if (particle.MaxOccurs > 1) multiValue = true;
\r
591 if (particle is XmlSchemaSequence) {
\r
592 ImportSequenceContent (typeQName, cmap, ((XmlSchemaSequence)particle).Items, classIds, multiValue, ref isMixed);
\r
594 else if (particle is XmlSchemaChoice) {
\r
595 if (((XmlSchemaChoice)particle).Items.Count == 1)
\r
596 ImportSequenceContent (typeQName, cmap, ((XmlSchemaChoice)particle).Items, classIds, multiValue, ref isMixed);
\r
598 ImportChoiceContent (typeQName, cmap, (XmlSchemaChoice)particle, classIds, multiValue);
\r
600 else if (particle is XmlSchemaAll) {
\r
601 ImportSequenceContent (typeQName, cmap, ((XmlSchemaAll)particle).Items, classIds, multiValue, ref isMixed);
\r
605 void ImportSequenceContent (XmlQualifiedName typeQName, ClassMap cmap, XmlSchemaObjectCollection items, CodeIdentifiers classIds, bool multiValue, ref bool isMixed)
\r
607 foreach (XmlSchemaObject item in items)
\r
609 if (item is XmlSchemaElement)
\r
612 XmlSchemaElement elem = (XmlSchemaElement) item;
\r
613 TypeData typeData = GetElementTypeData (typeQName, elem);
\r
614 XmlSchemaElement refElem = GetRefElement (typeQName, elem, out ns);
\r
616 if (elem.MaxOccurs == 1 && !multiValue)
\r
618 XmlTypeMapMemberElement member = null;
\r
619 if (typeData.SchemaType != SchemaTypes.Array)
\r
621 member = new XmlTypeMapMemberElement ();
\r
622 if (refElem.DefaultValue != null) member.DefaultValue = XmlCustomFormatter.FromXmlString (typeData, refElem.DefaultValue);
\r
624 else if (GetTypeMapping (typeData).IsSimpleType)
\r
626 // It is a simple list (space separated list).
\r
627 // Since this is not supported, map as a single item value
\r
628 // TODO: improve this
\r
629 member = new XmlTypeMapMemberElement ();
\r
630 typeData = typeData.ListItemTypeData;
\r
633 member = new XmlTypeMapMemberList ();
\r
635 if (elem.MinOccurs == 0 && typeData.IsValueType)
\r
636 member.IsOptionalValueType = true;
\r
638 member.Name = classIds.AddUnique(CodeIdentifier.MakeValid(refElem.Name), member);
\r
639 member.Documentation = GetDocumentation (elem);
\r
640 member.TypeData = typeData;
\r
641 member.ElementInfo.Add (CreateElementInfo (ns, member, refElem.Name, typeData, refElem.IsNillable));
\r
642 cmap.AddMember (member);
\r
646 XmlTypeMapMemberFlatList member = new XmlTypeMapMemberFlatList ();
\r
647 member.ListMap = new ListMap ();
\r
648 member.Name = classIds.AddUnique(CodeIdentifier.MakeValid(refElem.Name), member);
\r
649 member.Documentation = GetDocumentation (elem);
\r
650 member.TypeData = typeData.ListTypeData;
\r
651 member.ElementInfo.Add (CreateElementInfo (ns, member, refElem.Name, typeData, refElem.IsNillable));
\r
652 member.ListMap.ItemInfo = member.ElementInfo;
\r
653 cmap.AddMember (member);
\r
656 else if (item is XmlSchemaAny)
\r
658 XmlSchemaAny elem = (XmlSchemaAny) item;
\r
659 XmlTypeMapMemberAnyElement member = new XmlTypeMapMemberAnyElement ();
\r
660 member.Name = classIds.AddUnique ("Any", member);
\r
661 member.Documentation = GetDocumentation (elem);
\r
664 if (elem.MaxOccurs > 1 || multiValue)
\r
665 ctype = isMixed ? typeof(XmlNode[]) : typeof(XmlElement[]);
\r
667 ctype = isMixed ? typeof(XmlNode) : typeof(XmlElement);
\r
669 member.TypeData = TypeTranslator.GetTypeData (ctype);
\r
670 XmlTypeMapElementInfo einfo = new XmlTypeMapElementInfo (member, member.TypeData);
\r
671 einfo.IsUnnamedAnyElement = true;
\r
672 member.ElementInfo.Add (einfo);
\r
676 einfo = CreateTextElementInfo (typeQName.Namespace, member, member.TypeData);
\r
677 member.ElementInfo.Add (einfo);
\r
678 member.IsXmlTextCollector = true;
\r
679 isMixed = false; //Allow only one XmlTextAttribute
\r
682 cmap.AddMember (member);
\r
684 else if (item is XmlSchemaParticle) {
\r
685 ImportParticleContent (typeQName, cmap, (XmlSchemaParticle)item, classIds, multiValue, ref isMixed);
\r
691 void ImportChoiceContent (XmlQualifiedName typeQName, ClassMap cmap, XmlSchemaChoice choice, CodeIdentifiers classIds, bool multiValue)
\r
693 XmlTypeMapElementInfoList choices = new XmlTypeMapElementInfoList ();
\r
694 multiValue = ImportChoices (typeQName, null, choices, choice.Items) || multiValue;
\r
695 if (choices.Count == 0) return;
\r
697 if (choice.MaxOccurs > 1) multiValue = true;
\r
699 XmlTypeMapMemberElement member;
\r
702 member = new XmlTypeMapMemberFlatList ();
\r
703 member.Name = classIds.AddUnique ("Items", member);
\r
704 ListMap listMap = new ListMap ();
\r
705 listMap.ItemInfo = choices;
\r
706 ((XmlTypeMapMemberFlatList)member).ListMap = listMap;
\r
710 member = new XmlTypeMapMemberElement ();
\r
711 member.Name = classIds.AddUnique ("Item", member);
\r
714 // If all choices have the same type, use that type for the member.
\r
715 // If not use System.Object.
\r
716 // If there are at least two choices with the same type, use a choice
\r
717 // identifier attribute
\r
719 TypeData typeData = null;
\r
720 bool twoEqual = false;
\r
721 bool allEqual = true;
\r
722 Hashtable types = new Hashtable ();
\r
724 foreach (XmlTypeMapElementInfo einfo in choices)
\r
726 if (types.ContainsKey (einfo.TypeData)) twoEqual = true;
\r
727 else types.Add (einfo.TypeData, einfo);
\r
729 TypeData choiceType = einfo.TypeData;
\r
730 if (choiceType.SchemaType == SchemaTypes.Class)
\r
732 // When comparing class types, use the most generic class in the
\r
733 // inheritance hierarchy
\r
736 XmlTypeMapping choiceMap = GetTypeMapping (choiceType);
\r
737 BuildPendingMap (choiceMap);
\r
738 while (choiceMap.BaseMap != null) {
\r
739 choiceMap = choiceMap.BaseMap;
\r
740 BuildPendingMap (choiceMap);
\r
741 choiceType = choiceMap.TypeData;
\r
745 if (typeData == null) typeData = choiceType;
\r
746 else if (typeData != choiceType) allEqual = false;
\r
750 typeData = TypeTranslator.GetTypeData (typeof(object));
\r
754 // Create the choice member
\r
755 XmlTypeMapMemberElement choiceMember = new XmlTypeMapMemberElement ();
\r
756 choiceMember.Name = classIds.AddUnique (member.Name + "ElementName", choiceMember);
\r
757 member.ChoiceMember = choiceMember.Name;
\r
759 // Create the choice enum
\r
760 XmlTypeMapping enumMap = CreateTypeMapping (new XmlQualifiedName (member.Name + "ChoiceType", typeQName.Namespace), SchemaTypes.Enum, null);
\r
762 CodeIdentifiers codeIdents = new CodeIdentifiers ();
\r
763 EnumMap.EnumMapMember[] members = new EnumMap.EnumMapMember [choices.Count];
\r
764 for (int n=0; n<choices.Count; n++)
\r
766 XmlTypeMapElementInfo it =(XmlTypeMapElementInfo) choices[n];
\r
767 string xmlName = (it.Namespace != null && it.Namespace != "") ? it.Namespace + ":" + it.ElementName : it.ElementName;
\r
768 string enumName = codeIdents.AddUnique (CodeIdentifier.MakeValid (it.ElementName), it);
\r
769 members [n] = new EnumMap.EnumMapMember (xmlName, enumName);
\r
771 enumMap.ObjectMap = new EnumMap (members, false);
\r
773 choiceMember.TypeData = multiValue ? enumMap.TypeData.ListTypeData : enumMap.TypeData;
\r
774 choiceMember.ElementInfo.Add (CreateElementInfo (typeQName.Namespace, choiceMember, choiceMember.Name, choiceMember.TypeData, false));
\r
775 cmap.AddMember (choiceMember);
\r
779 typeData = typeData.ListTypeData;
\r
781 member.ElementInfo = choices;
\r
782 member.Documentation = GetDocumentation (choice);
\r
783 member.TypeData = typeData;
\r
784 cmap.AddMember (member);
\r
787 bool ImportChoices (XmlQualifiedName typeQName, XmlTypeMapMember member, XmlTypeMapElementInfoList choices, XmlSchemaObjectCollection items)
\r
789 bool multiValue = false;
\r
790 foreach (XmlSchemaObject titem in items)
\r
792 XmlSchemaObject item = titem;
\r
793 if (item is XmlSchemaGroupRef)
\r
794 item = GetRefGroupParticle ((XmlSchemaGroupRef)item);
\r
796 if (item is XmlSchemaElement)
\r
799 XmlSchemaElement elem = (XmlSchemaElement) item;
\r
800 TypeData typeData = GetElementTypeData (typeQName, elem);
\r
801 XmlSchemaElement refElem = GetRefElement (typeQName, elem, out ns);
\r
802 choices.Add (CreateElementInfo (ns, member, refElem.Name, typeData, refElem.IsNillable));
\r
803 if (elem.MaxOccurs > 1) multiValue = true;
\r
805 else if (item is XmlSchemaAny)
\r
807 XmlTypeMapElementInfo einfo = new XmlTypeMapElementInfo (member, TypeTranslator.GetTypeData(typeof(XmlElement)));
\r
808 einfo.IsUnnamedAnyElement = true;
\r
809 choices.Add (einfo);
\r
811 else if (item is XmlSchemaChoice) {
\r
812 multiValue = ImportChoices (typeQName, member, choices, ((XmlSchemaChoice)item).Items) || multiValue;
\r
814 else if (item is XmlSchemaSequence) {
\r
815 multiValue = ImportChoices (typeQName, member, choices, ((XmlSchemaSequence)item).Items) || multiValue;
\r
821 void ImportSimpleContent (XmlQualifiedName typeQName, XmlTypeMapping map, XmlSchemaSimpleContent content, CodeIdentifiers classIds, bool isMixed)
\r
823 ClassMap cmap = (ClassMap)map.ObjectMap;
\r
825 XmlQualifiedName qname = GetContentBaseType (content.Content);
\r
827 XmlTypeMapMemberElement member = new XmlTypeMapMemberElement ();
\r
828 member.Name = classIds.AddUnique("Value", member);
\r
829 member.TypeData = FindBuiltInType (qname);
\r
830 member.ElementInfo.Add (CreateTextElementInfo (typeQName.Namespace, member, member.TypeData));
\r
831 member.IsXmlTextCollector = true;
\r
832 cmap.AddMember (member);
\r
834 XmlSchemaSimpleContentExtension ext = content.Content as XmlSchemaSimpleContentExtension;
\r
836 ImportAttributes (typeQName, cmap, ext.Attributes, ext.AnyAttribute, classIds);
\r
839 TypeData FindBuiltInType (XmlQualifiedName qname)
\r
841 if (qname.Namespace == XmlSchema.Namespace)
\r
842 return TypeTranslator.GetPrimitiveTypeData (qname.Name);
\r
844 XmlSchemaComplexType ct = (XmlSchemaComplexType) schemas.Find (qname, typeof(XmlSchemaComplexType));
\r
847 XmlSchemaSimpleContent sc = ct.ContentModel as XmlSchemaSimpleContent;
\r
848 if (sc == null) throw new InvalidOperationException ("Invalid schema");
\r
849 return FindBuiltInType (GetContentBaseType (sc.Content));
\r
852 XmlSchemaSimpleType st = (XmlSchemaSimpleType) schemas.Find (qname, typeof(XmlSchemaSimpleType));
\r
854 return FindBuiltInType (qname, st);
\r
856 throw new InvalidOperationException ("Definition of type " + qname + " not found");
\r
859 TypeData FindBuiltInType (XmlQualifiedName qname, XmlSchemaSimpleType st)
\r
861 if (CanBeEnum (st))
\r
862 return ImportType (qname, null).TypeData;
\r
864 if (st.Content is XmlSchemaSimpleTypeRestriction) {
\r
865 return FindBuiltInType (GetContentBaseType (st.Content));
\r
867 else if (st.Content is XmlSchemaSimpleTypeList) {
\r
868 return FindBuiltInType (GetContentBaseType (st.Content)).ListTypeData;
\r
870 else if (st.Content is XmlSchemaSimpleTypeUnion)
\r
872 // Check if all types of the union are equal. If not, then will use anyType.
\r
873 XmlSchemaSimpleTypeUnion uni = (XmlSchemaSimpleTypeUnion) st.Content;
\r
874 TypeData utype = null;
\r
876 // Anonymous types are unique
\r
877 if (uni.BaseTypes.Count != 0 && uni.MemberTypes.Length != 0)
\r
878 return FindBuiltInType (anyType);
\r
880 foreach (XmlQualifiedName mt in uni.MemberTypes)
\r
882 TypeData qn = FindBuiltInType (mt);
\r
883 if (utype != null && qn != utype) return FindBuiltInType (anyType);
\r
892 XmlQualifiedName GetContentBaseType (XmlSchemaObject ob)
\r
894 if (ob is XmlSchemaSimpleContentExtension)
\r
895 return ((XmlSchemaSimpleContentExtension)ob).BaseTypeName;
\r
896 else if (ob is XmlSchemaSimpleContentRestriction)
\r
897 return ((XmlSchemaSimpleContentRestriction)ob).BaseTypeName;
\r
898 else if (ob is XmlSchemaSimpleTypeRestriction)
\r
899 return ((XmlSchemaSimpleTypeRestriction)ob).BaseTypeName;
\r
900 else if (ob is XmlSchemaSimpleTypeList)
\r
901 return ((XmlSchemaSimpleTypeList)ob).ItemTypeName;
\r
906 void ImportComplexContent (XmlQualifiedName typeQName, XmlTypeMapping map, XmlSchemaComplexContent content, CodeIdentifiers classIds, bool isMixed)
\r
908 ClassMap cmap = (ClassMap)map.ObjectMap;
\r
909 XmlQualifiedName qname;
\r
911 XmlSchemaComplexContentExtension ext = content.Content as XmlSchemaComplexContentExtension;
\r
912 if (ext != null) qname = ext.BaseTypeName;
\r
913 else qname = ((XmlSchemaComplexContentRestriction)content.Content).BaseTypeName;
\r
915 if (HasForcedBaseType (typeQName))
\r
916 RegisterForcedBaseType (qname, GetForcedBaseType (typeQName));
\r
918 // Add base map members to this map
\r
920 XmlTypeMapping baseMap = ImportType (qname, null);
\r
921 BuildPendingMap (baseMap);
\r
922 ClassMap baseClassMap = (ClassMap)baseMap.ObjectMap;
\r
924 foreach (XmlTypeMapMember member in baseClassMap.AllMembers)
\r
925 cmap.AddMember (member);
\r
927 if (baseClassMap.XmlTextCollector != null) isMixed = false;
\r
928 else if (content.IsMixed) isMixed = true;
\r
930 map.BaseMap = baseMap;
\r
931 baseMap.DerivedTypes.Add (map);
\r
934 // Add the members of this map
\r
935 if (ext.Particle != null)
\r
936 ImportParticleComplexContent (typeQName, cmap, ext.Particle, classIds, isMixed);
\r
938 ImportAttributes (typeQName, cmap, ext.Attributes, ext.AnyAttribute, classIds);
\r
941 if (isMixed) ImportParticleComplexContent (typeQName, cmap, null, classIds, true);
\r
945 public void ImportForcedDerivedType (XmlTypeMapping map, XmlQualifiedName qname, ref bool isMixed)
\r
947 ClassMap cmap = (ClassMap)map.ObjectMap;
\r
949 XmlTypeMapping baseMap;
\r
950 Type baseType = GetForcedBaseType (qname);
\r
953 if (auxXmlRefImporter == null) auxXmlRefImporter = new XmlReflectionImporter ();
\r
954 baseMap = auxXmlRefImporter.ImportTypeMapping (baseType);
\r
958 if (auxSoapRefImporter == null) auxSoapRefImporter = new SoapReflectionImporter ();
\r
959 baseMap = auxSoapRefImporter.ImportTypeMapping (baseType);
\r
962 ClassMap baseClassMap = (ClassMap)baseMap.ObjectMap;
\r
964 foreach (XmlTypeMapMember member in baseClassMap.AllMembers)
\r
965 cmap.AddMember (member);
\r
967 if (baseClassMap.XmlTextCollector != null) isMixed = false;
\r
969 map.BaseMap = baseMap;
\r
970 baseMap.DerivedTypes.Add (map);
\r
973 void ImportExtensionTypes (XmlQualifiedName qname)
\r
975 foreach (XmlSchema schema in schemas) {
\r
976 foreach (XmlSchemaObject sob in schema.Items)
\r
978 XmlSchemaComplexType sct = sob as XmlSchemaComplexType;
\r
979 if (sct != null && sct.ContentModel is XmlSchemaComplexContent) {
\r
980 XmlQualifiedName exqname;
\r
981 XmlSchemaComplexContentExtension ext = sct.ContentModel.Content as XmlSchemaComplexContentExtension;
\r
982 if (ext != null) exqname = ext.BaseTypeName;
\r
983 else exqname = ((XmlSchemaComplexContentRestriction)sct.ContentModel.Content).BaseTypeName;
\r
984 if (exqname == qname)
\r
985 ImportType (new XmlQualifiedName (sct.Name, schema.TargetNamespace), sct, null);
\r
991 XmlTypeMapping ImportClassSimpleType (XmlQualifiedName typeQName, XmlSchemaSimpleType stype, XmlQualifiedName root)
\r
993 if (CanBeEnum (stype))
\r
995 // Create an enum map
\r
997 CodeIdentifiers codeIdents = new CodeIdentifiers ();
\r
998 XmlTypeMapping enumMap = CreateTypeMapping (typeQName, SchemaTypes.Enum, null);
\r
999 enumMap.Documentation = GetDocumentation (stype);
\r
1001 bool isFlags = false;
\r
1002 if (stype.Content is XmlSchemaSimpleTypeList) {
\r
1003 stype = ((XmlSchemaSimpleTypeList)stype.Content).ItemType;
\r
1006 XmlSchemaSimpleTypeRestriction rest = (XmlSchemaSimpleTypeRestriction)stype.Content;
\r
1008 codeIdents.AddReserved (enumMap.TypeData.TypeName);
\r
1010 EnumMap.EnumMapMember[] members = new EnumMap.EnumMapMember [rest.Facets.Count];
\r
1011 for (int n=0; n<rest.Facets.Count; n++)
\r
1013 XmlSchemaEnumerationFacet enu = (XmlSchemaEnumerationFacet) rest.Facets[n];
\r
1014 string enumName = codeIdents.AddUnique(CodeIdentifier.MakeValid (enu.Value), enu);
\r
1015 members [n] = new EnumMap.EnumMapMember (enu.Value, enumName);
\r
1016 members [n].Documentation = GetDocumentation (enu);
\r
1018 enumMap.ObjectMap = new EnumMap (members, isFlags);
\r
1019 enumMap.IsSimpleType = true;
\r
1023 if (stype.Content is XmlSchemaSimpleTypeList)
\r
1025 XmlSchemaSimpleTypeList slist = (XmlSchemaSimpleTypeList)stype.Content;
\r
1026 TypeData arrayTypeData = FindBuiltInType (slist.ItemTypeName, stype);
\r
1028 ListMap listMap = new ListMap ();
\r
1030 listMap.ItemInfo = new XmlTypeMapElementInfoList ();
\r
1031 listMap.ItemInfo.Add (CreateElementInfo (typeQName.Namespace, null, "Item", arrayTypeData.ListItemTypeData, false));
\r
1033 XmlTypeMapping map = CreateArrayTypeMapping (typeQName, arrayTypeData);
\r
1034 map.ObjectMap = listMap;
\r
1035 map.IsSimpleType = true;
\r
1039 // It is an extension of a primitive or known type
\r
1041 TypeData typeData = FindBuiltInType (typeQName, stype);
\r
1042 return GetTypeMapping (typeData);
\r
1045 bool CanBeEnum (XmlSchemaSimpleType stype)
\r
1047 if (stype.Content is XmlSchemaSimpleTypeRestriction)
\r
1049 XmlSchemaSimpleTypeRestriction rest = (XmlSchemaSimpleTypeRestriction)stype.Content;
\r
1050 foreach (object ob in rest.Facets)
\r
1051 if (!(ob is XmlSchemaEnumerationFacet)) return false;
\r
1054 else if (stype.Content is XmlSchemaSimpleTypeList)
\r
1056 XmlSchemaSimpleTypeList list = (XmlSchemaSimpleTypeList) stype.Content;
\r
1057 return (list.ItemType != null && CanBeEnum (list.ItemType));
\r
1062 bool CanBeArray (XmlQualifiedName typeQName, XmlSchemaComplexType stype)
\r
1064 if (encodedFormat)
\r
1066 XmlSchemaComplexContent content = stype.ContentModel as XmlSchemaComplexContent;
\r
1067 if (content == null) return false;
\r
1068 XmlSchemaComplexContentRestriction rest = content.Content as XmlSchemaComplexContentRestriction;
\r
1069 if (rest == null) return false;
\r
1070 return rest.BaseTypeName == arrayType;
\r
1074 if (stype.Attributes.Count > 0 || stype.AnyAttribute != null) return false;
\r
1075 else return !stype.IsMixed && CanBeArray (typeQName, stype.Particle, false);
\r
1079 bool CanBeArray (XmlQualifiedName typeQName, XmlSchemaParticle particle, bool multiValue)
\r
1081 // To be an array, there can't be a direct child of type typeQName
\r
1083 if (particle == null) return false;
\r
1085 multiValue = multiValue || particle.MaxOccurs > 1;
\r
1087 if (particle is XmlSchemaGroupRef)
\r
1088 return CanBeArray (typeQName, GetRefGroupParticle ((XmlSchemaGroupRef)particle), multiValue);
\r
1090 if (particle is XmlSchemaElement)
\r
1092 XmlSchemaElement elem = (XmlSchemaElement)particle;
\r
1093 if (!elem.RefName.IsEmpty)
\r
1094 return CanBeArray (typeQName, FindRefElement (elem), multiValue);
\r
1096 return multiValue && !typeQName.Equals (((XmlSchemaElement)particle).SchemaTypeName);
\r
1099 if (particle is XmlSchemaAny)
\r
1100 return multiValue;
\r
1102 if (particle is XmlSchemaSequence)
\r
1104 XmlSchemaSequence seq = particle as XmlSchemaSequence;
\r
1105 if (seq.Items.Count != 1) return false;
\r
1106 return CanBeArray (typeQName, (XmlSchemaParticle)seq.Items[0], multiValue);
\r
1109 if (particle is XmlSchemaChoice)
\r
1111 // Can be array if all choices have different types
\r
1112 ArrayList types = new ArrayList ();
\r
1113 if(!CheckChoiceType (typeQName, particle, types, ref multiValue)) return false;
\r
1114 return multiValue;
\r
1120 bool CheckChoiceType (XmlQualifiedName typeQName, XmlSchemaParticle particle, ArrayList types, ref bool multiValue)
\r
1122 XmlQualifiedName type = null;
\r
1124 multiValue = multiValue || particle.MaxOccurs > 1;
\r
1126 if (particle is XmlSchemaGroupRef)
\r
1127 return CheckChoiceType (typeQName, GetRefGroupParticle ((XmlSchemaGroupRef)particle), types, ref multiValue);
\r
1129 if (particle is XmlSchemaElement) {
\r
1131 XmlSchemaElement elem = (XmlSchemaElement)particle;
\r
1132 XmlSchemaElement refElem = GetRefElement (typeQName, elem, out ns);
\r
1133 if (refElem.SchemaType != null) return true;
\r
1134 type = refElem.SchemaTypeName;
\r
1136 else if (particle is XmlSchemaAny) {
\r
1139 else if (particle is XmlSchemaSequence)
\r
1141 XmlSchemaSequence seq = particle as XmlSchemaSequence;
\r
1142 foreach (XmlSchemaParticle par in seq.Items)
\r
1143 if (!CheckChoiceType (typeQName, par, types, ref multiValue)) return false;
\r
1146 else if (particle is XmlSchemaChoice)
\r
1148 foreach (XmlSchemaParticle choice in ((XmlSchemaChoice)particle).Items)
\r
1149 if (!CheckChoiceType (typeQName, choice, types, ref multiValue)) return false;
\r
1153 if (typeQName.Equals (type)) return false;
\r
1155 // For primitive types, compare using CLR types, since several
\r
1156 // xml types can be mapped to a single CLR type
\r
1159 if (type.Namespace == XmlSchema.Namespace)
\r
1160 t = TypeTranslator.GetPrimitiveTypeData (type.Name).FullTypeName + ":" + type.Namespace;
\r
1163 t = type.Name + ":" + type.Namespace;
\r
1165 if (types.Contains (t)) return false;
\r
1170 bool CanBeAnyElement (XmlSchemaComplexType stype)
\r
1172 XmlSchemaSequence seq = stype.Particle as XmlSchemaSequence;
\r
1173 return (seq != null) && (seq.Items.Count == 1) && (seq.Items[0] is XmlSchemaAny);
\r
1176 bool CanBeIXmlSerializable (XmlSchemaComplexType stype)
\r
1178 XmlSchemaSequence seq = stype.Particle as XmlSchemaSequence;
\r
1179 if (seq == null) return false;
\r
1180 if (seq.Items.Count != 2) return false;
\r
1181 XmlSchemaElement elem = seq.Items[0] as XmlSchemaElement;
\r
1182 if (elem == null) return false;
\r
1183 if (elem.RefName != new XmlQualifiedName ("schema",XmlSchema.Namespace)) return false;
\r
1184 return (seq.Items[1] is XmlSchemaAny);
\r
1187 void RegisterForcedBaseType (XmlQualifiedName tname, Type type)
\r
1189 if (forcedBaseTypes == null) forcedBaseTypes = new Hashtable ();
\r
1190 forcedBaseTypes [tname] = type;
\r
1193 bool HasForcedBaseType (XmlQualifiedName tname)
\r
1195 if (forcedBaseTypes == null) return false;
\r
1196 return forcedBaseTypes.ContainsKey (tname);
\r
1199 Type GetForcedBaseType (XmlQualifiedName tname)
\r
1201 if (forcedBaseTypes == null) return null;
\r
1202 return (Type) forcedBaseTypes [tname];
\r
1205 XmlTypeMapElementInfo CreateElementInfo (string ns, XmlTypeMapMember member, string name, TypeData typeData, bool isNillable)
\r
1207 XmlTypeMapElementInfo einfo = new XmlTypeMapElementInfo (member, typeData);
\r
1208 einfo.ElementName = name;
\r
1209 einfo.Namespace = ns;
\r
1210 einfo.IsNullable = isNillable;
\r
1211 if (einfo.TypeData.IsComplexType)
\r
1212 einfo.MappedType = GetTypeMapping (typeData);
\r
1216 XmlTypeMapElementInfo CreateTextElementInfo (string ns, XmlTypeMapMember member, TypeData typeData)
\r
1218 XmlTypeMapElementInfo einfo = new XmlTypeMapElementInfo (member, typeData);
\r
1219 einfo.IsTextElement = true;
\r
1220 einfo.WrappedElement = false;
\r
1221 if (typeData.IsComplexType)
\r
1222 einfo.MappedType = GetTypeMapping (typeData);
\r
1226 XmlTypeMapping CreateTypeMapping (XmlQualifiedName typeQName, SchemaTypes schemaType, XmlQualifiedName root)
\r
1228 string typeName = CodeIdentifier.MakeValid (typeQName.Name);
\r
1229 typeName = typeIdentifiers.AddUnique (typeName, null);
\r
1231 TypeData typeData = new TypeData (typeName, typeName, typeName, schemaType, null);
\r
1235 if (root != null) {
\r
1236 rootElem = root.Name;
\r
1237 rootNs = root.Namespace;
\r
1240 rootElem = typeQName.Name;
\r
1244 XmlTypeMapping map = new XmlTypeMapping (rootElem, rootNs, typeData, typeQName.Name, typeQName.Namespace);
\r
1245 map.IncludeInSchema = true;
\r
1246 mappedTypes [typeQName] = map;
\r
1247 dataMappedTypes [typeData] = map;
\r
1252 XmlTypeMapping CreateArrayTypeMapping (XmlQualifiedName typeQName, TypeData arrayTypeData)
\r
1254 XmlTypeMapping map;
\r
1255 if (encodedFormat) map = new XmlTypeMapping ("Array", XmlSerializer.EncodingNamespace, arrayTypeData, "Array", XmlSerializer.EncodingNamespace);
\r
1256 else map = new XmlTypeMapping (arrayTypeData.XmlType, typeQName.Namespace, arrayTypeData, arrayTypeData.XmlType, typeQName.Namespace);
\r
1258 map.IncludeInSchema = true;
\r
1259 mappedTypes [typeQName] = map;
\r
1260 dataMappedTypes [arrayTypeData] = map;
\r
1265 XmlSchemaElement GetRefElement (XmlQualifiedName typeQName, XmlSchemaElement elem, out string ns)
\r
1268 if (!elem.RefName.IsEmpty)
\r
1270 ns = elem.RefName.Namespace;
\r
1271 return FindRefElement (elem);
\r
1275 ns = typeQName.Namespace;
\r
1280 XmlSchemaAttribute GetRefAttribute (XmlQualifiedName typeQName, XmlSchemaAttribute attr, out string ns)
\r
1282 if (!attr.RefName.IsEmpty)
\r
1284 ns = attr.RefName.Namespace;
\r
1285 return FindRefAttribute (attr.RefName);
\r
1289 ns = typeQName.Namespace;
\r
1294 TypeData GetElementTypeData (XmlQualifiedName typeQName, XmlSchemaElement elem)
\r
1296 bool sharedAnnType = false;
\r
1297 XmlQualifiedName root = null;
\r
1299 if (!elem.RefName.IsEmpty) {
\r
1300 XmlSchemaElement refElem = FindRefElement (elem);
\r
1301 if (refElem == null) throw new InvalidOperationException ("Global element not found: " + elem.RefName);
\r
1302 root = elem.RefName;
\r
1304 sharedAnnType = true;
\r
1307 if (!elem.SchemaTypeName.IsEmpty) return GetTypeData (elem.SchemaTypeName, root);
\r
1308 else if (elem.SchemaType == null) return TypeTranslator.GetTypeData (typeof(object));
\r
1309 else return GetTypeData (elem.SchemaType, typeQName, elem.Name, sharedAnnType, root);
\r
1312 TypeData GetAttributeTypeData (XmlQualifiedName typeQName, XmlSchemaAttribute attr)
\r
1314 bool sharedAnnType = false;
\r
1316 if (!attr.RefName.IsEmpty) {
\r
1317 XmlSchemaAttribute refAtt = FindRefAttribute (attr.RefName);
\r
1318 if (refAtt == null) throw new InvalidOperationException ("Global attribute not found: " + attr.RefName);
\r
1320 sharedAnnType = true;
\r
1323 if (!attr.SchemaTypeName.IsEmpty) return GetTypeData (attr.SchemaTypeName, null);
\r
1324 else return GetTypeData (attr.SchemaType, typeQName, attr.Name, sharedAnnType, null);
\r
1327 TypeData GetTypeData (XmlQualifiedName typeQName, XmlQualifiedName root)
\r
1329 if (typeQName.Namespace == XmlSchema.Namespace || (encodedFormat && typeQName.Namespace == ""))
\r
1330 return TypeTranslator.GetPrimitiveTypeData (typeQName.Name);
\r
1332 return ImportType (typeQName, root).TypeData;
\r
1335 TypeData GetTypeData (XmlSchemaType stype, XmlQualifiedName typeQNname, string propertyName, bool sharedAnnType, XmlQualifiedName root)
\r
1339 if (sharedAnnType)
\r
1341 // Anonymous types defined in root elements or attributes can be shared among all elements that
\r
1342 // reference this root element or attribute
\r
1343 TypeData std = sharedAnonymousTypes [stype] as TypeData;
\r
1344 if (std != null) return std;
\r
1345 baseName = propertyName;
\r
1348 baseName = typeQNname.Name + typeIdentifiers.MakeRightCase (propertyName);
\r
1350 baseName = elemIdentifiers.AddUnique (baseName, stype);
\r
1352 XmlQualifiedName newName;
\r
1353 newName = new XmlQualifiedName (baseName, typeQNname.Namespace);
\r
1355 XmlTypeMapping map = ImportType (newName, stype, root);
\r
1356 if (sharedAnnType) sharedAnonymousTypes [stype] = map.TypeData;
\r
1358 return map.TypeData;
\r
1361 XmlTypeMapping GetTypeMapping (TypeData typeData)
\r
1363 XmlTypeMapping map = (XmlTypeMapping) dataMappedTypes [typeData];
\r
1364 if (map != null) return map;
\r
1366 if (map == null && typeData.IsListType)
\r
1368 // Create an array map for the type
\r
1370 XmlTypeMapping itemMap = GetTypeMapping (typeData.ListItemTypeData);
\r
1372 map = new XmlTypeMapping (typeData.XmlType, itemMap.Namespace, typeData, typeData.XmlType, itemMap.Namespace);
\r
1373 map.IncludeInSchema = true;
\r
1375 ListMap listMap = new ListMap ();
\r
1376 listMap.ItemInfo = new XmlTypeMapElementInfoList();
\r
1377 listMap.ItemInfo.Add (CreateElementInfo (itemMap.Namespace, null, typeData.ListItemTypeData.XmlType, typeData.ListItemTypeData, false));
\r
1378 map.ObjectMap = listMap;
\r
1380 mappedTypes [new XmlQualifiedName(map.ElementName, map.Namespace)] = map;
\r
1381 dataMappedTypes [typeData] = map;
\r
1384 else if (typeData.SchemaType == SchemaTypes.Primitive || typeData.Type == typeof(object) || typeof(XmlNode).IsAssignableFrom(typeData.Type))
\r
1386 map = new XmlTypeMapping (typeData.XmlType, XmlSchema.Namespace, typeData, typeData.XmlType, XmlSchema.Namespace);
\r
1387 map.IncludeInSchema = false;
\r
1388 dataMappedTypes [typeData] = map;
\r
1392 throw new InvalidOperationException ("Map for type " + typeData.TypeName + " not found");
\r
1395 XmlTypeMapping GetRegisteredTypeMapping (XmlQualifiedName typeQName)
\r
1397 return (XmlTypeMapping) mappedTypes [typeQName];
\r
1400 XmlSchemaParticle GetRefGroupParticle (XmlSchemaGroupRef refGroup)
\r
1402 XmlSchemaGroup grp = (XmlSchemaGroup) schemas.Find (refGroup.RefName, typeof (XmlSchemaGroup));
\r
1403 return grp.Particle;
\r
1406 XmlSchemaElement FindRefElement (XmlSchemaElement elem)
\r
1408 if (elem.RefName.Namespace == XmlSchema.Namespace)
\r
1410 if (anyElement != null) return anyElement;
\r
1411 anyElement = new XmlSchemaElement ();
\r
1412 anyElement.Name = "any";
\r
1413 anyElement.SchemaTypeName = anyType;
\r
1414 return anyElement;
\r
1416 return (XmlSchemaElement) schemas.Find (elem.RefName, typeof(XmlSchemaElement));
\r
1419 XmlSchemaAttribute FindRefAttribute (XmlQualifiedName refName)
\r
1421 if (refName.Namespace == XmlNamespace)
\r
1423 XmlSchemaAttribute at = new XmlSchemaAttribute ();
\r
1424 at.Name = refName.Name;
\r
1425 at.SchemaTypeName = new XmlQualifiedName ("string",XmlSchema.Namespace);
\r
1428 return (XmlSchemaAttribute) schemas.Find (refName, typeof(XmlSchemaAttribute));
\r
1431 string GetDocumentation (XmlSchemaAnnotated elem)
\r
1434 XmlSchemaAnnotation anot = elem.Annotation;
\r
1435 if (anot == null || anot.Items == null) return null;
\r
1437 foreach (object ob in anot.Items)
\r
1439 XmlSchemaDocumentation doc = ob as XmlSchemaDocumentation;
\r
1440 if (doc != null && doc.Markup != null && doc.Markup.Length > 0) {
\r
1441 if (res != string.Empty) res += "\n";
\r
1442 foreach (XmlNode node in doc.Markup)
\r
1443 res += node.Value;
\r
1449 #endregion // Methods
\r