The Labs \ Source Viewer \ SSCLI \ System.Xml.Serialization \ XmlSchemaExporter

  1. //------------------------------------------------------------------------------
  2. // <copyright file="XmlSchemaExporter.cs" company="Microsoft">
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. // </copyright>
  14. // <owner current="true" primary="true">ElenaK</owner>
  15. //------------------------------------------------------------------------------
  16. namespace System.Xml.Serialization
  17. {
  18.    
  19.     using System;
  20.     using System.Collections;
  21.     using System.Xml.Schema;
  22.     using System.ComponentModel;
  23.     using System.Diagnostics;
  24.     using System.Globalization;
  25.    
  26.     /// <include file='doc\XmlSchemaExporter.uex' path='docs/doc[@for="XmlSchemaExporter"]/*' />
  27.     ///<internalonly/>
  28.     /// <devdoc>
  29.     /// <para>[To be supplied.]</para>
  30.     /// </devdoc>
  31.     public class XmlSchemaExporter
  32.     {
  33.         internal const XmlSchemaForm elementFormDefault = XmlSchemaForm.Qualified;
  34.         internal const XmlSchemaForm attributeFormDefault = XmlSchemaForm.Unqualified;
  35.        
  36.         XmlSchemas schemas;
  37.         Hashtable elements = new Hashtable();
  38.         // ElementAccessor -> XmlSchemaElement
  39.         Hashtable attributes = new Hashtable();
  40.         // AttributeAccessor -> XmlSchemaElement
  41.         Hashtable types = new Hashtable();
  42.         // StructMapping/EnumMapping -> XmlSchemaComplexType/XmlSchemaSimpleType
  43.         Hashtable references = new Hashtable();
  44.         // TypeMappings to keep track of circular references via anonymous types
  45.         bool needToExportRoot;
  46.         TypeScope scope;
  47.        
  48.         /// <include file='doc\XmlSchemaExporter.uex' path='docs/doc[@for="XmlSchemaExporter.XmlSchemaExporter"]/*' />
  49.         /// <devdoc>
  50.         /// <para>[To be supplied.]</para>
  51.         /// </devdoc>
  52.         public XmlSchemaExporter(XmlSchemas schemas)
  53.         {
  54.             this.schemas = schemas;
  55.         }
  56.        
  57.         /// <include file='doc\XmlSchemaExporter.uex' path='docs/doc[@for="XmlSchemaExporter.ExportTypeMapping"]/*' />
  58.         /// <devdoc>
  59.         /// <para>[To be supplied.]</para>
  60.         /// </devdoc>
  61.         public void ExportTypeMapping(XmlTypeMapping xmlTypeMapping)
  62.         {
  63.             xmlTypeMapping.CheckShallow();
  64.             CheckScope(xmlTypeMapping.Scope);
  65.             ExportElement(xmlTypeMapping.Accessor);
  66.             ExportRootIfNecessary(xmlTypeMapping.Scope);
  67.         }
  68.        
  69.         /// <include file='doc\XmlSchemaExporter.uex' path='docs/doc[@for="XmlSchemaExporter.ExportTypeMapping1"]/*' />
  70.         public XmlQualifiedName ExportTypeMapping(XmlMembersMapping xmlMembersMapping)
  71.         {
  72.             xmlMembersMapping.CheckShallow();
  73.             CheckScope(xmlMembersMapping.Scope);
  74.             MembersMapping mapping = (MembersMapping)xmlMembersMapping.Accessor.Mapping;
  75.             if (mapping.Members.Length == 1 && mapping.Members[0].Elements[0].Mapping is SpecialMapping) {
  76.                 SpecialMapping special = (SpecialMapping)mapping.Members[0].Elements[0].Mapping;
  77.                 XmlSchemaType type = ExportSpecialMapping(special, xmlMembersMapping.Accessor.Namespace, false, null);
  78.                 if (type != null && type.Name != null && type.Name.Length > 0) {
  79.                     type.Name = xmlMembersMapping.Accessor.Name;
  80.                     AddSchemaItem(type, xmlMembersMapping.Accessor.Namespace, null);
  81.                 }
  82.                 ExportRootIfNecessary(xmlMembersMapping.Scope);
  83.                 return (new XmlQualifiedName(xmlMembersMapping.Accessor.Name, xmlMembersMapping.Accessor.Namespace));
  84.             }
  85.             return null;
  86.         }
  87.        
  88.         /// <include file='doc\XmlSchemaExporter.uex' path='docs/doc[@for="XmlSchemaExporter.ExportMembersMapping"]/*' />
  89.         /// <devdoc>
  90.         /// <para>[To be supplied.]</para>
  91.         /// </devdoc>
  92.         public void ExportMembersMapping(XmlMembersMapping xmlMembersMapping)
  93.         {
  94.             ExportMembersMapping(xmlMembersMapping, true);
  95.         }
  96.        
  97.         /// <include file='doc\XmlSchemaExporter.uex' path='docs/doc[@for="XmlSchemaExporter.ExportMembersMapping1"]/*' />
  98.         /// <devdoc>
  99.         /// <para>[To be supplied.]</para>
  100.         /// </devdoc>
  101.         public void ExportMembersMapping(XmlMembersMapping xmlMembersMapping, bool exportEnclosingType)
  102.         {
  103.             xmlMembersMapping.CheckShallow();
  104.             MembersMapping mapping = (MembersMapping)xmlMembersMapping.Accessor.Mapping;
  105.             CheckScope(xmlMembersMapping.Scope);
  106.             if (mapping.HasWrapperElement && exportEnclosingType) {
  107.                 ExportElement(xmlMembersMapping.Accessor);
  108.             }
  109.             else {
  110.                 foreach (MemberMapping member in mapping.Members) {
  111.                     if (member.Attribute != null)
  112.                         throw new InvalidOperationException(Res.GetString(Res.XmlBareAttributeMember, member.Attribute.Name));
  113.                     else if (member.Text != null)
  114.                         throw new InvalidOperationException(Res.GetString(Res.XmlBareTextMember, member.Text.Name));
  115.                     else if (member.Elements == null || member.Elements.Length == 0)
  116.                         continue;
  117.                    
  118.                     if (member.TypeDesc.IsArrayLike && !(member.Elements[0].Mapping is ArrayMapping))
  119.                         throw new InvalidOperationException(Res.GetString(Res.XmlIllegalArrayElement, member.Elements[0].Name));
  120.                    
  121.                     if (exportEnclosingType) {
  122.                         ExportElement(member.Elements[0]);
  123.                     }
  124.                     else {
  125.                         ExportMapping(member.Elements[0].Mapping, member.Elements[0].Namespace, member.Elements[0].Any);
  126.                     }
  127.                 }
  128.             }
  129.             ExportRootIfNecessary(xmlMembersMapping.Scope);
  130.         }
  131.        
  132.         private static XmlSchemaType FindSchemaType(string name, XmlSchemaObjectCollection items)
  133.         {
  134.             // Have to loop through the items because schema.SchemaTypes has not been populated yet.
  135.             foreach (object o in items) {
  136.                 XmlSchemaType type = o as XmlSchemaType;
  137.                 if (type == null)
  138.                     continue;
  139.                 if (type.Name == name)
  140.                     return type;
  141.             }
  142.             return null;
  143.         }
  144.        
  145.         private static bool IsAnyType(XmlSchemaType schemaType, bool mixed, bool unbounded)
  146.         {
  147.             XmlSchemaComplexType complexType = schemaType as XmlSchemaComplexType;
  148.             if (complexType != null) {
  149.                 if (complexType.IsMixed != mixed)
  150.                     return false;
  151.                 if (complexType.Particle is XmlSchemaSequence) {
  152.                     XmlSchemaSequence sequence = (XmlSchemaSequence)complexType.Particle;
  153.                     if (sequence.Items.Count == 1 && sequence.Items[0] is XmlSchemaAny) {
  154.                         XmlSchemaAny any = (XmlSchemaAny)sequence.Items[0];
  155.                         return (unbounded == any.IsMultipleOccurrence);
  156.                     }
  157.                 }
  158.             }
  159.             return false;
  160.         }
  161.        
  162.         /// <include file='doc\XmlSchemaExporter.uex' path='docs/doc[@for="XmlSchemaExporter.ExportAnyType"]/*' />
  163.         public string ExportAnyType(string ns)
  164.         {
  165.             string name = "any";
  166.             int i = 0;
  167.             XmlSchema schema = schemas[ns];
  168.             if (schema != null) {
  169.                 while (true) {
  170.                     XmlSchemaType schemaType = FindSchemaType(name, schema.Items);
  171.                     if (schemaType == null)
  172.                         break;
  173.                     if (IsAnyType(schemaType, true, true))
  174.                         return name;
  175.                     i++;
  176.                     name = "any" + i.ToString(CultureInfo.InvariantCulture);
  177.                 }
  178.             }
  179.            
  180.             XmlSchemaComplexType type = new XmlSchemaComplexType();
  181.             type.Name = name;
  182.             type.IsMixed = true;
  183.             XmlSchemaSequence seq = new XmlSchemaSequence();
  184.             XmlSchemaAny any = new XmlSchemaAny();
  185.             any.MinOccurs = 0;
  186.             any.MaxOccurs = decimal.MaxValue;
  187.             seq.Items.Add(any);
  188.             type.Particle = seq;
  189.             AddSchemaItem(type, ns, null);
  190.             return name;
  191.         }
  192.        
  193.         /// <include file='doc\XmlSchemaExporter.uex' path='docs/doc[@for="XmlSchemaExporter.ExportAnyType1"]/*' />
  194.         public string ExportAnyType(XmlMembersMapping members)
  195.         {
  196.             if (members.Count == 1 && members[0].Any && members[0].ElementName.Length == 0) {
  197.                 XmlMemberMapping member = members[0];
  198.                 string ns = member.Namespace;
  199.                 bool isUnbounded = member.Mapping.TypeDesc.IsArrayLike;
  200.                 bool isMixed = isUnbounded && member.Mapping.TypeDesc.ArrayElementTypeDesc != null ? member.Mapping.TypeDesc.ArrayElementTypeDesc.IsMixed : member.Mapping.TypeDesc.IsMixed;
  201.                
  202.                 if (isMixed && member.Mapping.TypeDesc.IsMixed)
  203.                     // special case of the single top-level XmlNode --> map it to node array to match the "mixed" any type for backward compatibility
  204.                     isUnbounded = true;
  205.                
  206.                 // generate type name, make sure that it is backward compatible
  207.                 string baseName = isMixed ? "any" : isUnbounded ? "anyElements" : "anyElement";
  208.                 string name = baseName;
  209.                 int i = 0;
  210.                 XmlSchema schema = schemas[ns];
  211.                 if (schema != null) {
  212.                     while (true) {
  213.                         XmlSchemaType schemaType = FindSchemaType(name, schema.Items);
  214.                         if (schemaType == null)
  215.                             break;
  216.                         if (IsAnyType(schemaType, isMixed, isUnbounded))
  217.                             return name;
  218.                         i++;
  219.                         name = baseName + i.ToString(CultureInfo.InvariantCulture);
  220.                     }
  221.                 }
  222.                
  223.                 XmlSchemaComplexType type = new XmlSchemaComplexType();
  224.                 type.Name = name;
  225.                 type.IsMixed = isMixed;
  226.                 XmlSchemaSequence seq = new XmlSchemaSequence();
  227.                 XmlSchemaAny any = new XmlSchemaAny();
  228.                 any.MinOccurs = 0;
  229.                 if (isUnbounded)
  230.                     any.MaxOccurs = decimal.MaxValue;
  231.                 seq.Items.Add(any);
  232.                 type.Particle = seq;
  233.                 AddSchemaItem(type, ns, null);
  234.                 return name;
  235.             }
  236.             else {
  237.                 return null;
  238.             }
  239.         }
  240.        
  241.         void CheckScope(TypeScope scope)
  242.         {
  243.             if (this.scope == null) {
  244.                 this.scope = scope;
  245.             }
  246.             else if (this.scope != scope) {
  247.                 throw new InvalidOperationException(Res.GetString(Res.XmlMappingsScopeMismatch));
  248.             }
  249.         }
  250.        
  251.         XmlSchemaElement ExportElement(ElementAccessor accessor)
  252.         {
  253.             if (!accessor.Mapping.IncludeInSchema && !accessor.Mapping.TypeDesc.IsRoot) {
  254.                 return null;
  255.             }
  256.             if (accessor.Any && accessor.Name.Length == 0)
  257.                 throw new InvalidOperationException(Res.GetString(Res.XmlIllegalWildcard));
  258.             XmlSchemaElement element = (XmlSchemaElement)elements[accessor];
  259.             if (element != null)
  260.                 return element;
  261.             element = new XmlSchemaElement();
  262.             element.Name = accessor.Name;
  263.             element.IsNillable = accessor.IsNullable;
  264.             elements.Add(accessor, element);
  265.             element.Form = accessor.Form;
  266.             AddSchemaItem(element, accessor.Namespace, null);
  267.             ExportElementMapping(element, accessor.Mapping, accessor.Namespace, accessor.Any);
  268.             return element;
  269.         }
  270.        
  271.         void CheckForDuplicateType(TypeMapping mapping, string newNamespace)
  272.         {
  273.             if (mapping.IsAnonymousType)
  274.                 return;
  275.             string newTypeName = mapping.TypeName;
  276.             XmlSchema schema = schemas[newNamespace];
  277.             if (schema != null) {
  278.                 foreach (XmlSchemaObject o in schema.Items) {
  279.                     XmlSchemaType type = o as XmlSchemaType;
  280.                     if (type != null && type.Name == newTypeName)
  281.                         throw new InvalidOperationException(Res.GetString(Res.XmlDuplicateTypeName, newTypeName, newNamespace));
  282.                    
  283.                 }
  284.             }
  285.         }
  286.        
  287.         void AddSchemaItem(XmlSchemaObject item, string ns, string referencingNs)
  288.         {
  289.             XmlSchema schema = schemas[ns];
  290.             if (schema == null) {
  291.                 schema = new XmlSchema();
  292.                 schema.TargetNamespace = ns == null || ns.Length == 0 ? null : ns;
  293.                
  294.                 #pragma warning disable 429 // Unreachable code: the default values are constant, so will never be Unqualified
  295.                 schema.ElementFormDefault = elementFormDefault == XmlSchemaForm.Unqualified ? XmlSchemaForm.None : elementFormDefault;
  296.                 schema.AttributeFormDefault = attributeFormDefault == XmlSchemaForm.Unqualified ? XmlSchemaForm.None : attributeFormDefault;
  297.                 #pragma warning restore 429
  298.                 schemas.Add(schema);
  299.             }
  300.            
  301.             if (item is XmlSchemaElement) {
  302.                 XmlSchemaElement e = (XmlSchemaElement)item;
  303.                 if (e.Form == XmlSchemaForm.Unqualified)
  304.                     throw new InvalidOperationException(Res.GetString(Res.XmlIllegalForm, e.Name));
  305.                 e.Form = XmlSchemaForm.None;
  306.             }
  307.             else if (item is XmlSchemaAttribute) {
  308.                 XmlSchemaAttribute a = (XmlSchemaAttribute)item;
  309.                 if (a.Form == XmlSchemaForm.Unqualified)
  310.                     throw new InvalidOperationException(Res.GetString(Res.XmlIllegalForm, a.Name));
  311.                 a.Form = XmlSchemaForm.None;
  312.             }
  313.             schema.Items.Add(item);
  314.             AddSchemaImport(ns, referencingNs);
  315.         }
  316.        
  317.         void AddSchemaImport(string ns, string referencingNs)
  318.         {
  319.             if (referencingNs == null)
  320.                 return;
  321.             if (NamespacesEqual(ns, referencingNs))
  322.                 return;
  323.             XmlSchema schema = schemas[referencingNs];
  324.             if (schema == null)
  325.                 throw new InvalidOperationException(Res.GetString(Res.XmlMissingSchema, referencingNs));
  326.             if (FindImport(schema, ns) == null) {
  327.                 XmlSchemaImport import = new XmlSchemaImport();
  328.                 if (ns != null && ns.Length > 0)
  329.                     import.Namespace = ns;
  330.                 schema.Includes.Add(import);
  331.             }
  332.         }
  333.        
  334.         static bool NamespacesEqual(string ns1, string ns2)
  335.         {
  336.             if (ns1 == null || ns1.Length == 0)
  337.                 return (ns2 == null || ns2.Length == 0);
  338.             else
  339.                 return ns1 == ns2;
  340.         }
  341.        
  342.         bool SchemaContainsItem(XmlSchemaObject item, string ns)
  343.         {
  344.             XmlSchema schema = schemas[ns];
  345.             if (schema != null) {
  346.                 return schema.Items.Contains(item);
  347.             }
  348.             return false;
  349.         }
  350.        
  351.         XmlSchemaImport FindImport(XmlSchema schema, string ns)
  352.         {
  353.             foreach (object item in schema.Includes) {
  354.                 if (item is XmlSchemaImport) {
  355.                     XmlSchemaImport import = (XmlSchemaImport)item;
  356.                     if (NamespacesEqual(import.Namespace, ns)) {
  357.                         return import;
  358.                     }
  359.                 }
  360.             }
  361.             return null;
  362.         }
  363.        
  364.         void ExportMapping(Mapping mapping, string ns, bool isAny)
  365.         {
  366.             if (mapping is ArrayMapping)
  367.                 ExportArrayMapping((ArrayMapping)mapping, ns, null);
  368.             else if (mapping is PrimitiveMapping) {
  369.                 ExportPrimitiveMapping((PrimitiveMapping)mapping, ns);
  370.             }
  371.             else if (mapping is StructMapping)
  372.                 ExportStructMapping((StructMapping)mapping, ns, null);
  373.             else if (mapping is MembersMapping)
  374.                 ExportMembersMapping((MembersMapping)mapping, ns);
  375.             else if (mapping is SpecialMapping)
  376.                 ExportSpecialMapping((SpecialMapping)mapping, ns, isAny, null);
  377.             else if (mapping is NullableMapping)
  378.                 ExportMapping(((NullableMapping)mapping).BaseMapping, ns, isAny);
  379.             else
  380.                 throw new ArgumentException(Res.GetString(Res.XmlInternalError), "mapping");
  381.         }
  382.        
  383.         void ExportElementMapping(XmlSchemaElement element, Mapping mapping, string ns, bool isAny)
  384.         {
  385.             if (mapping is ArrayMapping)
  386.                 ExportArrayMapping((ArrayMapping)mapping, ns, element);
  387.             else if (mapping is PrimitiveMapping) {
  388.                 PrimitiveMapping pm = (PrimitiveMapping)mapping;
  389.                 if (pm.IsAnonymousType) {
  390.                     element.SchemaType = ExportAnonymousPrimitiveMapping(pm);
  391.                 }
  392.                 else {
  393.                     element.SchemaTypeName = ExportPrimitiveMapping(pm, ns);
  394.                 }
  395.             }
  396.             else if (mapping is StructMapping) {
  397.                 ExportStructMapping((StructMapping)mapping, ns, element);
  398.             }
  399.             else if (mapping is MembersMapping)
  400.                 element.SchemaType = ExportMembersMapping((MembersMapping)mapping, ns);
  401.             else if (mapping is SpecialMapping)
  402.                 ExportSpecialMapping((SpecialMapping)mapping, ns, isAny, element);
  403.             else if (mapping is NullableMapping) {
  404.                 ExportElementMapping(element, ((NullableMapping)mapping).BaseMapping, ns, isAny);
  405.             }
  406.             else
  407.                 throw new ArgumentException(Res.GetString(Res.XmlInternalError), "mapping");
  408.         }
  409.        
  410.         XmlQualifiedName ExportNonXsdPrimitiveMapping(PrimitiveMapping mapping, string ns)
  411.         {
  412.             XmlSchemaSimpleType type = (XmlSchemaSimpleType)mapping.TypeDesc.DataType;
  413.             if (!SchemaContainsItem(type, UrtTypes.Namespace)) {
  414.                 AddSchemaItem(type, UrtTypes.Namespace, ns);
  415.             }
  416.             else {
  417.                 AddSchemaImport(mapping.Namespace, ns);
  418.             }
  419.             return new XmlQualifiedName(mapping.TypeDesc.DataType.Name, UrtTypes.Namespace);
  420.         }
  421.        
  422.         XmlSchemaType ExportSpecialMapping(SpecialMapping mapping, string ns, bool isAny, XmlSchemaElement element)
  423.         {
  424.             switch (mapping.TypeDesc.Kind) {
  425.                 case TypeKind.Node:
  426.                    
  427.                     {
  428.                         XmlSchemaComplexType type = new XmlSchemaComplexType();
  429.                         type.IsMixed = mapping.TypeDesc.IsMixed;
  430.                         XmlSchemaSequence seq = new XmlSchemaSequence();
  431.                         XmlSchemaAny any = new XmlSchemaAny();
  432.                         if (isAny) {
  433.                             type.AnyAttribute = new XmlSchemaAnyAttribute();
  434.                             type.IsMixed = true;
  435.                             any.MaxOccurs = decimal.MaxValue;
  436.                         }
  437.                         seq.Items.Add(any);
  438.                         type.Particle = seq;
  439.                         if (element != null)
  440.                             element.SchemaType = type;
  441.                         return type;
  442.                     }
  443.                     break;
  444.                 case TypeKind.Serializable:
  445.                    
  446.                     {
  447.                         SerializableMapping serializableMapping = (SerializableMapping)mapping;
  448.                         if (serializableMapping.IsAny) {
  449.                             XmlSchemaComplexType type = new XmlSchemaComplexType();
  450.                             type.IsMixed = mapping.TypeDesc.IsMixed;
  451.                             XmlSchemaSequence seq = new XmlSchemaSequence();
  452.                             XmlSchemaAny any = new XmlSchemaAny();
  453.                             if (isAny) {
  454.                                 type.AnyAttribute = new XmlSchemaAnyAttribute();
  455.                                 type.IsMixed = true;
  456.                                 any.MaxOccurs = decimal.MaxValue;
  457.                             }
  458.                             if (serializableMapping.NamespaceList.Length > 0)
  459.                                 any.Namespace = serializableMapping.NamespaceList;
  460.                             any.ProcessContents = XmlSchemaContentProcessing.Lax;
  461.                             seq.Items.Add(any);
  462.                             type.Particle = seq;
  463.                             if (element != null)
  464.                                 element.SchemaType = type;
  465.                             return type;
  466.                         }
  467.                         else if (serializableMapping.XsiType != null || serializableMapping.XsdType != null) {
  468.                             XmlSchemaType type = serializableMapping.XsdType;
  469.                             // for performance reasons we need to postpone merging of the serializable schemas
  470.                             foreach (XmlSchema schema in serializableMapping.Schemas.Schemas()) {
  471.                                 if (schema.TargetNamespace != XmlSchema.Namespace) {
  472.                                     schemas.Add(schema, true);
  473.                                     AddSchemaImport(schema.TargetNamespace, ns);
  474.                                     if (!serializableMapping.XsiType.IsEmpty && serializableMapping.XsiType.Namespace == schema.TargetNamespace)
  475.                                         type = (XmlSchemaType)schema.SchemaTypes[serializableMapping.XsiType];
  476.                                 }
  477.                             }
  478.                             if (element != null) {
  479.                                 element.SchemaTypeName = serializableMapping.XsiType;
  480.                                 if (element.SchemaTypeName.IsEmpty)
  481.                                     element.SchemaType = type;
  482.                             }
  483.                             // check for duplicate top-level elements XmlAttributes
  484.                             serializableMapping.CheckDuplicateElement(element, ns);
  485.                             return type;
  486.                         }
  487.                         else if (serializableMapping.Schema != null) {
  488.                             // this is the strongly-typed DataSet
  489.                             XmlSchemaComplexType type = new XmlSchemaComplexType();
  490.                             XmlSchemaAny any = new XmlSchemaAny();
  491.                             XmlSchemaSequence seq = new XmlSchemaSequence();
  492.                             seq.Items.Add(any);
  493.                             type.Particle = seq;
  494.                             string anyNs = serializableMapping.Schema.TargetNamespace;
  495.                             any.Namespace = anyNs == null ? "" : anyNs;
  496.                             XmlSchema existingSchema = schemas[anyNs];
  497.                             if (existingSchema == null) {
  498.                                 schemas.Add(serializableMapping.Schema);
  499.                             }
  500.                             else if (existingSchema != serializableMapping.Schema) {
  501.                                 throw new InvalidOperationException(Res.GetString(Res.XmlDuplicateNamespace, anyNs));
  502.                             }
  503.                             if (element != null)
  504.                                 element.SchemaType = type;
  505.                            
  506.                             // check for duplicate top-level elements XmlAttributes
  507.                             serializableMapping.CheckDuplicateElement(element, ns);
  508.                             return type;
  509.                         }
  510.                         else {
  511.                             // DataSet
  512.                             XmlSchemaComplexType type = new XmlSchemaComplexType();
  513.                             XmlSchemaElement schemaElement = new XmlSchemaElement();
  514.                             schemaElement.RefName = new XmlQualifiedName("schema", XmlSchema.Namespace);
  515.                             XmlSchemaSequence seq = new XmlSchemaSequence();
  516.                             seq.Items.Add(schemaElement);
  517.                             seq.Items.Add(new XmlSchemaAny());
  518.                             type.Particle = seq;
  519.                             AddSchemaImport(XmlSchema.Namespace, ns);
  520.                             if (element != null)
  521.                                 element.SchemaType = type;
  522.                             return type;
  523.                         }
  524.                     }
  525.                     break;
  526.                 default:
  527.                     throw new ArgumentException(Res.GetString(Res.XmlInternalError), "mapping");
  528.                     break;
  529.             }
  530.         }
  531.        
  532.         XmlSchemaType ExportMembersMapping(MembersMapping mapping, string ns)
  533.         {
  534.             XmlSchemaComplexType type = new XmlSchemaComplexType();
  535.             ExportTypeMembers(type, mapping.Members, mapping.TypeName, ns, false, false);
  536.            
  537.             if (mapping.XmlnsMember != null) {
  538.                 AddXmlnsAnnotation(type, mapping.XmlnsMember.Name);
  539.             }
  540.            
  541.             return type;
  542.         }
  543.        
  544.         XmlSchemaType ExportAnonymousPrimitiveMapping(PrimitiveMapping mapping)
  545.         {
  546.             if (mapping is EnumMapping) {
  547.                 return ExportEnumMapping((EnumMapping)mapping, null);
  548.             }
  549.             else {
  550.                 throw new InvalidOperationException(Res.GetString(Res.XmlInternalErrorDetails, "Unsuported anonymous mapping type: " + mapping.ToString()));
  551.             }
  552.         }
  553.        
  554.         XmlQualifiedName ExportPrimitiveMapping(PrimitiveMapping mapping, string ns)
  555.         {
  556.             XmlQualifiedName qname;
  557.             if (mapping is EnumMapping) {
  558.                 XmlSchemaType type = ExportEnumMapping((EnumMapping)mapping, ns);
  559.                 qname = new XmlQualifiedName(type.Name, mapping.Namespace);
  560.             }
  561.             else {
  562.                 if (mapping.TypeDesc.IsXsdType) {
  563.                     qname = new XmlQualifiedName(mapping.TypeDesc.DataType.Name, XmlSchema.Namespace);
  564.                 }
  565.                 else {
  566.                     qname = ExportNonXsdPrimitiveMapping(mapping, ns);
  567.                 }
  568.             }
  569.             return qname;
  570.         }
  571.        
  572.         void ExportArrayMapping(ArrayMapping mapping, string ns, XmlSchemaElement element)
  573.         {
  574.             // some of the items in the linked list differ only by CLR type. We don't need to
  575.             // export different schema types for these. Look further down the list for another
  576.             // entry with the same elements. If there is one, it will be exported later so
  577.             // just return its name now.
  578.            
  579.             ArrayMapping currentMapping = mapping;
  580.             while (currentMapping.Next != null) {
  581.                 currentMapping = currentMapping.Next;
  582.             }
  583.             XmlSchemaComplexType type = (XmlSchemaComplexType)types[currentMapping];
  584.             if (type == null) {
  585.                 CheckForDuplicateType(currentMapping, currentMapping.Namespace);
  586.                 type = new XmlSchemaComplexType();
  587.                 if (!mapping.IsAnonymousType) {
  588.                     type.Name = mapping.TypeName;
  589.                     AddSchemaItem(type, mapping.Namespace, ns);
  590.                 }
  591.                 types.Add(currentMapping, type);
  592.                 XmlSchemaSequence seq = new XmlSchemaSequence();
  593.                 ExportElementAccessors(seq, mapping.Elements, true, false, mapping.Namespace);
  594.                 if (seq.Items.Count > 0) {
  595.                     #if DEBUG
  596.                     // we can have only one item for the array mapping
  597.                     if (seq.Items.Count != 1)
  598.                         throw new InvalidOperationException(Res.GetString(Res.XmlInternalErrorDetails, "Type " + mapping.TypeName + " from namespace '" + ns + "' is an invalid array mapping"));
  599.                     #endif
  600.                     if (seq.Items[0] is XmlSchemaChoice) {
  601.                         type.Particle = (XmlSchemaChoice)seq.Items[0];
  602.                     }
  603.                     else {
  604.                         type.Particle = seq;
  605.                     }
  606.                 }
  607.             }
  608.             else {
  609.                 AddSchemaImport(mapping.Namespace, ns);
  610.             }
  611.             if (element != null) {
  612.                 if (mapping.IsAnonymousType) {
  613.                     element.SchemaType = type;
  614.                 }
  615.                 else {
  616.                     element.SchemaTypeName = new XmlQualifiedName(type.Name, mapping.Namespace);
  617.                 }
  618.             }
  619.         }
  620.        
  621.         void ExportElementAccessors(XmlSchemaGroupBase group, ElementAccessor[] accessors, bool repeats, bool valueTypeOptional, string ns)
  622.         {
  623.             if (accessors.Length == 0)
  624.                 return;
  625.             if (accessors.Length == 1) {
  626.                 ExportElementAccessor(group, accessors[0], repeats, valueTypeOptional, ns);
  627.             }
  628.             else {
  629.                 XmlSchemaChoice choice = new XmlSchemaChoice();
  630.                 choice.MaxOccurs = repeats ? decimal.MaxValue : 1;
  631.                 choice.MinOccurs = repeats ? 0 : 1;
  632.                 for (int i = 0; i < accessors.Length; i++)
  633.                     ExportElementAccessor(choice, accessors[i], false, valueTypeOptional, ns);
  634.                
  635.                 if (choice.Items.Count > 0)
  636.                     group.Items.Add(choice);
  637.             }
  638.         }
  639.        
  640.         void ExportAttributeAccessor(XmlSchemaComplexType type, AttributeAccessor accessor, bool valueTypeOptional, string ns)
  641.         {
  642.             if (accessor == null)
  643.                 return;
  644.             XmlSchemaObjectCollection attributes;
  645.            
  646.             if (type.ContentModel != null) {
  647.                 if (type.ContentModel.Content is XmlSchemaComplexContentRestriction)
  648.                     attributes = ((XmlSchemaComplexContentRestriction)type.ContentModel.Content).Attributes;
  649.                 else if (type.ContentModel.Content is XmlSchemaComplexContentExtension)
  650.                     attributes = ((XmlSchemaComplexContentExtension)type.ContentModel.Content).Attributes;
  651.                 else if (type.ContentModel.Content is XmlSchemaSimpleContentExtension)
  652.                     attributes = ((XmlSchemaSimpleContentExtension)type.ContentModel.Content).Attributes;
  653.                 else
  654.                     throw new InvalidOperationException(Res.GetString(Res.XmlInvalidContent, type.ContentModel.Content.GetType().Name));
  655.             }
  656.             else {
  657.                 attributes = type.Attributes;
  658.             }
  659.            
  660.             if (accessor.IsSpecialXmlNamespace) {
  661.                
  662.                 // add <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
  663.                 AddSchemaImport(XmlReservedNs.NsXml, ns);
  664.                
  665.                 // generate <xsd:attribute ref="xml:lang" use="optional" />
  666.                 XmlSchemaAttribute attribute = new XmlSchemaAttribute();
  667.                 attribute.Use = XmlSchemaUse.Optional;
  668.                 attribute.RefName = new XmlQualifiedName(accessor.Name, XmlReservedNs.NsXml);
  669.                 attributes.Add(attribute);
  670.             }
  671.             else if (accessor.Any) {
  672.                 if (type.ContentModel == null) {
  673.                     type.AnyAttribute = new XmlSchemaAnyAttribute();
  674.                 }
  675.                 else {
  676.                     XmlSchemaContent content = type.ContentModel.Content;
  677.                     if (content is XmlSchemaComplexContentExtension) {
  678.                         XmlSchemaComplexContentExtension extension = (XmlSchemaComplexContentExtension)content;
  679.                         extension.AnyAttribute = new XmlSchemaAnyAttribute();
  680.                     }
  681.                     else if (content is XmlSchemaComplexContentRestriction) {
  682.                         XmlSchemaComplexContentRestriction restriction = (XmlSchemaComplexContentRestriction)content;
  683.                         restriction.AnyAttribute = new XmlSchemaAnyAttribute();
  684.                     }
  685.                     else if (type.ContentModel.Content is XmlSchemaSimpleContentExtension) {
  686.                         XmlSchemaSimpleContentExtension extension = (XmlSchemaSimpleContentExtension)content;
  687.                         extension.AnyAttribute = new XmlSchemaAnyAttribute();
  688.                     }
  689.                 }
  690.             }
  691.             else {
  692.                 XmlSchemaAttribute attribute = new XmlSchemaAttribute();
  693.                 attribute.Use = XmlSchemaUse.None;
  694.                 if (!accessor.HasDefault && !valueTypeOptional && accessor.Mapping.TypeDesc.IsValueType) {
  695.                     attribute.Use = XmlSchemaUse.Required;
  696.                 }
  697.                 attribute.Name = accessor.Name;
  698.                 if (accessor.Namespace == null || accessor.Namespace == ns) {
  699.                     // determine the form attribute value
  700.                     XmlSchema schema = schemas[ns];
  701.                     if (schema == null)
  702.                         attribute.Form = accessor.Form == attributeFormDefault ? XmlSchemaForm.None : accessor.Form;
  703.                     else {
  704.                         attribute.Form = accessor.Form == schema.AttributeFormDefault ? XmlSchemaForm.None : accessor.Form;
  705.                     }
  706.                     attributes.Add(attribute);
  707.                 }
  708.                 else {
  709.                     // we are going to add the attribute to the top-level items. "use" attribute should not be set
  710.                     if (this.attributes[accessor] == null) {
  711.                         attribute.Use = XmlSchemaUse.None;
  712.                         attribute.Form = accessor.Form;
  713.                         AddSchemaItem(attribute, accessor.Namespace, ns);
  714.                         this.attributes.Add(accessor, accessor);
  715.                     }
  716.                     XmlSchemaAttribute refAttribute = new XmlSchemaAttribute();
  717.                     refAttribute.Use = XmlSchemaUse.None;
  718.                     refAttribute.RefName = new XmlQualifiedName(accessor.Name, accessor.Namespace);
  719.                     attributes.Add(refAttribute);
  720.                     AddSchemaImport(accessor.Namespace, ns);
  721.                 }
  722.                 if (accessor.Mapping is PrimitiveMapping) {
  723.                     PrimitiveMapping pm = (PrimitiveMapping)accessor.Mapping;
  724.                     if (pm.IsList) {
  725.                         // create local simple type for the list-like attributes
  726.                         XmlSchemaSimpleType dataType = new XmlSchemaSimpleType();
  727.                         XmlSchemaSimpleTypeList list = new XmlSchemaSimpleTypeList();
  728.                         if (pm.IsAnonymousType) {
  729.                             list.ItemType = (XmlSchemaSimpleType)ExportAnonymousPrimitiveMapping(pm);
  730.                         }
  731.                         else {
  732.                             list.ItemTypeName = ExportPrimitiveMapping(pm, accessor.Namespace == null ? ns : accessor.Namespace);
  733.                         }
  734.                         dataType.Content = list;
  735.                         attribute.SchemaType = dataType;
  736.                     }
  737.                     else {
  738.                         if (pm.IsAnonymousType) {
  739.                             attribute.SchemaType = (XmlSchemaSimpleType)ExportAnonymousPrimitiveMapping(pm);
  740.                         }
  741.                         else {
  742.                             attribute.SchemaTypeName = ExportPrimitiveMapping(pm, accessor.Namespace == null ? ns : accessor.Namespace);
  743.                         }
  744.                     }
  745.                 }
  746.                 else if (!(accessor.Mapping is SpecialMapping))
  747.                     throw new InvalidOperationException(Res.GetString(Res.XmlInternalError));
  748.                
  749.                 if (accessor.HasDefault) {
  750.                     attribute.DefaultValue = ExportDefaultValue(accessor.Mapping, accessor.Default);
  751.                 }
  752.             }
  753.         }
  754.        
  755.         void ExportElementAccessor(XmlSchemaGroupBase group, ElementAccessor accessor, bool repeats, bool valueTypeOptional, string ns)
  756.         {
  757.             if (accessor.Any && accessor.Name.Length == 0) {
  758.                 XmlSchemaAny any = new XmlSchemaAny();
  759.                 any.MinOccurs = 0;
  760.                 any.MaxOccurs = repeats ? decimal.MaxValue : 1;
  761.                 if (accessor.Namespace != null && accessor.Namespace.Length > 0 && accessor.Namespace != ns)
  762.                     any.Namespace = accessor.Namespace;
  763.                 group.Items.Add(any);
  764.             }
  765.             else {
  766.                 XmlSchemaElement element = (XmlSchemaElement)elements[accessor];
  767.                 int minOccurs = repeats || accessor.HasDefault || (!accessor.IsNullable && !accessor.Mapping.TypeDesc.IsValueType) || valueTypeOptional ? 0 : 1;
  768.                 decimal maxOccurs = repeats || accessor.IsUnbounded ? decimal.MaxValue : 1;
  769.                
  770.                 if (element == null) {
  771.                     element = new XmlSchemaElement();
  772.                     element.IsNillable = accessor.IsNullable;
  773.                     element.Name = accessor.Name;
  774.                     if (accessor.HasDefault)
  775.                         element.DefaultValue = ExportDefaultValue(accessor.Mapping, accessor.Default);
  776.                    
  777.                     if (accessor.IsTopLevelInSchema) {
  778.                         elements.Add(accessor, element);
  779.                         element.Form = accessor.Form;
  780.                         AddSchemaItem(element, accessor.Namespace, ns);
  781.                     }
  782.                     else {
  783.                         element.MinOccurs = minOccurs;
  784.                         element.MaxOccurs = maxOccurs;
  785.                         // determine the form attribute value
  786.                         XmlSchema schema = schemas[ns];
  787.                         if (schema == null)
  788.                             element.Form = accessor.Form == elementFormDefault ? XmlSchemaForm.None : accessor.Form;
  789.                         else {
  790.                             element.Form = accessor.Form == schema.ElementFormDefault ? XmlSchemaForm.None : accessor.Form;
  791.                         }
  792.                     }
  793.                     ExportElementMapping(element, (TypeMapping)accessor.Mapping, accessor.Namespace, accessor.Any);
  794.                 }
  795.                 if (accessor.IsTopLevelInSchema) {
  796.                     XmlSchemaElement refElement = new XmlSchemaElement();
  797.                     refElement.RefName = new XmlQualifiedName(accessor.Name, accessor.Namespace);
  798.                     refElement.MinOccurs = minOccurs;
  799.                     refElement.MaxOccurs = maxOccurs;
  800.                     group.Items.Add(refElement);
  801.                     AddSchemaImport(accessor.Namespace, ns);
  802.                 }
  803.                 else {
  804.                     group.Items.Add(element);
  805.                 }
  806.             }
  807.         }
  808.        
  809.         static internal string ExportDefaultValue(TypeMapping mapping, object value)
  810.         {
  811.            
  812.             if (!(mapping is PrimitiveMapping))
  813.                 return null;
  814.            
  815.             if (value == null || value == DBNull.Value)
  816.                 return null;
  817.            
  818.             if (mapping is EnumMapping) {
  819.                 EnumMapping em = (EnumMapping)mapping;
  820.                
  821.                 #if DEBUG
  822.                 // use exception in the place of Debug.Assert to avoid throwing asserts from a server process such as aspnet_ewp.exe
  823.                 if (value.GetType() != typeof(string))
  824.                     throw new InvalidOperationException(Res.GetString(Res.XmlInternalErrorDetails, Res.GetString(Res.XmlInvalidDefaultValue, value.ToString(), value.GetType().FullName)));
  825.                 #endif
  826.                
  827.                 // check the validity of the value
  828.                 ConstantMapping[] c = em.Constants;
  829.                 if (em.IsFlags) {
  830.                     string[] names = new string[c.Length];
  831.                     long[] ids = new long[c.Length];
  832.                     Hashtable values = new Hashtable();
  833.                     for (int i = 0; i < c.Length; i++) {
  834.                         names[i] = c[i].XmlName;
  835.                         ids[i] = 1 << i;
  836.                         values.Add(c[i].Name, ids[i]);
  837.                     }
  838.                     long val = XmlCustomFormatter.ToEnum((string)value, values, em.TypeName, false);
  839.                     return val != 0 ? XmlCustomFormatter.FromEnum(val, names, ids, mapping.TypeDesc.FullName) : null;
  840.                 }
  841.                 else {
  842.                     for (int i = 0; i < c.Length; i++) {
  843.                         if (c[i].Name == (string)value) {
  844.                             return c[i].XmlName;
  845.                         }
  846.                     }
  847.                     return null;
  848.                     // unknown value
  849.                 }
  850.             }
  851.            
  852.             PrimitiveMapping pm = (PrimitiveMapping)mapping;
  853.            
  854.             if (!pm.TypeDesc.HasCustomFormatter) {
  855.                
  856.                 #if DEBUG
  857.                 // use exception in the place of Debug.Assert to avoid throwing asserts from a server process such as aspnet_ewp.exe
  858.                 if (pm.TypeDesc.Type == null) {
  859.                     throw new InvalidOperationException(Res.GetString(Res.XmlInternalErrorDetails, "Mapping for " + pm.TypeDesc.Name + " missing type property"));
  860.                 }
  861.                 #endif
  862.                
  863.                 if (pm.TypeDesc.FormatterName == "String")
  864.                     return (string)value;
  865.                
  866.                 Type formatter = typeof(XmlConvert);
  867.                 System.Reflection.MethodInfo format = formatter.GetMethod("ToString", new Type[] {pm.TypeDesc.Type});
  868.                 if (format != null)
  869.                     return (string)format.Invoke(formatter, new object[] {value});
  870.             }
  871.             else {
  872.                 string defaultValue = XmlCustomFormatter.FromDefaultValue(value, pm.TypeDesc.FormatterName);
  873.                 if (defaultValue == null)
  874.                     throw new InvalidOperationException(Res.GetString(Res.XmlInvalidDefaultValue, value.ToString(), pm.TypeDesc.Name));
  875.                 return defaultValue;
  876.             }
  877.             throw new InvalidOperationException(Res.GetString(Res.XmlInvalidDefaultValue, value.ToString(), pm.TypeDesc.Name));
  878.         }
  879.        
  880.         void ExportRootIfNecessary(TypeScope typeScope)
  881.         {
  882.             if (!needToExportRoot)
  883.                 return;
  884.             foreach (TypeMapping mapping in typeScope.TypeMappings) {
  885.                 if (mapping is StructMapping && mapping.TypeDesc.IsRoot) {
  886.                     ExportDerivedMappings((StructMapping)mapping);
  887.                 }
  888.                 else if (mapping is ArrayMapping) {
  889.                     ExportArrayMapping((ArrayMapping)mapping, mapping.Namespace, null);
  890.                 }
  891.                 else if (mapping is SerializableMapping) {
  892.                     ExportSpecialMapping((SerializableMapping)mapping, mapping.Namespace, false, null);
  893.                 }
  894.             }
  895.         }
  896.        
  897.         XmlQualifiedName ExportStructMapping(StructMapping mapping, string ns, XmlSchemaElement element)
  898.         {
  899.             if (mapping.TypeDesc.IsRoot) {
  900.                 needToExportRoot = true;
  901.                 return XmlQualifiedName.Empty;
  902.             }
  903.             if (mapping.IsAnonymousType) {
  904.                 if (references[mapping] != null)
  905.                     throw new InvalidOperationException(Res.GetString(Res.XmlCircularReference2, mapping.TypeDesc.Name, "AnonymousType", "false"));
  906.                 references[mapping] = mapping;
  907.             }
  908.             XmlSchemaComplexType type = (XmlSchemaComplexType)types[mapping];
  909.             if (type == null) {
  910.                 if (!mapping.IncludeInSchema)
  911.                     throw new InvalidOperationException(Res.GetString(Res.XmlCannotIncludeInSchema, mapping.TypeDesc.Name));
  912.                 CheckForDuplicateType(mapping, mapping.Namespace);
  913.                 type = new XmlSchemaComplexType();
  914.                 if (!mapping.IsAnonymousType) {
  915.                     type.Name = mapping.TypeName;
  916.                     AddSchemaItem(type, mapping.Namespace, ns);
  917.                 }
  918.                 types.Add(mapping, type);
  919.                 type.IsAbstract = mapping.TypeDesc.IsAbstract;
  920.                 bool openModel = mapping.IsOpenModel;
  921.                 if (mapping.BaseMapping != null && mapping.BaseMapping.IncludeInSchema) {
  922.                     if (mapping.BaseMapping.IsAnonymousType) {
  923.                         throw new InvalidOperationException(Res.GetString(Res.XmlAnonymousBaseType, mapping.TypeDesc.Name, mapping.BaseMapping.TypeDesc.Name, "AnonymousType", "false"));
  924.                     }
  925.                     if (mapping.HasSimpleContent) {
  926.                         XmlSchemaSimpleContent model = new XmlSchemaSimpleContent();
  927.                         XmlSchemaSimpleContentExtension extension = new XmlSchemaSimpleContentExtension();
  928.                         extension.BaseTypeName = ExportStructMapping(mapping.BaseMapping, mapping.Namespace, null);
  929.                         model.Content = extension;
  930.                         type.ContentModel = model;
  931.                     }
  932.                     else {
  933.                         XmlSchemaComplexContentExtension extension = new XmlSchemaComplexContentExtension();
  934.                         extension.BaseTypeName = ExportStructMapping(mapping.BaseMapping, mapping.Namespace, null);
  935.                         XmlSchemaComplexContent model = new XmlSchemaComplexContent();
  936.                         model.Content = extension;
  937.                         model.IsMixed = XmlSchemaImporter.IsMixed((XmlSchemaComplexType)types[mapping.BaseMapping]);
  938.                         type.ContentModel = model;
  939.                     }
  940.                     openModel = false;
  941.                 }
  942.                 ExportTypeMembers(type, mapping.Members, mapping.TypeName, mapping.Namespace, mapping.HasSimpleContent, openModel);
  943.                 ExportDerivedMappings(mapping);
  944.                 if (mapping.XmlnsMember != null) {
  945.                     AddXmlnsAnnotation(type, mapping.XmlnsMember.Name);
  946.                 }
  947.             }
  948.             else {
  949.                 AddSchemaImport(mapping.Namespace, ns);
  950.             }
  951.             if (mapping.IsAnonymousType) {
  952.                 references[mapping] = null;
  953.                 if (element != null)
  954.                     element.SchemaType = type;
  955.                 return XmlQualifiedName.Empty;
  956.             }
  957.             else {
  958.                 XmlQualifiedName qname = new XmlQualifiedName(type.Name, mapping.Namespace);
  959.                 if (element != null)
  960.                     element.SchemaTypeName = qname;
  961.                 return qname;
  962.             }
  963.         }
  964.        
  965.         void ExportTypeMembers(XmlSchemaComplexType type, MemberMapping[] members, string name, string ns, bool hasSimpleContent, bool openModel)
  966.         {
  967.             XmlSchemaGroupBase seq = new XmlSchemaSequence();
  968.             TypeMapping textMapping = null;
  969.            
  970.             for (int i = 0; i < members.Length; i++) {
  971.                 MemberMapping member = members[i];
  972.                 if (member.Ignore)
  973.                     continue;
  974.                 if (member.Text != null) {
  975.                     if (textMapping != null) {
  976.                         throw new InvalidOperationException(Res.GetString(Res.XmlIllegalMultipleText, name));
  977.                     }
  978.                     textMapping = member.Text.Mapping;
  979.                 }
  980.                 if (member.Elements.Length > 0) {
  981.                     bool repeats = member.TypeDesc.IsArrayLike && !(member.Elements.Length == 1 && member.Elements[0].Mapping is ArrayMapping);
  982.                     bool valueTypeOptional = member.CheckSpecified || member.CheckShouldPersist;
  983.                     ExportElementAccessors(seq, member.Elements, repeats, valueTypeOptional, ns);
  984.                 }
  985.             }
  986.            
  987.             if (seq.Items.Count > 0) {
  988.                 if (type.ContentModel != null) {
  989.                     if (type.ContentModel.Content is XmlSchemaComplexContentRestriction)
  990.                         ((XmlSchemaComplexContentRestriction)type.ContentModel.Content).Particle = seq;
  991.                     else if (type.ContentModel.Content is XmlSchemaComplexContentExtension)
  992.                         ((XmlSchemaComplexContentExtension)type.ContentModel.Content).Particle = seq;
  993.                     else
  994.                         throw new InvalidOperationException(Res.GetString(Res.XmlInvalidContent, type.ContentModel.Content.GetType().Name));
  995.                 }
  996.                 else {
  997.                     type.Particle = seq;
  998.                 }
  999.             }
  1000.             if (textMapping != null) {
  1001.                 if (hasSimpleContent) {
  1002.                     if (textMapping is PrimitiveMapping && seq.Items.Count == 0) {
  1003.                         PrimitiveMapping pm = (PrimitiveMapping)textMapping;
  1004.                         if (pm.IsList) {
  1005.                             type.IsMixed = true;
  1006.                         }
  1007.                         else {
  1008.                             if (pm.IsAnonymousType) {
  1009.                                 throw new InvalidOperationException(Res.GetString(Res.XmlAnonymousBaseType, textMapping.TypeDesc.Name, pm.TypeDesc.Name, "AnonymousType", "false"));
  1010.                             }
  1011.                             // Create simpleContent
  1012.                             XmlSchemaSimpleContent model = new XmlSchemaSimpleContent();
  1013.                             XmlSchemaSimpleContentExtension ex = new XmlSchemaSimpleContentExtension();
  1014.                             model.Content = ex;
  1015.                             type.ContentModel = model;
  1016.                             ex.BaseTypeName = ExportPrimitiveMapping(pm, ns);
  1017.                         }
  1018.                     }
  1019.                 }
  1020.                 else {
  1021.                     type.IsMixed = true;
  1022.                 }
  1023.             }
  1024.             bool anyAttribute = false;
  1025.             for (int i = 0; i < members.Length; i++) {
  1026.                 AttributeAccessor accessor = members[i].Attribute;
  1027.                 if (accessor != null) {
  1028.                     ExportAttributeAccessor(type, members[i].Attribute, members[i].CheckSpecified || members[i].CheckShouldPersist, ns);
  1029.                     if (members[i].Attribute.Any)
  1030.                         anyAttribute = true;
  1031.                 }
  1032.             }
  1033.             if (openModel && !anyAttribute) {
  1034.                 AttributeAccessor any = new AttributeAccessor();
  1035.                 any.Any = true;
  1036.                 ExportAttributeAccessor(type, any, false, ns);
  1037.             }
  1038.         }
  1039.        
  1040.         void ExportDerivedMappings(StructMapping mapping)
  1041.         {
  1042.             if (mapping.IsAnonymousType)
  1043.                 return;
  1044.             for (StructMapping derived = mapping.DerivedMappings; derived != null; derived = derived.NextDerivedMapping) {
  1045.                 if (derived.IncludeInSchema)
  1046.                     ExportStructMapping(derived, derived.Namespace, null);
  1047.             }
  1048.         }
  1049.        
  1050.         XmlSchemaType ExportEnumMapping(EnumMapping mapping, string ns)
  1051.         {
  1052.             if (!mapping.IncludeInSchema)
  1053.                 throw new InvalidOperationException(Res.GetString(Res.XmlCannotIncludeInSchema, mapping.TypeDesc.Name));
  1054.             XmlSchemaSimpleType dataType = (XmlSchemaSimpleType)types[mapping];
  1055.             if (dataType == null) {
  1056.                 CheckForDuplicateType(mapping, mapping.Namespace);
  1057.                 dataType = new XmlSchemaSimpleType();
  1058.                 dataType.Name = mapping.TypeName;
  1059.                 types.Add(mapping, dataType);
  1060.                 if (!mapping.IsAnonymousType)
  1061.                     AddSchemaItem(dataType, mapping.Namespace, ns);
  1062.                
  1063.                 XmlSchemaSimpleTypeRestriction restriction = new XmlSchemaSimpleTypeRestriction();
  1064.                 restriction.BaseTypeName = new XmlQualifiedName("string", XmlSchema.Namespace);
  1065.                
  1066.                 for (int i = 0; i < mapping.Constants.Length; i++) {
  1067.                     ConstantMapping constant = mapping.Constants[i];
  1068.                     XmlSchemaEnumerationFacet enumeration = new XmlSchemaEnumerationFacet();
  1069.                     enumeration.Value = constant.XmlName;
  1070.                     restriction.Facets.Add(enumeration);
  1071.                 }
  1072.                 if (!mapping.IsFlags) {
  1073.                     dataType.Content = restriction;
  1074.                 }
  1075.                 else {
  1076.                     XmlSchemaSimpleTypeList list = new XmlSchemaSimpleTypeList();
  1077.                     XmlSchemaSimpleType enumType = new XmlSchemaSimpleType();
  1078.                     enumType.Content = restriction;
  1079.                     list.ItemType = enumType;
  1080.                     dataType.Content = list;
  1081.                 }
  1082.             }
  1083.             if (!mapping.IsAnonymousType) {
  1084.                 AddSchemaImport(mapping.Namespace, ns);
  1085.             }
  1086.             return dataType;
  1087.         }
  1088.        
  1089.         void AddXmlnsAnnotation(XmlSchemaComplexType type, string xmlnsMemberName)
  1090.         {
  1091.             XmlSchemaAnnotation annotation = new XmlSchemaAnnotation();
  1092.             XmlSchemaAppInfo appinfo = new XmlSchemaAppInfo();
  1093.            
  1094.             XmlDocument d = new XmlDocument();
  1095.             XmlElement e = d.CreateElement("keepNamespaceDeclarations");
  1096.             if (xmlnsMemberName != null)
  1097.                 e.InsertBefore(d.CreateTextNode(xmlnsMemberName), null);
  1098.             appinfo.Markup = new XmlNode[] {e};
  1099.             annotation.Items.Add(appinfo);
  1100.             type.Annotation = annotation;
  1101.         }
  1102.     }
  1103. }

Developer Fusion