2 // System.Xml.Serialization.XmlSchemaExporter
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 using System.Xml.Schema;
34 using System.Collections;
36 namespace System.Xml.Serialization {
37 public class XmlSchemaExporter {
42 Hashtable exportedMaps = new Hashtable();
43 Hashtable exportedElements = new Hashtable();
44 bool encodedFormat = false;
51 public XmlSchemaExporter (XmlSchemas schemas)
53 this.schemas = schemas;
56 internal XmlSchemaExporter (XmlSchemas schemas, bool encodedFormat)
58 this.encodedFormat = encodedFormat;
59 this.schemas = schemas;
62 #endregion // Constructors
67 public string ExportAnyType (string ns)
69 throw new NotImplementedException ();
72 [MonoNotSupported("")]
73 public string ExportAnyType (XmlMembersMapping members)
75 throw new NotImplementedException ();
78 public void ExportMembersMapping (XmlMembersMapping xmlMembersMapping)
80 ExportMembersMapping (xmlMembersMapping, true);
84 void ExportMembersMapping (XmlMembersMapping xmlMembersMapping, bool exportEnclosingType)
86 ClassMap cmap = (ClassMap) xmlMembersMapping.ObjectMap;
88 if (xmlMembersMapping.HasWrapperElement && exportEnclosingType)
90 XmlSchema schema = GetSchema (xmlMembersMapping.Namespace);
91 XmlSchemaComplexType stype = new XmlSchemaComplexType ();
93 XmlSchemaSequence particle;
94 XmlSchemaAnyAttribute anyAttribute;
95 ExportMembersMapSchema (schema, cmap, null, stype.Attributes, out particle, out anyAttribute);
96 stype.Particle = particle;
97 stype.AnyAttribute = anyAttribute;
101 stype.Name = xmlMembersMapping.ElementName;
102 schema.Items.Add (stype);
106 XmlSchemaElement selem = new XmlSchemaElement ();
107 selem.Name = xmlMembersMapping.ElementName;
108 selem.SchemaType = stype;
109 schema.Items.Add (selem);
114 ICollection members = cmap.ElementMembers;
117 foreach (XmlTypeMapMemberElement member in members)
119 if (member is XmlTypeMapMemberAnyElement && member.TypeData.IsListType)
121 XmlSchema mschema = GetSchema (xmlMembersMapping.Namespace);
122 XmlSchemaParticle par = GetSchemaArrayElement (mschema, member.ElementInfo);
123 if (par is XmlSchemaAny)
125 XmlSchemaComplexType ct = FindComplexType (mschema.Items, "any");
126 if (ct != null) continue;
128 ct = new XmlSchemaComplexType ();
131 XmlSchemaSequence seq = new XmlSchemaSequence ();
134 mschema.Items.Add (ct);
140 XmlTypeMapElementInfo einfo = (XmlTypeMapElementInfo) member.ElementInfo [0];
145 schema = GetSchema (xmlMembersMapping.Namespace);
146 ImportNamespace (schema, XmlSerializer.EncodingNamespace);
149 schema = GetSchema (einfo.Namespace);
152 XmlSchemaElement exe = FindElement (schema.Items, einfo.ElementName);
153 XmlSchemaElement elem;
155 XmlSchemaObjectContainer container = null;
156 // In encoded format, the schema elements are not needed
158 container = new XmlSchemaObjectContainer (schema);
160 Type memType = member.GetType();
161 if (member is XmlTypeMapMemberFlatList)
162 throw new InvalidOperationException ("Unwrapped arrays not supported as parameters");
163 else if (memType == typeof(XmlTypeMapMemberElement))
164 elem = (XmlSchemaElement) GetSchemaElement (schema,
165 einfo, member.DefaultValue, false, container);
167 elem = (XmlSchemaElement) GetSchemaElement (schema,
168 einfo, false, container);
172 if (exe.SchemaTypeName.Equals (elem.SchemaTypeName))
173 schema.Items.Remove (elem);
176 string s = "The XML element named '" + einfo.ElementName + "' ";
177 s += "from namespace '" + schema.TargetNamespace + "' references distinct types " + elem.SchemaTypeName.Name + " and " + exe.SchemaTypeName.Name + ". ";
178 s += "Use XML attributes to specify another XML name or namespace for the element or types.";
179 throw new InvalidOperationException (s);
190 public XmlQualifiedName ExportTypeMapping (XmlMembersMapping xmlMembersMapping)
192 throw new NotImplementedException ();
195 public void ExportTypeMapping (XmlTypeMapping xmlTypeMapping)
197 if (!xmlTypeMapping.IncludeInSchema) return;
198 if (IsElementExported (xmlTypeMapping)) return;
202 ExportClassSchema (xmlTypeMapping);
203 XmlSchema schema = GetSchema (xmlTypeMapping.XmlTypeNamespace);
204 ImportNamespace (schema, XmlSerializer.EncodingNamespace);
208 XmlSchema schema = GetSchema (xmlTypeMapping.Namespace);
209 XmlTypeMapElementInfo einfo = new XmlTypeMapElementInfo (null, xmlTypeMapping.TypeData);
210 einfo.Namespace = xmlTypeMapping.Namespace;
211 einfo.ElementName = xmlTypeMapping.ElementName;
212 if (xmlTypeMapping.TypeData.IsComplexType)
213 einfo.MappedType = xmlTypeMapping;
214 einfo.IsNullable = xmlTypeMapping.IsNullable;
215 GetSchemaElement (schema, einfo, false, new XmlSchemaObjectContainer (schema));
216 SetElementExported (xmlTypeMapping);
222 void ExportXmlSerializableSchema (XmlSchema currentSchema, XmlSerializableMapping map)
224 if (IsMapExported (map)) return;
225 SetMapExported (map);
227 if (map.Schema == null) return;
229 string targetNs = map.Schema.TargetNamespace;
230 XmlSchema existingSchema = schemas [targetNs];
231 if (existingSchema == null)
233 schemas.Add (map.Schema);
234 ImportNamespace (currentSchema, targetNs);
236 else if (existingSchema != map.Schema && !CanBeDuplicated (existingSchema, map.Schema))
238 throw new InvalidOperationException("The namespace '" + targetNs +"' defined by the class '" + map.TypeFullName + "' is a duplicate.");
242 private static bool CanBeDuplicated (XmlSchema existingSchema, XmlSchema schema)
244 if(XmlSchemas.IsDataSet (existingSchema) && XmlSchemas.IsDataSet (schema)
245 && existingSchema.Id == schema.Id)
250 void ExportClassSchema (XmlTypeMapping map)
252 if (IsMapExported (map)) return;
253 SetMapExported (map);
255 if (map.TypeData.Type == typeof(object))
257 foreach (XmlTypeMapping dmap in map.DerivedTypes)
258 if (dmap.TypeData.SchemaType == SchemaTypes.Class) ExportClassSchema (dmap);
262 XmlSchema schema = GetSchema (map.XmlTypeNamespace);
263 XmlSchemaComplexType stype = new XmlSchemaComplexType ();
264 stype.Name = map.XmlType;
265 schema.Items.Add (stype);
267 ClassMap cmap = (ClassMap)map.ObjectMap;
269 if (cmap.HasSimpleContent)
271 XmlSchemaSimpleContent simple = new XmlSchemaSimpleContent ();
272 stype.ContentModel = simple;
273 XmlSchemaSimpleContentExtension ext = new XmlSchemaSimpleContentExtension ();
274 simple.Content = ext;
275 XmlSchemaSequence particle;
276 XmlSchemaAnyAttribute anyAttribute;
277 ExportMembersMapSchema (schema, cmap, map.BaseMap, ext.Attributes, out particle, out anyAttribute);
278 ext.AnyAttribute = anyAttribute;
279 if (map.BaseMap == null)
280 ext.BaseTypeName = cmap.SimpleContentBaseType;
282 ext.BaseTypeName = new XmlQualifiedName (map.BaseMap.XmlType, map.BaseMap.XmlTypeNamespace);
283 ImportNamespace (schema, map.BaseMap.XmlTypeNamespace);
284 ExportClassSchema (map.BaseMap);
287 else if (map.BaseMap != null && map.BaseMap.IncludeInSchema)
289 XmlSchemaComplexContent cstype = new XmlSchemaComplexContent ();
290 XmlSchemaComplexContentExtension ext = new XmlSchemaComplexContentExtension ();
291 ext.BaseTypeName = new XmlQualifiedName (map.BaseMap.XmlType, map.BaseMap.XmlTypeNamespace);
292 cstype.Content = ext;
293 stype.ContentModel = cstype;
295 XmlSchemaSequence particle;
296 XmlSchemaAnyAttribute anyAttribute;
297 ExportMembersMapSchema (schema, cmap, map.BaseMap, ext.Attributes, out particle, out anyAttribute);
298 ext.Particle = particle;
299 ext.AnyAttribute = anyAttribute;
300 stype.IsMixed = HasMixedContent (map);
301 cstype.IsMixed = BaseHasMixedContent (map);
303 ImportNamespace (schema, map.BaseMap.XmlTypeNamespace);
304 ExportClassSchema (map.BaseMap);
308 XmlSchemaSequence particle;
309 XmlSchemaAnyAttribute anyAttribute;
310 ExportMembersMapSchema (schema, cmap, map.BaseMap, stype.Attributes, out particle, out anyAttribute);
311 stype.Particle = particle;
312 stype.AnyAttribute = anyAttribute;
313 stype.IsMixed = cmap.XmlTextCollector != null;
316 foreach (XmlTypeMapping dmap in map.DerivedTypes)
317 if (dmap.TypeData.SchemaType == SchemaTypes.Class) ExportClassSchema (dmap);
320 bool BaseHasMixedContent (XmlTypeMapping map)
322 ClassMap cmap = (ClassMap)map.ObjectMap;
323 return (cmap.XmlTextCollector != null && (map.BaseMap != null && DefinedInBaseMap (map.BaseMap, cmap.XmlTextCollector)));
326 bool HasMixedContent (XmlTypeMapping map)
328 ClassMap cmap = (ClassMap)map.ObjectMap;
329 return (cmap.XmlTextCollector != null && (map.BaseMap == null || !DefinedInBaseMap (map.BaseMap, cmap.XmlTextCollector)));
332 void ExportMembersMapSchema (XmlSchema schema, ClassMap map, XmlTypeMapping baseMap, XmlSchemaObjectCollection outAttributes, out XmlSchemaSequence particle, out XmlSchemaAnyAttribute anyAttribute)
335 XmlSchemaSequence seq = new XmlSchemaSequence ();
337 ICollection members = map.ElementMembers;
338 if (members != null && !map.HasSimpleContent)
340 foreach (XmlTypeMapMemberElement member in members)
342 if (baseMap != null && DefinedInBaseMap (baseMap, member)) continue;
344 Type memType = member.GetType();
345 if (memType == typeof(XmlTypeMapMemberFlatList))
347 XmlSchemaParticle part = GetSchemaArrayElement (schema, member.ElementInfo);
348 if (part != null) seq.Items.Add (part);
350 else if (memType == typeof(XmlTypeMapMemberAnyElement))
352 seq.Items.Add (GetSchemaArrayElement (schema, member.ElementInfo));
354 else if (memType == typeof(XmlTypeMapMemberElement))
356 GetSchemaElement (schema, (XmlTypeMapElementInfo) member.ElementInfo [0],
357 member.DefaultValue, true, new XmlSchemaObjectContainer (seq));
361 GetSchemaElement (schema, (XmlTypeMapElementInfo) member.ElementInfo[0],
362 true, new XmlSchemaObjectContainer (seq));
367 if (seq.Items.Count > 0)
372 ICollection attributes = map.AttributeMembers;
373 if (attributes != null)
375 foreach (XmlTypeMapMemberAttribute attr in attributes) {
376 if (baseMap != null && DefinedInBaseMap (baseMap, attr)) continue;
377 outAttributes.Add (GetSchemaAttribute (schema, attr, true));
381 XmlTypeMapMember anyAttrMember = map.DefaultAnyAttributeMember;
382 if (anyAttrMember != null)
383 anyAttribute = new XmlSchemaAnyAttribute ();
388 XmlSchemaElement FindElement (XmlSchemaObjectCollection col, string name)
390 foreach (XmlSchemaObject ob in col)
392 XmlSchemaElement elem = ob as XmlSchemaElement;
393 if (elem != null && elem.Name == name) return elem;
398 XmlSchemaComplexType FindComplexType (XmlSchemaObjectCollection col, string name)
400 foreach (XmlSchemaObject ob in col)
402 XmlSchemaComplexType ctype = ob as XmlSchemaComplexType;
403 if (ctype != null && ctype.Name == name) return ctype;
408 XmlSchemaAttribute GetSchemaAttribute (XmlSchema currentSchema, XmlTypeMapMemberAttribute attinfo, bool isTypeMember)
410 XmlSchemaAttribute sat = new XmlSchemaAttribute ();
411 if (attinfo.DefaultValue != System.DBNull.Value) {
412 sat.DefaultValue = ExportDefaultValue (attinfo.TypeData,
413 attinfo.MappedType, attinfo.DefaultValue);
415 if (!attinfo.IsOptionalValueType && attinfo.TypeData.IsValueType)
416 sat.Use = XmlSchemaUse.Required;
419 ImportNamespace (currentSchema, attinfo.Namespace);
421 XmlSchema memberSchema;
422 if (attinfo.Namespace.Length == 0 && attinfo.Form != XmlSchemaForm.Qualified)
423 memberSchema = currentSchema;
425 memberSchema = GetSchema (attinfo.Namespace);
427 if (currentSchema == memberSchema || encodedFormat)
429 sat.Name = attinfo.AttributeName;
430 if (isTypeMember) sat.Form = attinfo.Form;
431 if (attinfo.TypeData.SchemaType == SchemaTypes.Enum)
433 ImportNamespace (currentSchema, attinfo.DataTypeNamespace);
434 ExportEnumSchema (attinfo.MappedType);
435 sat.SchemaTypeName = new XmlQualifiedName (attinfo.TypeData.XmlType, attinfo.DataTypeNamespace);
437 else if (attinfo.TypeData.SchemaType == SchemaTypes.Array && TypeTranslator.IsPrimitive (attinfo.TypeData.ListItemType))
439 sat.SchemaType = GetSchemaSimpleListType (attinfo.TypeData);
442 sat.SchemaTypeName = new XmlQualifiedName (attinfo.TypeData.XmlType, attinfo.DataTypeNamespace);;
446 sat.RefName = new XmlQualifiedName (attinfo.AttributeName, attinfo.Namespace);
447 foreach (XmlSchemaObject ob in memberSchema.Items)
448 if (ob is XmlSchemaAttribute && ((XmlSchemaAttribute)ob).Name == attinfo.AttributeName)
451 memberSchema.Items.Add (GetSchemaAttribute (memberSchema, attinfo, false));
456 XmlSchemaParticle GetSchemaElement (XmlSchema currentSchema, XmlTypeMapElementInfo einfo, bool isTypeMember)
458 return GetSchemaElement (currentSchema, einfo, System.DBNull.Value,
459 isTypeMember, (XmlSchemaObjectContainer) null);
462 XmlSchemaParticle GetSchemaElement (XmlSchema currentSchema, XmlTypeMapElementInfo einfo, bool isTypeMember, XmlSchemaObjectContainer container)
464 return GetSchemaElement (currentSchema, einfo, System.DBNull.Value, isTypeMember, container);
467 XmlSchemaParticle GetSchemaElement (XmlSchema currentSchema, XmlTypeMapElementInfo einfo, object defaultValue, bool isTypeMember, XmlSchemaObjectContainer container)
469 if (einfo.IsTextElement) return null;
471 if (einfo.IsUnnamedAnyElement)
473 XmlSchemaAny any = new XmlSchemaAny ();
476 if (container != null)
477 container.Items.Add (any);
481 XmlSchemaElement selem = new XmlSchemaElement ();
482 selem.IsNillable = einfo.IsNullable;
483 if (container != null)
484 container.Items.Add (selem);
489 selem.MinOccurs = einfo.IsNullable ? 1 : 0;
491 if ((defaultValue == DBNull.Value && einfo.TypeData.IsValueType && einfo.Member != null && !einfo.Member.IsOptionalValueType) || encodedFormat)
495 XmlSchema memberSchema = null;
499 memberSchema = GetSchema (einfo.Namespace);
500 ImportNamespace (currentSchema, einfo.Namespace);
503 if (currentSchema == memberSchema || encodedFormat || !isTypeMember)
505 if (isTypeMember) selem.IsNillable = einfo.IsNullable;
506 selem.Name = einfo.ElementName;
508 if (defaultValue != System.DBNull.Value)
509 selem.DefaultValue = ExportDefaultValue (einfo.TypeData,
510 einfo.MappedType, defaultValue);
512 if (einfo.Form != XmlSchemaForm.Qualified)
513 selem.Form = einfo.Form;
515 switch (einfo.TypeData.SchemaType)
517 case SchemaTypes.XmlNode:
518 selem.SchemaType = GetSchemaXmlNodeType ();
521 case SchemaTypes.XmlSerializable:
522 SetSchemaXmlSerializableType (einfo.MappedType as XmlSerializableMapping, selem);
523 ExportXmlSerializableSchema (currentSchema, einfo.MappedType as XmlSerializableMapping);
526 case SchemaTypes.Enum:
527 selem.SchemaTypeName = new XmlQualifiedName (einfo.MappedType.XmlType, einfo.MappedType.XmlTypeNamespace);
528 ImportNamespace (currentSchema, einfo.MappedType.XmlTypeNamespace);
529 ExportEnumSchema (einfo.MappedType);
532 case SchemaTypes.Array:
533 XmlQualifiedName atypeName = ExportArraySchema (einfo.MappedType, currentSchema.TargetNamespace);
534 selem.SchemaTypeName = atypeName;
535 ImportNamespace (currentSchema, atypeName.Namespace);
538 case SchemaTypes.Class:
539 if (einfo.MappedType.TypeData.Type != typeof(object)) {
540 selem.SchemaTypeName = new XmlQualifiedName (einfo.MappedType.XmlType, einfo.MappedType.XmlTypeNamespace);
541 ImportNamespace (currentSchema, einfo.MappedType.XmlTypeNamespace);
543 else if (encodedFormat)
544 selem.SchemaTypeName = new XmlQualifiedName (einfo.MappedType.XmlType, einfo.MappedType.XmlTypeNamespace);
546 ExportClassSchema (einfo.MappedType);
549 case SchemaTypes.Primitive:
550 selem.SchemaTypeName = new XmlQualifiedName (einfo.TypeData.XmlType, einfo.DataTypeNamespace);
551 if (!einfo.TypeData.IsXsdType) {
552 ImportNamespace (currentSchema, einfo.MappedType.XmlTypeNamespace);
553 ExportDerivedSchema (einfo.MappedType);
560 selem.RefName = new XmlQualifiedName (einfo.ElementName, einfo.Namespace);
561 foreach (XmlSchemaObject ob in memberSchema.Items)
562 if (ob is XmlSchemaElement && ((XmlSchemaElement)ob).Name == einfo.ElementName)
565 GetSchemaElement (memberSchema, einfo, defaultValue, false,
566 new XmlSchemaObjectContainer (memberSchema));
571 void ImportNamespace (XmlSchema schema, string ns)
573 if (ns == null || ns.Length == 0 ||
574 ns == schema.TargetNamespace || ns == XmlSchema.Namespace) return;
576 foreach (XmlSchemaObject sob in schema.Includes)
577 if ((sob is XmlSchemaImport) && ((XmlSchemaImport)sob).Namespace == ns) return;
579 XmlSchemaImport imp = new XmlSchemaImport ();
581 schema.Includes.Add (imp);
584 bool DefinedInBaseMap (XmlTypeMapping map, XmlTypeMapMember member)
586 if (((ClassMap)map.ObjectMap).FindMember (member.Name) != null)
588 else if (map.BaseMap != null)
589 return DefinedInBaseMap (map.BaseMap, member);
594 XmlSchemaType GetSchemaXmlNodeType ()
596 XmlSchemaComplexType stype = new XmlSchemaComplexType ();
597 stype.IsMixed = true;
598 XmlSchemaSequence seq = new XmlSchemaSequence ();
599 seq.Items.Add (new XmlSchemaAny ());
600 stype.Particle = seq;
604 void SetSchemaXmlSerializableType (XmlSerializableMapping map, XmlSchemaElement elem)
606 if (map.SchemaType != null && map.Schema != null) {
607 elem.SchemaType = map.SchemaType;
611 if (map.SchemaType == null && map.SchemaTypeName != null) {
612 elem.SchemaTypeName = map.SchemaTypeName;
613 elem.Name = map.SchemaTypeName.Name;
616 XmlSchemaComplexType stype = new XmlSchemaComplexType ();
617 XmlSchemaSequence seq = new XmlSchemaSequence ();
618 if (map.Schema == null) {
619 XmlSchemaElement selem = new XmlSchemaElement ();
620 selem.RefName = new XmlQualifiedName ("schema",XmlSchema.Namespace);
621 seq.Items.Add (selem);
622 seq.Items.Add (new XmlSchemaAny ());
624 XmlSchemaAny any = new XmlSchemaAny ();
625 any.Namespace = map.Schema.TargetNamespace;
628 stype.Particle = seq;
629 elem.SchemaType = stype;
632 XmlSchemaSimpleType GetSchemaSimpleListType (TypeData typeData)
634 XmlSchemaSimpleType stype = new XmlSchemaSimpleType ();
635 XmlSchemaSimpleTypeList list = new XmlSchemaSimpleTypeList ();
636 TypeData itemTypeData = TypeTranslator.GetTypeData (typeData.ListItemType);
637 list.ItemTypeName = new XmlQualifiedName (itemTypeData.XmlType, XmlSchema.Namespace);
638 stype.Content = list;
642 XmlSchemaParticle GetSchemaArrayElement (XmlSchema currentSchema, XmlTypeMapElementInfoList infos)
644 int numInfos = infos.Count;
645 if (numInfos > 0 && ((XmlTypeMapElementInfo)infos[0]).IsTextElement) numInfos--;
646 if (numInfos == 0) return null;
650 XmlSchemaParticle selem = GetSchemaElement (currentSchema, (XmlTypeMapElementInfo) infos[infos.Count-1], true);
651 selem.MinOccursString = "0";
652 selem.MaxOccursString = "unbounded";
657 XmlSchemaChoice schoice = new XmlSchemaChoice ();
658 schoice.MinOccursString = "0";
659 schoice.MaxOccursString = "unbounded";
660 foreach (XmlTypeMapElementInfo einfo in infos)
662 if (einfo.IsTextElement) continue;
663 schoice.Items.Add (GetSchemaElement (currentSchema, einfo, true));
669 string ExportDefaultValue (TypeData typeData, XmlTypeMapping map, object defaultValue)
671 if (typeData.SchemaType == SchemaTypes.Enum) {
672 EnumMap enumMap = (EnumMap) map.ObjectMap;
673 // get corresponding xml name
674 return enumMap.GetXmlName (map.TypeFullName, defaultValue);
676 return XmlCustomFormatter.ToXmlString (typeData, defaultValue);
679 void ExportDerivedSchema(XmlTypeMapping map) {
680 if (IsMapExported (map)) return;
681 SetMapExported (map);
683 XmlSchema schema = GetSchema (map.XmlTypeNamespace);
684 for (int i = 0; i < schema.Items.Count; i++) {
685 XmlSchemaSimpleType item = schema.Items [i] as XmlSchemaSimpleType;
686 if (item != null && item.Name == map.ElementName)
689 XmlSchemaSimpleType stype = new XmlSchemaSimpleType ();
690 stype.Name = map.ElementName;
691 schema.Items.Add (stype);
693 XmlSchemaSimpleTypeRestriction rest = new XmlSchemaSimpleTypeRestriction ();
694 rest.BaseTypeName = new XmlQualifiedName (map.TypeData.MappedType.XmlType, XmlSchema.Namespace);
695 XmlSchemaPatternFacet facet = map.TypeData.XmlSchemaPatternFacet;
697 rest.Facets.Add(facet);
698 stype.Content = rest;
701 void ExportEnumSchema (XmlTypeMapping map)
703 if (IsMapExported (map)) return;
704 SetMapExported (map);
706 XmlSchema schema = GetSchema (map.XmlTypeNamespace);
707 XmlSchemaSimpleType stype = new XmlSchemaSimpleType ();
708 stype.Name = map.ElementName;
709 schema.Items.Add (stype);
711 XmlSchemaSimpleTypeRestriction rest = new XmlSchemaSimpleTypeRestriction ();
712 rest.BaseTypeName = new XmlQualifiedName ("string",XmlSchema.Namespace);
713 EnumMap emap = (EnumMap) map.ObjectMap;
715 foreach (EnumMap.EnumMapMember emem in emap.Members)
717 XmlSchemaEnumerationFacet ef = new XmlSchemaEnumerationFacet ();
718 ef.Value = emem.XmlName;
719 rest.Facets.Add (ef);
723 XmlSchemaSimpleTypeList slist = new XmlSchemaSimpleTypeList ();
724 XmlSchemaSimpleType restrictionType = new XmlSchemaSimpleType ();
725 restrictionType.Content = rest;
726 slist.ItemType = restrictionType;
727 stype.Content = slist;
729 stype.Content = rest;
733 XmlQualifiedName ExportArraySchema (XmlTypeMapping map, string defaultNamespace)
735 ListMap lmap = (ListMap) map.ObjectMap;
739 string name, ns, schemaNs;
740 lmap.GetArrayType (-1, out name, out ns);
741 if (ns == XmlSchema.Namespace) schemaNs = defaultNamespace;
744 if (IsMapExported (map)) return new XmlQualifiedName (lmap.GetSchemaArrayName (), schemaNs);
745 SetMapExported (map);
747 XmlSchema schema = GetSchema (schemaNs);
748 XmlSchemaComplexType stype = new XmlSchemaComplexType ();
749 stype.Name = lmap.GetSchemaArrayName ();
750 schema.Items.Add (stype);
752 XmlSchemaComplexContent content = new XmlSchemaComplexContent();
753 content.IsMixed = false;
754 stype.ContentModel = content;
756 XmlSchemaComplexContentRestriction rest = new XmlSchemaComplexContentRestriction ();
757 content.Content = rest;
758 rest.BaseTypeName = new XmlQualifiedName ("Array", XmlSerializer.EncodingNamespace);
759 XmlSchemaAttribute at = new XmlSchemaAttribute ();
760 rest.Attributes.Add (at);
761 at.RefName = new XmlQualifiedName ("arrayType", XmlSerializer.EncodingNamespace);
763 XmlAttribute arrayType = Document.CreateAttribute ("arrayType", XmlSerializer.WsdlNamespace);
764 arrayType.Value = ns + (ns != "" ? ":" : "") + name;
765 at.UnhandledAttributes = new XmlAttribute [] { arrayType };
766 ImportNamespace (schema, XmlSerializer.WsdlNamespace);
768 XmlTypeMapElementInfo einfo = (XmlTypeMapElementInfo) lmap.ItemInfo[0];
769 if (einfo.MappedType != null)
771 switch (einfo.TypeData.SchemaType)
773 case SchemaTypes.Enum:
774 ExportEnumSchema (einfo.MappedType);
776 case SchemaTypes.Array:
777 ExportArraySchema (einfo.MappedType, schemaNs);
779 case SchemaTypes.Class:
780 ExportClassSchema (einfo.MappedType);
785 return new XmlQualifiedName (lmap.GetSchemaArrayName (), schemaNs);
789 if (IsMapExported (map)) return new XmlQualifiedName (map.XmlType, map.XmlTypeNamespace);
791 SetMapExported (map);
792 XmlSchema schema = GetSchema (map.XmlTypeNamespace);
793 XmlSchemaComplexType stype = new XmlSchemaComplexType ();
794 stype.Name = map.ElementName;
795 schema.Items.Add (stype);
797 XmlSchemaParticle spart = GetSchemaArrayElement (schema, lmap.ItemInfo);
798 if (spart is XmlSchemaChoice)
799 stype.Particle = spart;
802 XmlSchemaSequence seq = new XmlSchemaSequence ();
803 seq.Items.Add (spart);
804 stype.Particle = seq;
807 return new XmlQualifiedName (map.XmlType, map.XmlTypeNamespace);
815 if (xmlDoc == null) xmlDoc = new XmlDocument ();
820 bool IsMapExported (XmlTypeMapping map)
822 if (exportedMaps.ContainsKey (GetMapKey(map))) return true;
826 void SetMapExported (XmlTypeMapping map)
828 exportedMaps [GetMapKey(map)] = map;
831 bool IsElementExported (XmlTypeMapping map)
833 if (exportedElements.ContainsKey (GetMapKey(map))) return true;
834 if (map.TypeData.Type == typeof(object)) return true;
838 void SetElementExported (XmlTypeMapping map)
840 exportedElements [GetMapKey(map)] = map;
843 string GetMapKey (XmlTypeMapping map)
845 // Don't use type name for array types, since we can have different
846 // classes that represent the same array type (for example
847 // StringCollection and string[]).
849 if (map.TypeData.IsListType)
850 return GetArrayKeyName (map.TypeData) + " " + map.XmlType + " " + map.XmlTypeNamespace;
852 return map.TypeData.FullTypeName + " " + map.XmlType + " " + map.XmlTypeNamespace;
855 string GetArrayKeyName (TypeData td)
857 TypeData etd = td.ListItemTypeData;
858 return "*arrayof*" + (etd.IsListType ? GetArrayKeyName (etd) : etd.FullTypeName);
861 void CompileSchemas ()
863 // foreach (XmlSchema sc in schemas)
864 // sc.Compile (null);
867 XmlSchema GetSchema (string ns)
869 XmlSchema schema = schemas [ns];
872 schema = new XmlSchema ();
873 if (ns != null && ns.Length > 0)
874 schema.TargetNamespace = ns;
876 schema.ElementFormDefault = XmlSchemaForm.Qualified;
877 schemas.Add (schema);
882 #endregion // Methods
884 private class XmlSchemaObjectContainer
886 private readonly XmlSchemaObject _xmlSchemaObject;
888 public XmlSchemaObjectContainer (XmlSchema schema)
890 _xmlSchemaObject = schema;
893 public XmlSchemaObjectContainer (XmlSchemaGroupBase group)
895 _xmlSchemaObject = group;
898 public XmlSchemaObjectCollection Items {
900 if (_xmlSchemaObject is XmlSchema) {
901 return ((XmlSchema) _xmlSchemaObject).Items;
903 return ((XmlSchemaGroupBase) _xmlSchemaObject).Items;