2010-04-06 Jb Evain <jbevain@novell.com>
[mcs.git] / class / System.XML / System.Xml.Serialization / XmlSchemaExporter.cs
blob6fe67c8fa831813e9090031afabdc12dff0be0e3
1 //
2 // System.Xml.Serialization.XmlSchemaExporter
3 //
4 // Author:
5 // Tim Coleman (tim@timcoleman.com)
6 // Lluis Sanchez Gual (lluis@ximian.com)
7 //
8 // Copyright (C) Tim Coleman, 2002
9 //
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:
19 //
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 //
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.
32 using System.Xml;
33 using System.Xml.Schema;
34 using System.Collections;
36 namespace System.Xml.Serialization {
37 public class XmlSchemaExporter {
39 #region Fields
41 XmlSchemas schemas;
42 Hashtable exportedMaps = new Hashtable();
43 Hashtable exportedElements = new Hashtable();
44 bool encodedFormat = false;
45 XmlDocument xmlDoc;
47 #endregion
49 #region Constructors
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
64 #region Methods
66 [MonoTODO]
67 public string ExportAnyType (string ns)
69 throw new NotImplementedException ();
72 #if NET_2_0
73 [MonoNotSupported("")]
74 public string ExportAnyType (XmlMembersMapping members)
76 throw new NotImplementedException ();
78 #endif
80 public void ExportMembersMapping (XmlMembersMapping xmlMembersMapping)
82 ExportMembersMapping (xmlMembersMapping, true);
85 #if NET_2_0
86 public
87 #else
88 internal
89 #endif
90 void ExportMembersMapping (XmlMembersMapping xmlMembersMapping, bool exportEnclosingType)
92 ClassMap cmap = (ClassMap) xmlMembersMapping.ObjectMap;
94 if (xmlMembersMapping.HasWrapperElement && exportEnclosingType)
96 XmlSchema schema = GetSchema (xmlMembersMapping.Namespace);
97 XmlSchemaComplexType stype = new XmlSchemaComplexType ();
99 XmlSchemaSequence particle;
100 XmlSchemaAnyAttribute anyAttribute;
101 ExportMembersMapSchema (schema, cmap, null, stype.Attributes, out particle, out anyAttribute);
102 stype.Particle = particle;
103 stype.AnyAttribute = anyAttribute;
105 if (encodedFormat)
107 stype.Name = xmlMembersMapping.ElementName;
108 schema.Items.Add (stype);
110 else
112 XmlSchemaElement selem = new XmlSchemaElement ();
113 selem.Name = xmlMembersMapping.ElementName;
114 selem.SchemaType = stype;
115 schema.Items.Add (selem);
118 else
120 ICollection members = cmap.ElementMembers;
121 if (members != null)
123 foreach (XmlTypeMapMemberElement member in members)
125 if (member is XmlTypeMapMemberAnyElement && member.TypeData.IsListType)
127 XmlSchema mschema = GetSchema (xmlMembersMapping.Namespace);
128 XmlSchemaParticle par = GetSchemaArrayElement (mschema, member.ElementInfo);
129 if (par is XmlSchemaAny)
131 XmlSchemaComplexType ct = FindComplexType (mschema.Items, "any");
132 if (ct != null) continue;
134 ct = new XmlSchemaComplexType ();
135 ct.Name = "any";
136 ct.IsMixed = true;
137 XmlSchemaSequence seq = new XmlSchemaSequence ();
138 ct.Particle = seq;
139 seq.Items.Add (par);
140 mschema.Items.Add (ct);
141 continue;
146 XmlTypeMapElementInfo einfo = (XmlTypeMapElementInfo) member.ElementInfo [0];
147 XmlSchema schema;
149 if (encodedFormat)
151 schema = GetSchema (xmlMembersMapping.Namespace);
152 ImportNamespace (schema, XmlSerializer.EncodingNamespace);
154 else
155 schema = GetSchema (einfo.Namespace);
158 XmlSchemaElement exe = FindElement (schema.Items, einfo.ElementName);
159 XmlSchemaElement elem;
161 XmlSchemaObjectContainer container = null;
162 // In encoded format, the schema elements are not needed
163 if (!encodedFormat)
164 container = new XmlSchemaObjectContainer (schema);
166 Type memType = member.GetType();
167 if (member is XmlTypeMapMemberFlatList)
168 throw new InvalidOperationException ("Unwrapped arrays not supported as parameters");
169 else if (memType == typeof(XmlTypeMapMemberElement))
170 elem = (XmlSchemaElement) GetSchemaElement (schema,
171 einfo, member.DefaultValue, false, container);
172 else
173 elem = (XmlSchemaElement) GetSchemaElement (schema,
174 einfo, false, container);
176 if (exe != null)
178 if (exe.SchemaTypeName.Equals (elem.SchemaTypeName))
179 schema.Items.Remove (elem);
180 else
182 string s = "The XML element named '" + einfo.ElementName + "' ";
183 s += "from namespace '" + schema.TargetNamespace + "' references distinct types " + elem.SchemaTypeName.Name + " and " + exe.SchemaTypeName.Name + ". ";
184 s += "Use XML attributes to specify another XML name or namespace for the element or types.";
185 throw new InvalidOperationException (s);
192 CompileSchemas ();
195 [MonoTODO]
196 public XmlQualifiedName ExportTypeMapping (XmlMembersMapping xmlMembersMapping)
198 throw new NotImplementedException ();
201 public void ExportTypeMapping (XmlTypeMapping xmlTypeMapping)
203 if (!xmlTypeMapping.IncludeInSchema) return;
204 if (IsElementExported (xmlTypeMapping)) return;
206 if (encodedFormat)
208 ExportClassSchema (xmlTypeMapping);
209 XmlSchema schema = GetSchema (xmlTypeMapping.XmlTypeNamespace);
210 ImportNamespace (schema, XmlSerializer.EncodingNamespace);
212 else
214 XmlSchema schema = GetSchema (xmlTypeMapping.Namespace);
215 XmlTypeMapElementInfo einfo = new XmlTypeMapElementInfo (null, xmlTypeMapping.TypeData);
216 einfo.Namespace = xmlTypeMapping.Namespace;
217 einfo.ElementName = xmlTypeMapping.ElementName;
218 if (xmlTypeMapping.TypeData.IsComplexType)
219 einfo.MappedType = xmlTypeMapping;
220 einfo.IsNullable = xmlTypeMapping.IsNullable;
221 GetSchemaElement (schema, einfo, false, new XmlSchemaObjectContainer (schema));
222 SetElementExported (xmlTypeMapping);
225 CompileSchemas ();
228 void ExportXmlSerializableSchema (XmlSchema currentSchema, XmlSerializableMapping map)
230 if (IsMapExported (map)) return;
231 SetMapExported (map);
233 if (map.Schema == null) return;
235 string targetNs = map.Schema.TargetNamespace;
236 XmlSchema existingSchema = schemas [targetNs];
237 if (existingSchema == null)
239 schemas.Add (map.Schema);
240 ImportNamespace (currentSchema, targetNs);
242 else if (existingSchema != map.Schema && !CanBeDuplicated (existingSchema, map.Schema))
244 throw new InvalidOperationException("The namespace '" + targetNs +"' defined by the class '" + map.TypeFullName + "' is a duplicate.");
248 private static bool CanBeDuplicated (XmlSchema existingSchema, XmlSchema schema)
250 if(XmlSchemas.IsDataSet (existingSchema) && XmlSchemas.IsDataSet (schema)
251 && existingSchema.Id == schema.Id)
252 return true;
253 return false;
256 void ExportClassSchema (XmlTypeMapping map)
258 if (IsMapExported (map)) return;
259 SetMapExported (map);
261 if (map.TypeData.Type == typeof(object))
263 foreach (XmlTypeMapping dmap in map.DerivedTypes)
264 if (dmap.TypeData.SchemaType == SchemaTypes.Class) ExportClassSchema (dmap);
265 return;
268 XmlSchema schema = GetSchema (map.XmlTypeNamespace);
269 XmlSchemaComplexType stype = new XmlSchemaComplexType ();
270 stype.Name = map.XmlType;
271 schema.Items.Add (stype);
273 ClassMap cmap = (ClassMap)map.ObjectMap;
275 if (cmap.HasSimpleContent)
277 XmlSchemaSimpleContent simple = new XmlSchemaSimpleContent ();
278 stype.ContentModel = simple;
279 XmlSchemaSimpleContentExtension ext = new XmlSchemaSimpleContentExtension ();
280 simple.Content = ext;
281 XmlSchemaSequence particle;
282 XmlSchemaAnyAttribute anyAttribute;
283 ExportMembersMapSchema (schema, cmap, map.BaseMap, ext.Attributes, out particle, out anyAttribute);
284 ext.AnyAttribute = anyAttribute;
285 if (map.BaseMap == null)
286 ext.BaseTypeName = cmap.SimpleContentBaseType;
287 else {
288 ext.BaseTypeName = new XmlQualifiedName (map.BaseMap.XmlType, map.BaseMap.XmlTypeNamespace);
289 ImportNamespace (schema, map.BaseMap.XmlTypeNamespace);
290 ExportClassSchema (map.BaseMap);
293 else if (map.BaseMap != null && map.BaseMap.IncludeInSchema)
295 XmlSchemaComplexContent cstype = new XmlSchemaComplexContent ();
296 XmlSchemaComplexContentExtension ext = new XmlSchemaComplexContentExtension ();
297 ext.BaseTypeName = new XmlQualifiedName (map.BaseMap.XmlType, map.BaseMap.XmlTypeNamespace);
298 cstype.Content = ext;
299 stype.ContentModel = cstype;
301 XmlSchemaSequence particle;
302 XmlSchemaAnyAttribute anyAttribute;
303 ExportMembersMapSchema (schema, cmap, map.BaseMap, ext.Attributes, out particle, out anyAttribute);
304 ext.Particle = particle;
305 ext.AnyAttribute = anyAttribute;
306 stype.IsMixed = HasMixedContent (map);
307 cstype.IsMixed = BaseHasMixedContent (map);
309 ImportNamespace (schema, map.BaseMap.XmlTypeNamespace);
310 ExportClassSchema (map.BaseMap);
312 else
314 XmlSchemaSequence particle;
315 XmlSchemaAnyAttribute anyAttribute;
316 ExportMembersMapSchema (schema, cmap, map.BaseMap, stype.Attributes, out particle, out anyAttribute);
317 stype.Particle = particle;
318 stype.AnyAttribute = anyAttribute;
319 stype.IsMixed = cmap.XmlTextCollector != null;
322 foreach (XmlTypeMapping dmap in map.DerivedTypes)
323 if (dmap.TypeData.SchemaType == SchemaTypes.Class) ExportClassSchema (dmap);
326 bool BaseHasMixedContent (XmlTypeMapping map)
328 ClassMap cmap = (ClassMap)map.ObjectMap;
329 return (cmap.XmlTextCollector != null && (map.BaseMap != null && DefinedInBaseMap (map.BaseMap, cmap.XmlTextCollector)));
332 bool HasMixedContent (XmlTypeMapping map)
334 ClassMap cmap = (ClassMap)map.ObjectMap;
335 return (cmap.XmlTextCollector != null && (map.BaseMap == null || !DefinedInBaseMap (map.BaseMap, cmap.XmlTextCollector)));
338 void ExportMembersMapSchema (XmlSchema schema, ClassMap map, XmlTypeMapping baseMap, XmlSchemaObjectCollection outAttributes, out XmlSchemaSequence particle, out XmlSchemaAnyAttribute anyAttribute)
340 particle = null;
341 XmlSchemaSequence seq = new XmlSchemaSequence ();
343 ICollection members = map.ElementMembers;
344 if (members != null && !map.HasSimpleContent)
346 foreach (XmlTypeMapMemberElement member in members)
348 if (baseMap != null && DefinedInBaseMap (baseMap, member)) continue;
350 Type memType = member.GetType();
351 if (memType == typeof(XmlTypeMapMemberFlatList))
353 XmlSchemaParticle part = GetSchemaArrayElement (schema, member.ElementInfo);
354 if (part != null) seq.Items.Add (part);
356 else if (memType == typeof(XmlTypeMapMemberAnyElement))
358 seq.Items.Add (GetSchemaArrayElement (schema, member.ElementInfo));
360 else if (memType == typeof(XmlTypeMapMemberElement))
362 GetSchemaElement (schema, (XmlTypeMapElementInfo) member.ElementInfo [0],
363 member.DefaultValue, true, new XmlSchemaObjectContainer (seq));
365 else
367 GetSchemaElement (schema, (XmlTypeMapElementInfo) member.ElementInfo[0],
368 true, new XmlSchemaObjectContainer (seq));
373 if (seq.Items.Count > 0)
374 particle = seq;
376 // Write attributes
378 ICollection attributes = map.AttributeMembers;
379 if (attributes != null)
381 foreach (XmlTypeMapMemberAttribute attr in attributes) {
382 if (baseMap != null && DefinedInBaseMap (baseMap, attr)) continue;
383 outAttributes.Add (GetSchemaAttribute (schema, attr, true));
387 XmlTypeMapMember anyAttrMember = map.DefaultAnyAttributeMember;
388 if (anyAttrMember != null)
389 anyAttribute = new XmlSchemaAnyAttribute ();
390 else
391 anyAttribute = null;
394 XmlSchemaElement FindElement (XmlSchemaObjectCollection col, string name)
396 foreach (XmlSchemaObject ob in col)
398 XmlSchemaElement elem = ob as XmlSchemaElement;
399 if (elem != null && elem.Name == name) return elem;
401 return null;
404 XmlSchemaComplexType FindComplexType (XmlSchemaObjectCollection col, string name)
406 foreach (XmlSchemaObject ob in col)
408 XmlSchemaComplexType ctype = ob as XmlSchemaComplexType;
409 if (ctype != null && ctype.Name == name) return ctype;
411 return null;
414 XmlSchemaAttribute GetSchemaAttribute (XmlSchema currentSchema, XmlTypeMapMemberAttribute attinfo, bool isTypeMember)
416 XmlSchemaAttribute sat = new XmlSchemaAttribute ();
417 if (attinfo.DefaultValue != System.DBNull.Value) {
418 sat.DefaultValue = ExportDefaultValue (attinfo.TypeData,
419 attinfo.MappedType, attinfo.DefaultValue);
420 } else {
421 if (!attinfo.IsOptionalValueType && attinfo.TypeData.IsValueType)
422 sat.Use = XmlSchemaUse.Required;
425 ImportNamespace (currentSchema, attinfo.Namespace);
427 XmlSchema memberSchema;
428 if (attinfo.Namespace.Length == 0 && attinfo.Form != XmlSchemaForm.Qualified)
429 memberSchema = currentSchema;
430 else
431 memberSchema = GetSchema (attinfo.Namespace);
433 if (currentSchema == memberSchema || encodedFormat)
435 sat.Name = attinfo.AttributeName;
436 if (isTypeMember) sat.Form = attinfo.Form;
437 if (attinfo.TypeData.SchemaType == SchemaTypes.Enum)
439 ImportNamespace (currentSchema, attinfo.DataTypeNamespace);
440 ExportEnumSchema (attinfo.MappedType);
441 sat.SchemaTypeName = new XmlQualifiedName (attinfo.TypeData.XmlType, attinfo.DataTypeNamespace);
443 else if (attinfo.TypeData.SchemaType == SchemaTypes.Array && TypeTranslator.IsPrimitive (attinfo.TypeData.ListItemType))
445 sat.SchemaType = GetSchemaSimpleListType (attinfo.TypeData);
447 else
448 sat.SchemaTypeName = new XmlQualifiedName (attinfo.TypeData.XmlType, attinfo.DataTypeNamespace);;
450 else
452 sat.RefName = new XmlQualifiedName (attinfo.AttributeName, attinfo.Namespace);
453 foreach (XmlSchemaObject ob in memberSchema.Items)
454 if (ob is XmlSchemaAttribute && ((XmlSchemaAttribute)ob).Name == attinfo.AttributeName)
455 return sat;
457 memberSchema.Items.Add (GetSchemaAttribute (memberSchema, attinfo, false));
459 return sat;
462 XmlSchemaParticle GetSchemaElement (XmlSchema currentSchema, XmlTypeMapElementInfo einfo, bool isTypeMember)
464 return GetSchemaElement (currentSchema, einfo, System.DBNull.Value,
465 isTypeMember, (XmlSchemaObjectContainer) null);
468 XmlSchemaParticle GetSchemaElement (XmlSchema currentSchema, XmlTypeMapElementInfo einfo, bool isTypeMember, XmlSchemaObjectContainer container)
470 return GetSchemaElement (currentSchema, einfo, System.DBNull.Value, isTypeMember, container);
473 XmlSchemaParticle GetSchemaElement (XmlSchema currentSchema, XmlTypeMapElementInfo einfo, object defaultValue, bool isTypeMember, XmlSchemaObjectContainer container)
475 if (einfo.IsTextElement) return null;
477 if (einfo.IsUnnamedAnyElement)
479 XmlSchemaAny any = new XmlSchemaAny ();
480 any.MinOccurs = 0;
481 any.MaxOccurs = 1;
482 if (container != null)
483 container.Items.Add (any);
484 return any;
487 XmlSchemaElement selem = new XmlSchemaElement ();
488 selem.IsNillable = einfo.IsNullable;
489 if (container != null)
490 container.Items.Add (selem);
492 if (isTypeMember)
494 selem.MaxOccurs = 1;
495 selem.MinOccurs = einfo.IsNullable ? 1 : 0;
497 if ((defaultValue == DBNull.Value && einfo.TypeData.IsValueType && einfo.Member != null && !einfo.Member.IsOptionalValueType) || encodedFormat)
498 selem.MinOccurs = 1;
501 XmlSchema memberSchema = null;
503 if (!encodedFormat)
505 memberSchema = GetSchema (einfo.Namespace);
506 ImportNamespace (currentSchema, einfo.Namespace);
509 if (currentSchema == memberSchema || encodedFormat || !isTypeMember)
511 if (isTypeMember) selem.IsNillable = einfo.IsNullable;
512 selem.Name = einfo.ElementName;
514 if (defaultValue != System.DBNull.Value)
515 selem.DefaultValue = ExportDefaultValue (einfo.TypeData,
516 einfo.MappedType, defaultValue);
518 if (einfo.Form != XmlSchemaForm.Qualified)
519 selem.Form = einfo.Form;
521 switch (einfo.TypeData.SchemaType)
523 case SchemaTypes.XmlNode:
524 selem.SchemaType = GetSchemaXmlNodeType ();
525 break;
527 case SchemaTypes.XmlSerializable:
528 SetSchemaXmlSerializableType (einfo.MappedType as XmlSerializableMapping, selem);
529 ExportXmlSerializableSchema (currentSchema, einfo.MappedType as XmlSerializableMapping);
530 break;
532 case SchemaTypes.Enum:
533 selem.SchemaTypeName = new XmlQualifiedName (einfo.MappedType.XmlType, einfo.MappedType.XmlTypeNamespace);
534 ImportNamespace (currentSchema, einfo.MappedType.XmlTypeNamespace);
535 ExportEnumSchema (einfo.MappedType);
536 break;
538 case SchemaTypes.Array:
539 XmlQualifiedName atypeName = ExportArraySchema (einfo.MappedType, currentSchema.TargetNamespace);
540 selem.SchemaTypeName = atypeName;
541 ImportNamespace (currentSchema, atypeName.Namespace);
542 break;
544 case SchemaTypes.Class:
545 if (einfo.MappedType.TypeData.Type != typeof(object)) {
546 selem.SchemaTypeName = new XmlQualifiedName (einfo.MappedType.XmlType, einfo.MappedType.XmlTypeNamespace);
547 ImportNamespace (currentSchema, einfo.MappedType.XmlTypeNamespace);
549 else if (encodedFormat)
550 selem.SchemaTypeName = new XmlQualifiedName (einfo.MappedType.XmlType, einfo.MappedType.XmlTypeNamespace);
552 ExportClassSchema (einfo.MappedType);
553 break;
555 case SchemaTypes.Primitive:
556 selem.SchemaTypeName = new XmlQualifiedName (einfo.TypeData.XmlType, einfo.DataTypeNamespace);
557 if (!einfo.TypeData.IsXsdType) {
558 ImportNamespace (currentSchema, einfo.MappedType.XmlTypeNamespace);
559 ExportDerivedSchema (einfo.MappedType);
561 break;
564 else
566 selem.RefName = new XmlQualifiedName (einfo.ElementName, einfo.Namespace);
567 foreach (XmlSchemaObject ob in memberSchema.Items)
568 if (ob is XmlSchemaElement && ((XmlSchemaElement)ob).Name == einfo.ElementName)
569 return selem;
571 GetSchemaElement (memberSchema, einfo, defaultValue, false,
572 new XmlSchemaObjectContainer (memberSchema));
574 return selem;
577 void ImportNamespace (XmlSchema schema, string ns)
579 if (ns == null || ns.Length == 0 ||
580 ns == schema.TargetNamespace || ns == XmlSchema.Namespace) return;
582 foreach (XmlSchemaObject sob in schema.Includes)
583 if ((sob is XmlSchemaImport) && ((XmlSchemaImport)sob).Namespace == ns) return;
585 XmlSchemaImport imp = new XmlSchemaImport ();
586 imp.Namespace = ns;
587 schema.Includes.Add (imp);
590 bool DefinedInBaseMap (XmlTypeMapping map, XmlTypeMapMember member)
592 if (((ClassMap)map.ObjectMap).FindMember (member.Name) != null)
593 return true;
594 else if (map.BaseMap != null)
595 return DefinedInBaseMap (map.BaseMap, member);
596 else
597 return false;
600 XmlSchemaType GetSchemaXmlNodeType ()
602 XmlSchemaComplexType stype = new XmlSchemaComplexType ();
603 stype.IsMixed = true;
604 XmlSchemaSequence seq = new XmlSchemaSequence ();
605 seq.Items.Add (new XmlSchemaAny ());
606 stype.Particle = seq;
607 return stype;
610 void SetSchemaXmlSerializableType (XmlSerializableMapping map, XmlSchemaElement elem)
612 #if NET_2_0
613 if (map.SchemaType != null && map.Schema != null) {
614 elem.SchemaType = map.SchemaType;
615 return;
618 if (map.SchemaType == null && map.SchemaTypeName != null) {
619 elem.SchemaTypeName = map.SchemaTypeName;
620 elem.Name = map.SchemaTypeName.Name;
621 return;
623 #endif
624 XmlSchemaComplexType stype = new XmlSchemaComplexType ();
625 XmlSchemaSequence seq = new XmlSchemaSequence ();
626 if (map.Schema == null) {
627 XmlSchemaElement selem = new XmlSchemaElement ();
628 selem.RefName = new XmlQualifiedName ("schema",XmlSchema.Namespace);
629 seq.Items.Add (selem);
630 seq.Items.Add (new XmlSchemaAny ());
631 } else {
632 XmlSchemaAny any = new XmlSchemaAny ();
633 any.Namespace = map.Schema.TargetNamespace;
634 seq.Items.Add (any);
636 stype.Particle = seq;
637 elem.SchemaType = stype;
640 XmlSchemaSimpleType GetSchemaSimpleListType (TypeData typeData)
642 XmlSchemaSimpleType stype = new XmlSchemaSimpleType ();
643 XmlSchemaSimpleTypeList list = new XmlSchemaSimpleTypeList ();
644 TypeData itemTypeData = TypeTranslator.GetTypeData (typeData.ListItemType);
645 list.ItemTypeName = new XmlQualifiedName (itemTypeData.XmlType, XmlSchema.Namespace);
646 stype.Content = list;
647 return stype;
650 XmlSchemaParticle GetSchemaArrayElement (XmlSchema currentSchema, XmlTypeMapElementInfoList infos)
652 int numInfos = infos.Count;
653 if (numInfos > 0 && ((XmlTypeMapElementInfo)infos[0]).IsTextElement) numInfos--;
654 if (numInfos == 0) return null;
656 if (numInfos == 1)
658 XmlSchemaParticle selem = GetSchemaElement (currentSchema, (XmlTypeMapElementInfo) infos[infos.Count-1], true);
659 selem.MinOccursString = "0";
660 selem.MaxOccursString = "unbounded";
661 return selem;
663 else
665 XmlSchemaChoice schoice = new XmlSchemaChoice ();
666 schoice.MinOccursString = "0";
667 schoice.MaxOccursString = "unbounded";
668 foreach (XmlTypeMapElementInfo einfo in infos)
670 if (einfo.IsTextElement) continue;
671 schoice.Items.Add (GetSchemaElement (currentSchema, einfo, true));
673 return schoice;
677 string ExportDefaultValue (TypeData typeData, XmlTypeMapping map, object defaultValue)
679 if (typeData.SchemaType == SchemaTypes.Enum) {
680 EnumMap enumMap = (EnumMap) map.ObjectMap;
681 // get corresponding xml name
682 return enumMap.GetXmlName (map.TypeFullName, defaultValue);
684 return XmlCustomFormatter.ToXmlString (typeData, defaultValue);
687 void ExportDerivedSchema(XmlTypeMapping map) {
688 if (IsMapExported (map)) return;
689 SetMapExported (map);
691 XmlSchema schema = GetSchema (map.XmlTypeNamespace);
692 for (int i = 0; i < schema.Items.Count; i++) {
693 XmlSchemaSimpleType item = schema.Items [i] as XmlSchemaSimpleType;
694 if (item != null && item.Name == map.ElementName)
695 return;
697 XmlSchemaSimpleType stype = new XmlSchemaSimpleType ();
698 stype.Name = map.ElementName;
699 schema.Items.Add (stype);
701 XmlSchemaSimpleTypeRestriction rest = new XmlSchemaSimpleTypeRestriction ();
702 rest.BaseTypeName = new XmlQualifiedName (map.TypeData.MappedType.XmlType, XmlSchema.Namespace);
703 XmlSchemaPatternFacet facet = map.TypeData.XmlSchemaPatternFacet;
704 if (facet != null)
705 rest.Facets.Add(facet);
706 stype.Content = rest;
709 void ExportEnumSchema (XmlTypeMapping map)
711 if (IsMapExported (map)) return;
712 SetMapExported (map);
714 XmlSchema schema = GetSchema (map.XmlTypeNamespace);
715 XmlSchemaSimpleType stype = new XmlSchemaSimpleType ();
716 stype.Name = map.ElementName;
717 schema.Items.Add (stype);
719 XmlSchemaSimpleTypeRestriction rest = new XmlSchemaSimpleTypeRestriction ();
720 rest.BaseTypeName = new XmlQualifiedName ("string",XmlSchema.Namespace);
721 EnumMap emap = (EnumMap) map.ObjectMap;
723 foreach (EnumMap.EnumMapMember emem in emap.Members)
725 XmlSchemaEnumerationFacet ef = new XmlSchemaEnumerationFacet ();
726 ef.Value = emem.XmlName;
727 rest.Facets.Add (ef);
730 if (emap.IsFlags) {
731 XmlSchemaSimpleTypeList slist = new XmlSchemaSimpleTypeList ();
732 XmlSchemaSimpleType restrictionType = new XmlSchemaSimpleType ();
733 restrictionType.Content = rest;
734 slist.ItemType = restrictionType;
735 stype.Content = slist;
736 } else {
737 stype.Content = rest;
741 XmlQualifiedName ExportArraySchema (XmlTypeMapping map, string defaultNamespace)
743 ListMap lmap = (ListMap) map.ObjectMap;
745 if (encodedFormat)
747 string name, ns, schemaNs;
748 lmap.GetArrayType (-1, out name, out ns);
749 if (ns == XmlSchema.Namespace) schemaNs = defaultNamespace;
750 else schemaNs = ns;
752 if (IsMapExported (map)) return new XmlQualifiedName (lmap.GetSchemaArrayName (), schemaNs);
753 SetMapExported (map);
755 XmlSchema schema = GetSchema (schemaNs);
756 XmlSchemaComplexType stype = new XmlSchemaComplexType ();
757 stype.Name = lmap.GetSchemaArrayName ();
758 schema.Items.Add (stype);
760 XmlSchemaComplexContent content = new XmlSchemaComplexContent();
761 content.IsMixed = false;
762 stype.ContentModel = content;
764 XmlSchemaComplexContentRestriction rest = new XmlSchemaComplexContentRestriction ();
765 content.Content = rest;
766 rest.BaseTypeName = new XmlQualifiedName ("Array", XmlSerializer.EncodingNamespace);
767 XmlSchemaAttribute at = new XmlSchemaAttribute ();
768 rest.Attributes.Add (at);
769 at.RefName = new XmlQualifiedName ("arrayType", XmlSerializer.EncodingNamespace);
771 XmlAttribute arrayType = Document.CreateAttribute ("arrayType", XmlSerializer.WsdlNamespace);
772 arrayType.Value = ns + (ns != "" ? ":" : "") + name;
773 at.UnhandledAttributes = new XmlAttribute [] { arrayType };
774 ImportNamespace (schema, XmlSerializer.WsdlNamespace);
776 XmlTypeMapElementInfo einfo = (XmlTypeMapElementInfo) lmap.ItemInfo[0];
777 if (einfo.MappedType != null)
779 switch (einfo.TypeData.SchemaType)
781 case SchemaTypes.Enum:
782 ExportEnumSchema (einfo.MappedType);
783 break;
784 case SchemaTypes.Array:
785 ExportArraySchema (einfo.MappedType, schemaNs);
786 break;
787 case SchemaTypes.Class:
788 ExportClassSchema (einfo.MappedType);
789 break;
793 return new XmlQualifiedName (lmap.GetSchemaArrayName (), schemaNs);
795 else
797 if (IsMapExported (map)) return new XmlQualifiedName (map.XmlType, map.XmlTypeNamespace);
799 SetMapExported (map);
800 XmlSchema schema = GetSchema (map.XmlTypeNamespace);
801 XmlSchemaComplexType stype = new XmlSchemaComplexType ();
802 stype.Name = map.ElementName;
803 schema.Items.Add (stype);
805 XmlSchemaParticle spart = GetSchemaArrayElement (schema, lmap.ItemInfo);
806 if (spart is XmlSchemaChoice)
807 stype.Particle = spart;
808 else
810 XmlSchemaSequence seq = new XmlSchemaSequence ();
811 seq.Items.Add (spart);
812 stype.Particle = seq;
815 return new XmlQualifiedName (map.XmlType, map.XmlTypeNamespace);
819 XmlDocument Document
823 if (xmlDoc == null) xmlDoc = new XmlDocument ();
824 return xmlDoc;
828 bool IsMapExported (XmlTypeMapping map)
830 if (exportedMaps.ContainsKey (GetMapKey(map))) return true;
831 return false;
834 void SetMapExported (XmlTypeMapping map)
836 exportedMaps [GetMapKey(map)] = map;
839 bool IsElementExported (XmlTypeMapping map)
841 if (exportedElements.ContainsKey (GetMapKey(map))) return true;
842 if (map.TypeData.Type == typeof(object)) return true;
843 return false;
846 void SetElementExported (XmlTypeMapping map)
848 exportedElements [GetMapKey(map)] = map;
851 string GetMapKey (XmlTypeMapping map)
853 // Don't use type name for array types, since we can have different
854 // classes that represent the same array type (for example
855 // StringCollection and string[]).
857 if (map.TypeData.IsListType)
858 return GetArrayKeyName (map.TypeData) + " " + map.XmlType + " " + map.XmlTypeNamespace;
859 else
860 return map.TypeData.FullTypeName + " " + map.XmlType + " " + map.XmlTypeNamespace;
863 string GetArrayKeyName (TypeData td)
865 TypeData etd = td.ListItemTypeData;
866 return "*arrayof*" + (etd.IsListType ? GetArrayKeyName (etd) : etd.FullTypeName);
869 void CompileSchemas ()
871 // foreach (XmlSchema sc in schemas)
872 // sc.Compile (null);
875 XmlSchema GetSchema (string ns)
877 XmlSchema schema = schemas [ns];
878 if (schema == null)
880 schema = new XmlSchema ();
881 if (ns != null && ns.Length > 0)
882 schema.TargetNamespace = ns;
883 if (!encodedFormat)
884 schema.ElementFormDefault = XmlSchemaForm.Qualified;
885 schemas.Add (schema);
887 return schema;
890 #endregion // Methods
892 private class XmlSchemaObjectContainer
894 private readonly XmlSchemaObject _xmlSchemaObject;
896 public XmlSchemaObjectContainer (XmlSchema schema)
898 _xmlSchemaObject = schema;
901 public XmlSchemaObjectContainer (XmlSchemaGroupBase group)
903 _xmlSchemaObject = group;
906 public XmlSchemaObjectCollection Items {
907 get {
908 if (_xmlSchemaObject is XmlSchema) {
909 return ((XmlSchema) _xmlSchemaObject).Items;
910 } else {
911 return ((XmlSchemaGroupBase) _xmlSchemaObject).Items;