1 //------------------------------------------------------------------------------
2 // <copyright file="XmlSchemaImporter.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 // <owner current="true" primary="true">Microsoft</owner>
6 //------------------------------------------------------------------------------
8 namespace System
.Xml
.Serialization
{
11 using System
.Xml
.Schema
;
12 using System
.Collections
;
13 using System
.Collections
.Generic
;
14 using System
.ComponentModel
;
15 using System
.Reflection
;
16 using System
.Xml
.Serialization
.Configuration
;
18 using System
.CodeDom
.Compiler
;
19 using System
.Collections
.Specialized
;
20 using System
.Globalization
;
21 using System
.Security
.Permissions
;
22 using System
.Xml
.Serialization
.Advanced
;
25 using System
.Diagnostics
;
28 /// <include file='doc\XmlSchemaImporter.uex' path='docs/doc[@for="XmlSchemaImporter"]/*' />
31 /// <para>[To be supplied.]</para>
33 public class XmlSchemaImporter
: SchemaImporter
{
35 /// <include file='doc\XmlSchemaImporter.uex' path='docs/doc[@for="XmlSchemaImporter.XmlSchemaImporter"]/*' />
37 /// <para>[To be supplied.]</para>
39 public XmlSchemaImporter(XmlSchemas schemas
) : base(schemas
, CodeGenerationOptions
.GenerateProperties
, null, new ImportContext()) {}
41 /// <include file='doc\XmlSchemaImporter.uex' path='docs/doc[@for="XmlSchemaImporter.XmlSchemaImporter1"]/*' />
43 /// <para>[To be supplied.]</para>
45 public XmlSchemaImporter(XmlSchemas schemas
, CodeIdentifiers typeIdentifiers
) : base(schemas
, CodeGenerationOptions
.GenerateProperties
, null, new ImportContext(typeIdentifiers
, false)) {}
47 /// <include file='doc\XmlSchemaImporter.uex' path='docs/doc[@for="XmlSchemaImporter.XmlSchemaImporter2"]/*' />
49 /// <para>[To be supplied.]</para>
51 public XmlSchemaImporter(XmlSchemas schemas
, CodeIdentifiers typeIdentifiers
, CodeGenerationOptions options
) : base(schemas
, options
, null, new ImportContext(typeIdentifiers
, false)) {}
53 /// <include file='doc\XmlSchemaImporter.uex' path='docs/doc[@for="XmlSchemaImporter.XmlSchemaImporter3"]/*' />
55 /// <para>[To be supplied.]</para>
57 public XmlSchemaImporter(XmlSchemas schemas
, CodeGenerationOptions options
, ImportContext context
) : base(schemas
, options
, null, context
){}
59 /// <include file='doc\XmlSchemaImporter.uex' path='docs/doc[@for="XmlSchemaImporter.XmlSchemaImporter4"]/*' />
61 /// <para>[To be supplied.]</para>
63 public XmlSchemaImporter(XmlSchemas schemas
, CodeGenerationOptions options
, CodeDomProvider codeProvider
, ImportContext context
) : base(schemas
, options
, codeProvider
, context
){
66 /// <include file='doc\XmlSchemaImporter.uex' path='docs/doc[@for="XmlSchemaImporter.ImportDerivedTypeMapping"]/*' />
68 /// <para>[To be supplied.]</para>
70 public XmlTypeMapping
ImportDerivedTypeMapping(XmlQualifiedName name
, Type baseType
) {
71 return ImportDerivedTypeMapping(name
, baseType
, false);
74 internal bool GenerateOrder
{
75 get { return (Options & CodeGenerationOptions.GenerateOrder) != 0; }
78 internal TypeMapping
GetDefaultMapping(TypeFlags flags
) {
79 PrimitiveMapping mapping
= new PrimitiveMapping();
80 mapping
.TypeDesc
= Scope
.GetTypeDesc("string", XmlSchema
.Namespace
, flags
);
81 mapping
.TypeName
= mapping
.TypeDesc
.DataType
.Name
;
82 mapping
.Namespace
= XmlSchema
.Namespace
;
86 /// <include file='doc\XmlSchemaImporter.uex' path='docs/doc[@for="XmlSchemaImporter.ImportDerivedTypeMapping1"]/*' />
88 /// <para>[To be supplied.]</para>
90 public XmlTypeMapping
ImportDerivedTypeMapping(XmlQualifiedName name
, Type baseType
, bool baseTypeCanBeIndirect
) {
91 ElementAccessor element
= ImportElement(name
, typeof(TypeMapping
), baseType
);
93 if (element
.Mapping
is StructMapping
) {
94 MakeDerived((StructMapping
)element
.Mapping
, baseType
, baseTypeCanBeIndirect
);
96 else if (baseType
!= null) {
97 if (element
.Mapping
is ArrayMapping
) {
98 // in the case of the ArrayMapping we can use the top-level StructMapping, because it does not have base base type
99 element
.Mapping
= ((ArrayMapping
)element
.Mapping
).TopLevelMapping
;
100 MakeDerived((StructMapping
)element
.Mapping
, baseType
, baseTypeCanBeIndirect
);
103 // Element '{0}' from namespace '{1}' is not a complex type and cannot be used as a {2}.
104 throw new InvalidOperationException(Res
.GetString(Res
.XmlBadBaseElement
, name
.Name
, name
.Namespace
, baseType
.FullName
));
107 return new XmlTypeMapping(Scope
, element
);
110 /// <include file='doc\XmlSchemaImporter.uex' path='docs/doc[@for="XmlSchemaImporter.ImportSchemaType"]/*' />
112 /// <para>[To be supplied.]</para>
114 public XmlTypeMapping
ImportSchemaType(XmlQualifiedName typeName
) {
115 return ImportSchemaType(typeName
, null, false);
119 /// <include file='doc\XmlSchemaImporter.uex' path='docs/doc[@for="XmlSchemaImporter.ImportSchemaType1"]/*' />
121 /// <para>[To be supplied.]</para>
123 public XmlTypeMapping
ImportSchemaType(XmlQualifiedName typeName
, Type baseType
) {
124 return ImportSchemaType(typeName
, baseType
, false);
127 /// <include file='doc\XmlSchemaImporter.uex' path='docs/doc[@for="XmlSchemaImporter.ImportSchemaType2"]/*' />
129 /// <para>[To be supplied.]</para>
131 public XmlTypeMapping
ImportSchemaType(XmlQualifiedName typeName
, Type baseType
, bool baseTypeCanBeIndirect
) {
132 TypeMapping typeMapping
= ImportType(typeName
, typeof(TypeMapping
), baseType
, TypeFlags
.CanBeElementValue
, true);
133 typeMapping
.ReferencedByElement
= false;
135 ElementAccessor accessor
= new ElementAccessor();
136 accessor
.IsTopLevelInSchema
= true; // false
137 accessor
.Name
= typeName
.Name
;
138 accessor
.Namespace
= typeName
.Namespace
;
139 accessor
.Mapping
= typeMapping
;
141 if (typeMapping
is SpecialMapping
&& ((SpecialMapping
)typeMapping
).NamedAny
)
143 accessor
.IsNullable
= typeMapping
.TypeDesc
.IsNullable
;
144 accessor
.Form
= XmlSchemaForm
.Qualified
;
146 if (accessor
.Mapping
is StructMapping
) {
147 MakeDerived((StructMapping
)accessor
.Mapping
, baseType
, baseTypeCanBeIndirect
);
149 else if (baseType
!= null) {
150 if (accessor
.Mapping
is ArrayMapping
) {
151 // in the case of the ArrayMapping we can use the top-level StructMapping, because it does not have base base type
152 accessor
.Mapping
= ((ArrayMapping
)accessor
.Mapping
).TopLevelMapping
;
153 MakeDerived((StructMapping
)accessor
.Mapping
, baseType
, baseTypeCanBeIndirect
);
156 // Type '{0}' from namespace '{1}' is not a complex type and cannot be used as a {2}.
157 throw new InvalidOperationException(Res
.GetString(Res
.XmlBadBaseType
, typeName
.Name
, typeName
.Namespace
, baseType
.FullName
));
160 return new XmlTypeMapping(Scope
, accessor
);
163 /// <include file='doc\XmlSchemaImporter.uex' path='docs/doc[@for="XmlSchemaImporter.ImportTypeMapping"]/*' />
165 /// <para>[To be supplied.]</para>
167 public XmlTypeMapping
ImportTypeMapping(XmlQualifiedName name
) {
168 return ImportDerivedTypeMapping(name
, null);
171 /// <include file='doc\XmlSchemaImporter.uex' path='docs/doc[@for="XmlSchemaImporter.ImportMembersMapping"]/*' />
173 /// <para>[To be supplied.]</para>
175 public XmlMembersMapping
ImportMembersMapping(XmlQualifiedName name
) {
176 return new XmlMembersMapping(Scope
, ImportElement(name
, typeof(MembersMapping
), null), XmlMappingAccess
.Read
| XmlMappingAccess
.Write
);
179 /// <include file='doc\XmlSchemaImporter.uex' path='docs/doc[@for="XmlSchemaImporter.ImportAnyType"]/*' />
180 public XmlMembersMapping
ImportAnyType(XmlQualifiedName typeName
, string elementName
) {
181 TypeMapping typeMapping
= ImportType(typeName
, typeof(MembersMapping
), null, TypeFlags
.CanBeElementValue
, true);
182 MembersMapping mapping
= typeMapping
as MembersMapping
;
184 if (mapping
== null) {
185 XmlSchemaComplexType type
= new XmlSchemaComplexType();
186 XmlSchemaSequence seq
= new XmlSchemaSequence();
188 XmlSchemaElement element
= new XmlSchemaElement();
189 element
.Name
= elementName
;
190 element
.SchemaTypeName
= typeName
;
191 seq
.Items
.Add(element
);
192 mapping
= ImportMembersType(type
, typeName
.Namespace
, elementName
);
195 if (mapping
.Members
.Length
!= 1 || !mapping
.Members
[0].Accessor
.Any
)
197 mapping
.Members
[0].Name
= elementName
;
198 ElementAccessor accessor
= new ElementAccessor();
199 accessor
.Name
= elementName
;
200 accessor
.Namespace
= typeName
.Namespace
;
201 accessor
.Mapping
= mapping
;
204 XmlSchemaObject xso
= Schemas
.SchemaSet
.GlobalTypes
[typeName
];
206 XmlSchema schema
= xso
.Parent
as XmlSchema
;
207 if (schema
!= null) {
208 accessor
.Form
= schema
.ElementFormDefault
== XmlSchemaForm
.None
? XmlSchemaForm
.Unqualified
: schema
.ElementFormDefault
;
211 XmlMembersMapping members
= new XmlMembersMapping(Scope
, accessor
, XmlMappingAccess
.Read
| XmlMappingAccess
.Write
);
215 /// <include file='doc\XmlSchemaImporter.uex' path='docs/doc[@for="XmlSchemaImporter.ImportMembersMapping1"]/*' />
217 /// <para>[To be supplied.]</para>
219 public XmlMembersMapping
ImportMembersMapping(XmlQualifiedName
[] names
) {
220 return ImportMembersMapping(names
, null, false);
223 /// <include file='doc\XmlSchemaImporter.uex' path='docs/doc[@for="XmlSchemaImporter.ImportMembersMapping2"]/*' />
225 /// <para>[To be supplied.]</para>
227 public XmlMembersMapping
ImportMembersMapping(XmlQualifiedName
[] names
, Type baseType
, bool baseTypeCanBeIndirect
) {
228 CodeIdentifiers memberScope
= new CodeIdentifiers();
229 memberScope
.UseCamelCasing
= true;
230 MemberMapping
[] members
= new MemberMapping
[names
.Length
];
231 for (int i
= 0; i
< names
.Length
; i
++) {
232 XmlQualifiedName name
= names
[i
];
233 ElementAccessor accessor
= ImportElement(name
, typeof(TypeMapping
), baseType
);
234 if (baseType
!= null && accessor
.Mapping
is StructMapping
)
235 MakeDerived((StructMapping
)accessor
.Mapping
, baseType
, baseTypeCanBeIndirect
);
237 MemberMapping member
= new MemberMapping();
238 member
.Name
= CodeIdentifier
.MakeValid(Accessor
.UnescapeName(accessor
.Name
));
239 member
.Name
= memberScope
.AddUnique(member
.Name
, member
);
240 member
.TypeDesc
= accessor
.Mapping
.TypeDesc
;
241 member
.Elements
= new ElementAccessor
[] { accessor }
;
244 MembersMapping mapping
= new MembersMapping();
245 mapping
.HasWrapperElement
= false;
246 mapping
.TypeDesc
= Scope
.GetTypeDesc(typeof(object[]));
247 mapping
.Members
= members
;
248 ElementAccessor element
= new ElementAccessor();
249 element
.Mapping
= mapping
;
250 return new XmlMembersMapping(Scope
, element
, XmlMappingAccess
.Read
| XmlMappingAccess
.Write
);
253 public XmlMembersMapping
ImportMembersMapping(string name
, string ns
, SoapSchemaMember
[] members
) {
254 XmlSchemaComplexType type
= new XmlSchemaComplexType();
255 XmlSchemaSequence seq
= new XmlSchemaSequence();
257 foreach (SoapSchemaMember member
in members
) {
258 XmlSchemaElement element
= new XmlSchemaElement();
259 element
.Name
= member
.MemberName
;
260 element
.SchemaTypeName
= member
.MemberType
;
261 seq
.Items
.Add(element
);
263 MembersMapping mapping
= ImportMembersType(type
, null, name
);
265 ElementAccessor accessor
= new ElementAccessor();
266 accessor
.Name
= Accessor
.EscapeName(name
);
267 accessor
.Namespace
= ns
;
268 accessor
.Mapping
= mapping
;
269 accessor
.IsNullable
= false;
270 accessor
.Form
= XmlSchemaForm
.Qualified
;
271 return new XmlMembersMapping(Scope
, accessor
, XmlMappingAccess
.Read
| XmlMappingAccess
.Write
);
274 ElementAccessor
ImportElement(XmlQualifiedName name
, Type desiredMappingType
, Type baseType
) {
275 XmlSchemaElement element
= FindElement(name
);
276 ElementAccessor accessor
= (ElementAccessor
)ImportedElements
[element
];
277 if (accessor
!= null) return accessor
;
278 accessor
= ImportElement(element
, string.Empty
, desiredMappingType
, baseType
, name
.Namespace
, true);
279 ElementAccessor existing
= (ElementAccessor
)ImportedElements
[element
];
280 if (existing
!= null) {
283 ImportedElements
.Add(element
, accessor
);
287 ElementAccessor
ImportElement(XmlSchemaElement element
, string identifier
, Type desiredMappingType
, Type baseType
, string ns
, bool topLevelElement
) {
288 if (!element
.RefName
.IsEmpty
) {
289 // we cannot re-use the accessor for the element refs
290 ElementAccessor topAccessor
= ImportElement(element
.RefName
, desiredMappingType
, baseType
);
291 if (element
.IsMultipleOccurrence
&& topAccessor
.Mapping
is ArrayMapping
) {
292 ElementAccessor refAccessor
= topAccessor
.Clone();
293 refAccessor
.IsTopLevelInSchema
= false;
294 refAccessor
.Mapping
.ReferencedByElement
= true;
300 if (element
.Name
.Length
== 0) {
301 XmlQualifiedName parentType
= XmlSchemas
.GetParentName(element
);
302 throw new InvalidOperationException(Res
.GetString(Res
.XmlElementHasNoName
, parentType
.Name
, parentType
.Namespace
));
304 string unescapedName
= Accessor
.UnescapeName(element
.Name
);
305 if (identifier
.Length
== 0)
306 identifier
= CodeIdentifier
.MakeValid(unescapedName
);
308 identifier
+= CodeIdentifier
.MakePascal(unescapedName
);
309 TypeMapping mapping
= ImportElementType(element
, identifier
, desiredMappingType
, baseType
, ns
);
310 ElementAccessor accessor
= new ElementAccessor();
311 accessor
.IsTopLevelInSchema
= element
.Parent
is XmlSchema
;
312 accessor
.Name
= element
.Name
;
313 accessor
.Namespace
= ns
;
314 accessor
.Mapping
= mapping
;
315 accessor
.IsOptional
= element
.MinOccurs
== 0m
;
317 if (element
.DefaultValue
!= null) {
318 accessor
.Default
= element
.DefaultValue
;
320 else if (element
.FixedValue
!= null) {
321 accessor
.Default
= element
.FixedValue
;
322 accessor
.IsFixed
= true;
325 if (mapping
is SpecialMapping
&& ((SpecialMapping
)mapping
).NamedAny
)
327 accessor
.IsNullable
= element
.IsNillable
;
328 if (topLevelElement
) {
329 accessor
.Form
= XmlSchemaForm
.Qualified
;
332 accessor
.Form
= ElementForm(ns
, element
);
337 TypeMapping
ImportElementType(XmlSchemaElement element
, string identifier
, Type desiredMappingType
, Type baseType
, string ns
) {
339 if (!element
.SchemaTypeName
.IsEmpty
) {
340 mapping
= ImportType(element
.SchemaTypeName
, desiredMappingType
, baseType
, TypeFlags
.CanBeElementValue
, false);
341 if (!mapping
.ReferencedByElement
) {
342 object type
= FindType(element
.SchemaTypeName
, TypeFlags
.CanBeElementValue
);
343 XmlSchemaObject parent
= element
;
344 while (parent
.Parent
!= null && type
!= parent
) {
345 parent
= parent
.Parent
;
347 mapping
.ReferencedByElement
= (type
!= parent
);
350 else if (element
.SchemaType
!= null) {
351 if (element
.SchemaType
is XmlSchemaComplexType
)
352 mapping
= ImportType((XmlSchemaComplexType
)element
.SchemaType
, ns
, identifier
, desiredMappingType
, baseType
, TypeFlags
.CanBeElementValue
);
354 mapping
= ImportDataType((XmlSchemaSimpleType
)element
.SchemaType
, ns
, identifier
, baseType
, TypeFlags
.CanBeElementValue
| TypeFlags
.CanBeAttributeValue
| TypeFlags
.CanBeTextValue
, false);
355 mapping
.ReferencedByElement
= true;
357 else if (!element
.SubstitutionGroup
.IsEmpty
)
358 mapping
= ImportElementType(FindElement(element
.SubstitutionGroup
), identifier
, desiredMappingType
, baseType
, ns
);
360 if (desiredMappingType
== typeof(MembersMapping
)) {
361 mapping
= ImportMembersType(new XmlSchemaType(), ns
, identifier
);
364 mapping
= ImportRootMapping();
367 if (!(desiredMappingType
.IsAssignableFrom(mapping
.GetType())))
368 throw new InvalidOperationException(Res
.GetString(Res
.XmlElementImportedTwice
, element
.Name
, ns
, mapping
.GetType().Name
, desiredMappingType
.Name
));
370 // let the extensions to run
371 if (!mapping
.TypeDesc
.IsMappedType
) {
372 RunSchemaExtensions(mapping
, element
.SchemaTypeName
, element
.SchemaType
, element
, TypeFlags
.CanBeElementValue
);
377 void RunSchemaExtensions(TypeMapping mapping
, XmlQualifiedName qname
, XmlSchemaType type
, XmlSchemaObject context
, TypeFlags flags
) {
378 string typeName
= null;
379 SchemaImporterExtension typeOwner
= null;
380 CodeCompileUnit compileUnit
= new CodeCompileUnit();
381 CodeNamespace mainNamespace
= new CodeNamespace();
382 compileUnit
.Namespaces
.Add(mainNamespace
);
384 if (!qname
.IsEmpty
) {
385 typeName
= FindExtendedType(qname
.Name
, qname
.Namespace
, context
, compileUnit
, mainNamespace
, out typeOwner
);
387 else if (type
!= null) {
388 typeName
= FindExtendedType(type
, context
, compileUnit
, mainNamespace
, out typeOwner
);
390 else if (context
is XmlSchemaAny
) {
391 typeName
= FindExtendedAnyElement((XmlSchemaAny
)context
, ((flags
& TypeFlags
.CanBeTextValue
) != 0), compileUnit
, mainNamespace
, out typeOwner
);
394 if (typeName
!= null && typeName
.Length
> 0) {
395 // check if the type name is valid
396 typeName
= typeName
.Replace('+', '.');
398 CodeGenerator
.ValidateIdentifiers(new CodeTypeReference(typeName
));
400 catch (ArgumentException
) {
402 throw new InvalidOperationException(Res
.GetString(Res
.XmlImporterExtensionBadLocalTypeName
, typeOwner
.GetType().FullName
, typeName
));
405 throw new InvalidOperationException(Res
.GetString(Res
.XmlImporterExtensionBadTypeName
, typeOwner
.GetType().FullName
, qname
.Name
, qname
.Namespace
, typeName
));
411 foreach (CodeNamespace ns
in compileUnit
.Namespaces
) {
412 CodeGenerator
.ValidateIdentifiers(ns
);
416 mapping
.TypeDesc
= mapping
.TypeDesc
.CreateMappedTypeDesc(new MappedTypeDesc(typeName
, qname
.Name
, qname
.Namespace
, type
, context
, typeOwner
, mainNamespace
, compileUnit
.ReferencedAssemblies
));
418 if (mapping
is ArrayMapping
) {
419 TypeMapping top
= ((ArrayMapping
)mapping
).TopLevelMapping
;
420 top
.TypeName
= mapping
.TypeName
;
421 top
.TypeDesc
= mapping
.TypeDesc
;
424 mapping
.TypeName
= qname
.IsEmpty
? null : typeName
;
428 string GenerateUniqueTypeName(string desiredName
, string ns
) {
431 string typeName
= desiredName
;
433 XmlQualifiedName qname
= new XmlQualifiedName(typeName
, ns
);
435 object type
= Schemas
.Find(qname
, typeof(XmlSchemaType
));
439 typeName
= desiredName
+ i
.ToString(CultureInfo
.InvariantCulture
);
442 typeName
= CodeIdentifier
.MakeValid(typeName
);
443 return TypeIdentifiers
.AddUnique(typeName
, typeName
);
446 [PermissionSet(SecurityAction
.InheritanceDemand
, Name
="FullTrust")]
447 internal override void ImportDerivedTypes(XmlQualifiedName baseName
) {
448 foreach (XmlSchema schema
in Schemas
) {
449 if (Schemas
.IsReference(schema
)) continue;
450 if (XmlSchemas
.IsDataSet(schema
)) continue;
451 XmlSchemas
.Preprocess(schema
);
452 foreach (object item
in schema
.SchemaTypes
.Values
) {
453 if (item
is XmlSchemaType
) {
454 XmlSchemaType type
= (XmlSchemaType
)item
;
455 if (type
.DerivedFrom
== baseName
&& TypesInUse
[type
.Name
, schema
.TargetNamespace
] == null) {
456 ImportType(type
.QualifiedName
, typeof(TypeMapping
), null, TypeFlags
.CanBeElementValue
, false);
463 TypeMapping
ImportType(XmlQualifiedName name
, Type desiredMappingType
, Type baseType
, TypeFlags flags
, bool addref
) {
464 if (name
.Name
== Soap
.UrType
&& name
.Namespace
== XmlSchema
.Namespace
)
465 return ImportRootMapping();
466 object type
= FindType(name
, flags
);
468 TypeMapping mapping
= (TypeMapping
)ImportedMappings
[type
];
469 if (mapping
!= null && desiredMappingType
.IsAssignableFrom(mapping
.GetType()))
473 AddReference(name
, TypesInUse
, Res
.XmlCircularTypeReference
);
474 if (type
is XmlSchemaComplexType
) {
475 mapping
= ImportType((XmlSchemaComplexType
)type
, name
.Namespace
, name
.Name
, desiredMappingType
, baseType
, flags
);
477 else if (type
is XmlSchemaSimpleType
)
478 mapping
= ImportDataType((XmlSchemaSimpleType
)type
, name
.Namespace
, name
.Name
, baseType
, flags
, false);
480 throw new InvalidOperationException(Res
.GetString(Res
.XmlInternalError
));
482 if (addref
&& name
.Namespace
!= XmlSchema
.Namespace
)
483 RemoveReference(name
, TypesInUse
);
488 TypeMapping
ImportType(XmlSchemaComplexType type
, string typeNs
, string identifier
, Type desiredMappingType
, Type baseType
, TypeFlags flags
) {
489 if (type
.Redefined
!= null) {
490 // we do not support redefine in the current version
491 throw new NotSupportedException(Res
.GetString(Res
.XmlUnsupportedRedefine
, type
.Name
, typeNs
));
493 if (desiredMappingType
== typeof(TypeMapping
)) {
494 TypeMapping mapping
= null;
496 if (baseType
== null) {
497 if ((mapping
= ImportArrayMapping(type
, identifier
, typeNs
, false)) == null) {
498 mapping
= ImportAnyMapping(type
, identifier
, typeNs
, false);
501 if (mapping
== null) {
502 mapping
= ImportStructType(type
, typeNs
, identifier
, baseType
, false);
504 if (mapping
!= null && type
.Name
!= null && type
.Name
.Length
!= 0)
505 ImportDerivedTypes(new XmlQualifiedName(identifier
, typeNs
));
509 else if (desiredMappingType
== typeof(MembersMapping
))
510 return ImportMembersType(type
, typeNs
, identifier
);
512 throw new ArgumentException(Res
.GetString(Res
.XmlInternalError
), "desiredMappingType");
515 MembersMapping
ImportMembersType(XmlSchemaType type
, string typeNs
, string identifier
) {
516 if (!type
.DerivedFrom
.IsEmpty
) throw new InvalidOperationException(Res
.GetString(Res
.XmlMembersDeriveError
));
517 CodeIdentifiers memberScope
= new CodeIdentifiers();
518 memberScope
.UseCamelCasing
= true;
519 bool needExplicitOrder
= false;
520 MemberMapping
[] members
= ImportTypeMembers(type
, typeNs
, identifier
, memberScope
, new CodeIdentifiers(), new NameTable(), ref needExplicitOrder
, false, false);
521 MembersMapping mappings
= new MembersMapping();
522 mappings
.HasWrapperElement
= true;
523 mappings
.TypeDesc
= Scope
.GetTypeDesc(typeof(object[]));
524 mappings
.Members
= members
;
528 StructMapping
ImportStructType(XmlSchemaType type
, string typeNs
, string identifier
, Type baseType
, bool arrayLike
) {
529 TypeDesc baseTypeDesc
= null;
530 TypeMapping baseMapping
= null;
532 bool isRootType
= false;
533 if (!type
.DerivedFrom
.IsEmpty
) {
534 baseMapping
= ImportType(type
.DerivedFrom
, typeof(TypeMapping
), null, TypeFlags
.CanBeElementValue
| TypeFlags
.CanBeTextValue
, false);
536 if (baseMapping
is StructMapping
)
537 baseTypeDesc
= ((StructMapping
)baseMapping
).TypeDesc
;
538 else if (baseMapping
is ArrayMapping
) {
539 baseMapping
= ((ArrayMapping
)baseMapping
).TopLevelMapping
;
540 if (baseMapping
!= null) {
541 baseMapping
.ReferencedByTopLevelElement
= false;
542 baseMapping
.ReferencedByElement
= true;
543 baseTypeDesc
= baseMapping
.TypeDesc
;
549 if (baseTypeDesc
== null && baseType
!= null)
550 baseTypeDesc
= Scope
.GetTypeDesc(baseType
);
551 if (baseMapping
== null)
553 baseMapping
= GetRootMapping();
556 Mapping previousMapping
= (Mapping
)ImportedMappings
[type
];
557 if (previousMapping
!= null) {
558 if (previousMapping
is StructMapping
) {
559 return (StructMapping
)previousMapping
;
561 else if (arrayLike
&& previousMapping
is ArrayMapping
){
562 ArrayMapping arrayMapping
= (ArrayMapping
)previousMapping
;
563 if (arrayMapping
.TopLevelMapping
!= null) {
564 return arrayMapping
.TopLevelMapping
;
568 throw new InvalidOperationException(Res
.GetString(Res
.XmlTypeUsedTwice
, type
.QualifiedName
.Name
, type
.QualifiedName
.Namespace
));
571 StructMapping structMapping
= new StructMapping();
572 structMapping
.IsReference
= Schemas
.IsReference(type
);
573 TypeFlags flags
= TypeFlags
.Reference
;
574 if (type
is XmlSchemaComplexType
) {
575 if (((XmlSchemaComplexType
)type
).IsAbstract
)
576 flags
|= TypeFlags
.Abstract
;
579 identifier
= Accessor
.UnescapeName(identifier
);
580 string typeName
= type
.Name
== null || type
.Name
.Length
== 0 ? GenerateUniqueTypeName(identifier
, typeNs
) : GenerateUniqueTypeName(identifier
);
581 structMapping
.TypeDesc
= new TypeDesc(typeName
, typeName
, TypeKind
.Struct
, baseTypeDesc
, flags
);
582 structMapping
.Namespace
= typeNs
;
583 structMapping
.TypeName
= type
.Name
== null || type
.Name
.Length
== 0 ? null : identifier
;
584 structMapping
.BaseMapping
= (StructMapping
)baseMapping
;
586 ImportedMappings
.Add(type
, structMapping
);
587 CodeIdentifiers members
= new CodeIdentifiers();
588 CodeIdentifiers membersScope
= structMapping
.BaseMapping
.Scope
.Clone();
589 members
.AddReserved(typeName
);
590 membersScope
.AddReserved(typeName
);
591 AddReservedIdentifiersForDataBinding(members
);
593 AddReservedIdentifiersForDataBinding(membersScope
);
594 bool needExplicitOrder
= false;
595 structMapping
.Members
= ImportTypeMembers(type
, typeNs
, identifier
, members
, membersScope
, structMapping
, ref needExplicitOrder
, true, true);
597 if (!IsAllGroup(type
)) {
598 if (needExplicitOrder
&& !GenerateOrder
) {
599 structMapping
.SetSequence();
601 else if (GenerateOrder
) {
602 structMapping
.IsSequence
= true;
606 for (int i
= 0; i
< structMapping
.Members
.Length
; i
++) {
607 StructMapping declaringMapping
;
608 MemberMapping baseMember
= ((StructMapping
)baseMapping
).FindDeclaringMapping(structMapping
.Members
[i
], out declaringMapping
, structMapping
.TypeName
);
609 if (baseMember
!= null && baseMember
.TypeDesc
!= structMapping
.Members
[i
].TypeDesc
)
610 throw new InvalidOperationException(Res
.GetString(Res
.XmlIllegalOverride
, type
.Name
, baseMember
.Name
, baseMember
.TypeDesc
.FullName
, structMapping
.Members
[i
].TypeDesc
.FullName
, declaringMapping
.TypeDesc
.FullName
));
612 structMapping
.Scope
= membersScope
;
613 Scope
.AddTypeMapping(structMapping
);
614 return structMapping
;
617 bool IsAllGroup(XmlSchemaType type
) {
618 TypeItems items
= GetTypeItems(type
);
619 return (items
.Particle
!= null) && (items
.Particle
is XmlSchemaAll
);
622 StructMapping
ImportStructDataType(XmlSchemaSimpleType dataType
, string typeNs
, string identifier
, Type baseType
) {
623 identifier
= Accessor
.UnescapeName(identifier
);
624 string typeName
= GenerateUniqueTypeName(identifier
);
625 StructMapping structMapping
= new StructMapping();
626 structMapping
.IsReference
= Schemas
.IsReference(dataType
);
627 TypeFlags flags
= TypeFlags
.Reference
;
628 TypeDesc baseTypeDesc
= Scope
.GetTypeDesc(baseType
);
629 structMapping
.TypeDesc
= new TypeDesc(typeName
, typeName
, TypeKind
.Struct
, baseTypeDesc
, flags
);
630 structMapping
.Namespace
= typeNs
;
631 structMapping
.TypeName
= identifier
;
632 CodeIdentifiers members
= new CodeIdentifiers();
633 members
.AddReserved(typeName
);
634 AddReservedIdentifiersForDataBinding(members
);
635 ImportTextMember(members
, new CodeIdentifiers(), null);
636 structMapping
.Members
= (MemberMapping
[])members
.ToArray(typeof(MemberMapping
));
637 structMapping
.Scope
= members
;
638 Scope
.AddTypeMapping(structMapping
);
639 return structMapping
;
643 internal XmlSchemaObjectCollection Attributes
= new XmlSchemaObjectCollection();
644 internal XmlSchemaAnyAttribute AnyAttribute
;
645 internal XmlSchemaGroupBase Particle
;
646 internal XmlQualifiedName baseSimpleType
;
647 internal bool IsUnbounded
;
650 MemberMapping
[] ImportTypeMembers(XmlSchemaType type
, string typeNs
, string identifier
, CodeIdentifiers members
, CodeIdentifiers membersScope
, INameScope elementsScope
, ref bool needExplicitOrder
, bool order
, bool allowUnboundedElements
) {
651 TypeItems items
= GetTypeItems(type
);
652 bool mixed
= IsMixed(type
);
655 // check if we can transfer the attribute to the base class
656 XmlSchemaType t
= type
;
657 while (!t
.DerivedFrom
.IsEmpty
) {
658 t
= FindType(t
.DerivedFrom
, TypeFlags
.CanBeElementValue
| TypeFlags
.CanBeTextValue
);
660 // keep the mixed attribute on the base class
667 if (items
.Particle
!= null) {
668 ImportGroup(items
.Particle
, identifier
, members
, membersScope
, elementsScope
, typeNs
, mixed
, ref needExplicitOrder
, order
, items
.IsUnbounded
, allowUnboundedElements
);
670 for (int i
= 0; i
< items
.Attributes
.Count
; i
++) {
671 object item
= items
.Attributes
[i
];
672 if (item
is XmlSchemaAttribute
) {
673 ImportAttributeMember((XmlSchemaAttribute
)item
, identifier
, members
, membersScope
, typeNs
);
675 else if (item
is XmlSchemaAttributeGroupRef
) {
676 XmlQualifiedName groupName
= ((XmlSchemaAttributeGroupRef
)item
).RefName
;
677 ImportAttributeGroupMembers(FindAttributeGroup(groupName
), identifier
, members
, membersScope
, groupName
.Namespace
);
680 if (items
.AnyAttribute
!= null) {
681 ImportAnyAttributeMember(items
.AnyAttribute
, members
, membersScope
);
684 if (items
.baseSimpleType
!= null || (items
.Particle
== null && mixed
)) {
685 ImportTextMember(members
, membersScope
, mixed
? null : items
.baseSimpleType
);
688 ImportXmlnsDeclarationsMember(type
, members
, membersScope
);
689 MemberMapping
[] typeMembers
= (MemberMapping
[])members
.ToArray(typeof(MemberMapping
));
693 internal static bool IsMixed(XmlSchemaType type
) {
694 if (!(type
is XmlSchemaComplexType
))
697 XmlSchemaComplexType ct
= (XmlSchemaComplexType
)type
;
698 bool mixed
= ct
.IsMixed
;
700 // check the mixed attribute on the complexContent
702 if (ct
.ContentModel
!= null && ct
.ContentModel
is XmlSchemaComplexContent
) {
703 mixed
= ((XmlSchemaComplexContent
)ct
.ContentModel
).IsMixed
;
709 TypeItems
GetTypeItems(XmlSchemaType type
) {
710 TypeItems items
= new TypeItems();
711 if (type
is XmlSchemaComplexType
) {
712 XmlSchemaParticle particle
= null;
713 XmlSchemaComplexType ct
= (XmlSchemaComplexType
)type
;
714 if (ct
.ContentModel
!= null) {
715 XmlSchemaContent content
= ct
.ContentModel
.Content
;
716 if (content
is XmlSchemaComplexContentExtension
) {
717 XmlSchemaComplexContentExtension extension
= (XmlSchemaComplexContentExtension
)content
;
718 items
.Attributes
= extension
.Attributes
;
719 items
.AnyAttribute
= extension
.AnyAttribute
;
720 particle
= extension
.Particle
;
722 else if (content
is XmlSchemaSimpleContentExtension
) {
723 XmlSchemaSimpleContentExtension extension
= (XmlSchemaSimpleContentExtension
)content
;
724 items
.Attributes
= extension
.Attributes
;
725 items
.AnyAttribute
= extension
.AnyAttribute
;
726 items
.baseSimpleType
= extension
.BaseTypeName
;
730 items
.Attributes
= ct
.Attributes
;
731 items
.AnyAttribute
= ct
.AnyAttribute
;
732 particle
= ct
.Particle
;
734 if (particle
is XmlSchemaGroupRef
) {
735 XmlSchemaGroupRef refGroup
= (XmlSchemaGroupRef
)particle
;
736 items
.Particle
= FindGroup(refGroup
.RefName
).Particle
;
737 items
.IsUnbounded
= particle
.IsMultipleOccurrence
;
739 else if (particle
is XmlSchemaGroupBase
) {
740 items
.Particle
= (XmlSchemaGroupBase
)particle
;
741 items
.IsUnbounded
= particle
.IsMultipleOccurrence
;
747 void ImportGroup(XmlSchemaGroupBase
group, string identifier
, CodeIdentifiers members
, CodeIdentifiers membersScope
, INameScope elementsScope
, string ns
, bool mixed
, ref bool needExplicitOrder
, bool allowDuplicates
, bool groupRepeats
, bool allowUnboundedElements
) {
748 if (group is XmlSchemaChoice
)
749 ImportChoiceGroup((XmlSchemaChoice
)group, identifier
, members
, membersScope
, elementsScope
, ns
, groupRepeats
, ref needExplicitOrder
, allowDuplicates
);
751 ImportGroupMembers(group, identifier
, members
, membersScope
, elementsScope
, ns
, groupRepeats
, ref mixed
, ref needExplicitOrder
, allowDuplicates
, allowUnboundedElements
);
754 ImportTextMember(members
, membersScope
, null);
758 MemberMapping
ImportChoiceGroup(XmlSchemaGroupBase
group, string identifier
, CodeIdentifiers members
, CodeIdentifiers membersScope
, INameScope elementsScope
, string ns
, bool groupRepeats
, ref bool needExplicitOrder
, bool allowDuplicates
) {
759 NameTable choiceElements
= new NameTable();
760 if (GatherGroupChoices(group, choiceElements
, identifier
, ns
, ref needExplicitOrder
, allowDuplicates
))
762 MemberMapping member
= new MemberMapping();
763 member
.Elements
= (ElementAccessor
[])choiceElements
.ToArray(typeof(ElementAccessor
));
764 Array
.Sort(member
.Elements
, new ElementComparer());
766 AddScopeElements(elementsScope
, member
.Elements
, ref needExplicitOrder
, allowDuplicates
);
767 bool duplicateTypes
= false;
768 bool nullableMismatch
= false;
769 Hashtable uniqueTypeDescs
= new Hashtable(member
.Elements
.Length
);
771 for (int i
= 0; i
< member
.Elements
.Length
; i
++) {
772 ElementAccessor element
= member
.Elements
[i
];
773 string tdFullName
= element
.Mapping
.TypeDesc
.FullName
;
774 object val
= uniqueTypeDescs
[tdFullName
];
776 duplicateTypes
= true;
777 ElementAccessor existingElement
= (ElementAccessor
)val
;
778 if (!nullableMismatch
&& existingElement
.IsNullable
!= element
.IsNullable
)
779 nullableMismatch
= true;
782 uniqueTypeDescs
.Add(tdFullName
, element
);
785 ArrayMapping arrayMapping
= element
.Mapping
as ArrayMapping
;
786 if (arrayMapping
!= null) {
787 if (IsNeedXmlSerializationAttributes(arrayMapping
)) {
788 // we cannot use ArrayMapping in choice if additional custom
789 // serialization attributes are needed to serialize it
790 element
.Mapping
= arrayMapping
.TopLevelMapping
;
791 element
.Mapping
.ReferencedByTopLevelElement
= false;
792 element
.Mapping
.ReferencedByElement
= true;
796 if (nullableMismatch
)
797 member
.TypeDesc
= Scope
.GetTypeDesc(typeof(object));
800 TypeDesc
[] typeDescs
= new TypeDesc
[uniqueTypeDescs
.Count
];
801 IEnumerator enumerator
= uniqueTypeDescs
.Values
.GetEnumerator();
802 for (int i
= 0; i
< typeDescs
.Length
; i
++)
804 if (!enumerator
.MoveNext())
806 typeDescs
[i
] = ((ElementAccessor
)enumerator
.Current
).Mapping
.TypeDesc
;
808 member
.TypeDesc
= TypeDesc
.FindCommonBaseTypeDesc(typeDescs
);
809 if (member
.TypeDesc
== null) member
.TypeDesc
= Scope
.GetTypeDesc(typeof(object));
813 member
.TypeDesc
= member
.TypeDesc
.CreateArrayTypeDesc();
815 if (membersScope
!= null) {
816 member
.Name
= membersScope
.AddUnique(groupRepeats
? "Items" : "Item", member
);
817 if (members
!= null) {
818 members
.Add(member
.Name
, member
);
822 if (duplicateTypes
) {
823 member
.ChoiceIdentifier
= new ChoiceIdentifierAccessor();
824 member
.ChoiceIdentifier
.MemberName
= member
.Name
+ "ElementName";
825 // we need to create the EnumMapping to store all of the element names
826 member
.ChoiceIdentifier
.Mapping
= ImportEnumeratedChoice(member
.Elements
, ns
, member
.Name
+ "ChoiceType");
827 member
.ChoiceIdentifier
.MemberIds
= new string[member
.Elements
.Length
];
828 ConstantMapping
[] constants
= ((EnumMapping
)member
.ChoiceIdentifier
.Mapping
).Constants
;
829 for (int i
= 0; i
< member
.Elements
.Length
; i
++) {
830 member
.ChoiceIdentifier
.MemberIds
[i
] = constants
[i
].Name
;
832 MemberMapping choiceIdentifier
= new MemberMapping();
833 choiceIdentifier
.Ignore
= true;
834 choiceIdentifier
.Name
= member
.ChoiceIdentifier
.MemberName
;
836 choiceIdentifier
.TypeDesc
= member
.ChoiceIdentifier
.Mapping
.TypeDesc
.CreateArrayTypeDesc();
839 choiceIdentifier
.TypeDesc
= member
.ChoiceIdentifier
.Mapping
.TypeDesc
;
842 // create element accessor for the choiceIdentifier
844 ElementAccessor choiceAccessor
= new ElementAccessor();
845 choiceAccessor
.Name
= choiceIdentifier
.Name
;
846 choiceAccessor
.Namespace
= ns
;
847 choiceAccessor
.Mapping
= member
.ChoiceIdentifier
.Mapping
;
848 choiceIdentifier
.Elements
= new ElementAccessor
[] {choiceAccessor}
;
850 if (membersScope
!= null) {
851 choiceAccessor
.Name
= choiceIdentifier
.Name
= member
.ChoiceIdentifier
.MemberName
= membersScope
.AddUnique(member
.ChoiceIdentifier
.MemberName
, choiceIdentifier
);
852 if (members
!= null) {
853 members
.Add(choiceAccessor
.Name
, choiceIdentifier
);
860 bool IsNeedXmlSerializationAttributes(ArrayMapping arrayMapping
) {
861 if (arrayMapping
.Elements
.Length
!= 1)
864 ElementAccessor item
= arrayMapping
.Elements
[0];
865 TypeMapping itemMapping
= item
.Mapping
;
867 if (item
.Name
!= itemMapping
.DefaultElementName
)
870 if (item
.Form
!= XmlSchemaForm
.None
&& item
.Form
!= XmlSchemaExporter
.elementFormDefault
)
873 if (item
.Mapping
.TypeDesc
!= null)
875 if (item
.IsNullable
!= item
.Mapping
.TypeDesc
.IsNullable
)
878 if (item
.Mapping
.TypeDesc
.IsAmbiguousDataType
)
884 bool GatherGroupChoices(XmlSchemaGroup
group, NameTable choiceElements
, string identifier
, string ns
, ref bool needExplicitOrder
, bool allowDuplicates
) {
885 return GatherGroupChoices(group.Particle
, choiceElements
, identifier
, ns
, ref needExplicitOrder
, allowDuplicates
);
888 bool GatherGroupChoices(XmlSchemaParticle particle
, NameTable choiceElements
, string identifier
, string ns
, ref bool needExplicitOrder
, bool allowDuplicates
) {
889 if (particle
is XmlSchemaGroupRef
) {
890 XmlSchemaGroupRef refGroup
= (XmlSchemaGroupRef
)particle
;
891 if (!refGroup
.RefName
.IsEmpty
) {
892 AddReference(refGroup
.RefName
, GroupsInUse
, Res
.XmlCircularGroupReference
);
893 if (GatherGroupChoices(FindGroup(refGroup
.RefName
), choiceElements
, identifier
, refGroup
.RefName
.Namespace
, ref needExplicitOrder
, allowDuplicates
)) {
894 RemoveReference(refGroup
.RefName
, GroupsInUse
);
897 RemoveReference(refGroup
.RefName
, GroupsInUse
);
900 else if (particle
is XmlSchemaGroupBase
) {
901 XmlSchemaGroupBase
group = (XmlSchemaGroupBase
)particle
;
902 bool groupRepeats
= group.IsMultipleOccurrence
;
903 XmlSchemaAny any
= null;
904 bool duplicateElements
= false;
905 for (int i
= 0; i
< group.Items
.Count
; i
++) {
906 object item
= group.Items
[i
];
907 if (item
is XmlSchemaGroupBase
|| item
is XmlSchemaGroupRef
) {
908 if (GatherGroupChoices((XmlSchemaParticle
)item
, choiceElements
, identifier
, ns
, ref needExplicitOrder
, allowDuplicates
))
911 else if (item
is XmlSchemaAny
) {
913 AddScopeElements(choiceElements
, ImportAny((XmlSchemaAny
)item
, true, ns
), ref duplicateElements
, allowDuplicates
);
916 any
= (XmlSchemaAny
)item
;
919 else if (item
is XmlSchemaElement
) {
920 XmlSchemaElement element
= (XmlSchemaElement
)item
;
921 XmlSchemaElement headElement
= GetTopLevelElement(element
);
922 if (headElement
!= null) {
923 XmlSchemaElement
[] elements
= GetEquivalentElements(headElement
);
924 for (int j
= 0; j
< elements
.Length
; j
++) {
925 if (elements
[j
].IsMultipleOccurrence
) groupRepeats
= true;
926 AddScopeElement(choiceElements
, ImportElement(elements
[j
], identifier
, typeof(TypeMapping
), null, elements
[j
].QualifiedName
.Namespace
, true), ref duplicateElements
, allowDuplicates
);
929 if (element
.IsMultipleOccurrence
) groupRepeats
= true;
930 AddScopeElement(choiceElements
, ImportElement(element
, identifier
, typeof(TypeMapping
), null, element
.QualifiedName
.Namespace
, false), ref duplicateElements
, allowDuplicates
);
934 AddScopeElements(choiceElements
, ImportAny(any
, true, ns
), ref duplicateElements
, allowDuplicates
);
936 if (!groupRepeats
&& !(group is XmlSchemaChoice
) && group.Items
.Count
> 1) {
944 void AddScopeElement(INameScope scope
, ElementAccessor element
, ref bool duplicateElements
, bool allowDuplicates
) {
948 ElementAccessor scopeElement
= (ElementAccessor
)scope
[element
.Name
, element
.Namespace
];
949 if (scopeElement
!= null) {
950 if (!allowDuplicates
) {
951 throw new InvalidOperationException(Res
.GetString(Res
.XmlDuplicateElementInScope
, element
.Name
, element
.Namespace
));
953 if (scopeElement
.Mapping
.TypeDesc
!= element
.Mapping
.TypeDesc
) {
954 throw new InvalidOperationException(Res
.GetString(Res
.XmlDuplicateElementInScope1
, element
.Name
, element
.Namespace
));
956 duplicateElements
= true;
959 scope
[element
.Name
, element
.Namespace
] = element
;
963 void AddScopeElements(INameScope scope
, ElementAccessor
[] elements
, ref bool duplicateElements
, bool allowDuplicates
) {
964 for (int i
= 0; i
< elements
.Length
; i
++) {
965 AddScopeElement(scope
, elements
[i
], ref duplicateElements
, allowDuplicates
);
969 void ImportGroupMembers(XmlSchemaParticle particle
, string identifier
, CodeIdentifiers members
, CodeIdentifiers membersScope
, INameScope elementsScope
, string ns
, bool groupRepeats
, ref bool mixed
, ref bool needExplicitOrder
, bool allowDuplicates
, bool allowUnboundedElements
) {
971 if (particle
is XmlSchemaGroupRef
) {
972 XmlSchemaGroupRef refGroup
= (XmlSchemaGroupRef
)particle
;
973 if (!refGroup
.RefName
.IsEmpty
) {
974 AddReference(refGroup
.RefName
, GroupsInUse
, Res
.XmlCircularGroupReference
);
975 ImportGroupMembers(FindGroup(refGroup
.RefName
).Particle
, identifier
, members
, membersScope
, elementsScope
, refGroup
.RefName
.Namespace
, groupRepeats
| refGroup
.IsMultipleOccurrence
, ref mixed
, ref needExplicitOrder
, allowDuplicates
, allowUnboundedElements
);
976 RemoveReference(refGroup
.RefName
, GroupsInUse
);
979 else if (particle
is XmlSchemaGroupBase
) {
980 XmlSchemaGroupBase
group = (XmlSchemaGroupBase
)particle
;
982 if (group.IsMultipleOccurrence
)
985 if (GenerateOrder
&& groupRepeats
&& group.Items
.Count
> 1) {
986 ImportChoiceGroup(group, identifier
, members
, membersScope
, elementsScope
, ns
, groupRepeats
, ref needExplicitOrder
, allowDuplicates
);
989 for (int i
= 0; i
< group.Items
.Count
; i
++) {
990 object item
= group.Items
[i
];
991 if (item
is XmlSchemaChoice
)
992 ImportChoiceGroup((XmlSchemaGroupBase
)item
, identifier
, members
, membersScope
, elementsScope
, ns
, groupRepeats
, ref needExplicitOrder
, allowDuplicates
);
993 else if (item
is XmlSchemaElement
)
994 ImportElementMember((XmlSchemaElement
)item
, identifier
, members
, membersScope
, elementsScope
, ns
, groupRepeats
, ref needExplicitOrder
, allowDuplicates
, allowUnboundedElements
);
995 else if (item
is XmlSchemaAny
) {
996 ImportAnyMember((XmlSchemaAny
)item
, identifier
, members
, membersScope
, elementsScope
, ns
, ref mixed
, ref needExplicitOrder
, allowDuplicates
);
998 else if (item
is XmlSchemaParticle
) {
999 ImportGroupMembers((XmlSchemaParticle
)item
, identifier
, members
, membersScope
, elementsScope
, ns
, groupRepeats
, ref mixed
, ref needExplicitOrder
, allowDuplicates
, true);
1006 XmlSchemaElement
GetTopLevelElement(XmlSchemaElement element
) {
1007 if (!element
.RefName
.IsEmpty
)
1008 return FindElement(element
.RefName
);
1012 XmlSchemaElement
[] GetEquivalentElements(XmlSchemaElement element
) {
1013 ArrayList equivalentElements
= new ArrayList();
1015 foreach (XmlSchema schema
in Schemas
.SchemaSet
.Schemas()) {
1016 for (int j
= 0; j
< schema
.Items
.Count
; j
++) {
1017 object item
= schema
.Items
[j
];
1018 if (item
is XmlSchemaElement
) {
1019 XmlSchemaElement equivalentElement
= (XmlSchemaElement
)item
;
1020 if (!equivalentElement
.IsAbstract
&&
1021 equivalentElement
.SubstitutionGroup
.Namespace
== schema
.TargetNamespace
&&
1022 equivalentElement
.SubstitutionGroup
.Name
== element
.Name
) {
1023 equivalentElements
.Add(equivalentElement
);
1029 return (XmlSchemaElement
[])equivalentElements
.ToArray(typeof(XmlSchemaElement
));
1032 bool ImportSubstitutionGroupMember(XmlSchemaElement element
, string identifier
, CodeIdentifiers members
, CodeIdentifiers membersScope
, string ns
, bool repeats
, ref bool needExplicitOrder
, bool allowDuplicates
) {
1033 XmlSchemaElement
[] elements
= GetEquivalentElements(element
);
1034 if (elements
.Length
== 0)
1036 XmlSchemaChoice choice
= new XmlSchemaChoice();
1037 for (int i
= 0; i
< elements
.Length
; i
++)
1038 choice
.Items
.Add(elements
[i
]);
1039 if (!element
.IsAbstract
)
1040 choice
.Items
.Add(element
);
1041 if (identifier
.Length
== 0)
1042 identifier
= CodeIdentifier
.MakeValid(Accessor
.UnescapeName(element
.Name
));
1044 identifier
+= CodeIdentifier
.MakePascal(Accessor
.UnescapeName(element
.Name
));
1045 ImportChoiceGroup(choice
, identifier
, members
, membersScope
, null, ns
, repeats
, ref needExplicitOrder
, allowDuplicates
);
1050 void ImportTextMember(CodeIdentifiers members
, CodeIdentifiers membersScope
, XmlQualifiedName simpleContentType
) {
1051 TypeMapping mapping
;
1052 bool isMixed
= false;
1054 if (simpleContentType
!= null) {
1055 // allow to use all primitive types
1056 mapping
= ImportType(simpleContentType
, typeof(TypeMapping
), null, TypeFlags
.CanBeElementValue
| TypeFlags
.CanBeTextValue
, false);
1057 if (!(mapping
is PrimitiveMapping
|| mapping
.TypeDesc
.CanBeTextValue
)) {
1062 // this is a case of the mixed content type, just generate string typeDesc
1064 mapping
= GetDefaultMapping(TypeFlags
.CanBeElementValue
| TypeFlags
.CanBeTextValue
);
1067 TextAccessor accessor
= new TextAccessor();
1068 accessor
.Mapping
= mapping
;
1070 MemberMapping member
= new MemberMapping();
1071 member
.Elements
= new ElementAccessor
[0];
1072 member
.Text
= accessor
;
1074 // just generate code for the standard mixed case (string[] text)
1075 member
.TypeDesc
= accessor
.Mapping
.TypeDesc
.CreateArrayTypeDesc();
1076 member
.Name
= members
.MakeRightCase("Text");
1079 // import mapping for the simpleContent
1080 PrimitiveMapping pm
= (PrimitiveMapping
)accessor
.Mapping
;
1082 member
.TypeDesc
= accessor
.Mapping
.TypeDesc
.CreateArrayTypeDesc();
1083 member
.Name
= members
.MakeRightCase("Text");
1086 member
.TypeDesc
= accessor
.Mapping
.TypeDesc
;
1087 member
.Name
= members
.MakeRightCase("Value");
1090 member
.Name
= membersScope
.AddUnique(member
.Name
, member
);
1091 members
.Add(member
.Name
, member
);
1094 MemberMapping
ImportAnyMember(XmlSchemaAny any
, string identifier
, CodeIdentifiers members
, CodeIdentifiers membersScope
, INameScope elementsScope
, string ns
, ref bool mixed
, ref bool needExplicitOrder
, bool allowDuplicates
) {
1095 ElementAccessor
[] accessors
= ImportAny(any
, !mixed
, ns
);
1096 AddScopeElements(elementsScope
, accessors
, ref needExplicitOrder
, allowDuplicates
);
1097 MemberMapping member
= new MemberMapping();
1098 member
.Elements
= accessors
;
1099 member
.Name
= membersScope
.MakeRightCase("Any");
1100 member
.Name
= membersScope
.AddUnique(member
.Name
, member
);
1101 members
.Add(member
.Name
, member
);
1102 member
.TypeDesc
= ((TypeMapping
)accessors
[0].Mapping
).TypeDesc
;
1104 bool repeats
= any
.IsMultipleOccurrence
;
1107 SpecialMapping textMapping
= new SpecialMapping();
1108 textMapping
.TypeDesc
= Scope
.GetTypeDesc(typeof(XmlNode
));
1109 textMapping
.TypeName
= textMapping
.TypeDesc
.Name
;
1110 member
.TypeDesc
= textMapping
.TypeDesc
;
1111 TextAccessor text
= new TextAccessor();
1112 text
.Mapping
= textMapping
;
1119 member
.TypeDesc
= member
.TypeDesc
.CreateArrayTypeDesc();
1123 ElementAccessor
[] ImportAny(XmlSchemaAny any
, bool makeElement
, string targetNamespace
) {
1124 SpecialMapping mapping
= new SpecialMapping();
1126 mapping
.TypeDesc
= Scope
.GetTypeDesc(makeElement
? typeof(XmlElement
) : typeof(XmlNode
));
1127 mapping
.TypeName
= mapping
.TypeDesc
.Name
;
1130 TypeFlags flags
= TypeFlags
.CanBeElementValue
;
1132 flags
|= TypeFlags
.CanBeTextValue
;
1134 // let the extensions to run
1135 RunSchemaExtensions(mapping
, XmlQualifiedName
.Empty
, null, any
, flags
);
1137 if (GenerateOrder
&& any
.Namespace
!= null) {
1138 NamespaceList list
= new NamespaceList(any
.Namespace
, targetNamespace
);
1140 if (list
.Type
== NamespaceList
.ListType
.Set
) {
1141 ICollection namespaces
= list
.Enumerate
;
1142 ElementAccessor
[] accessors
= new ElementAccessor
[namespaces
.Count
== 0 ? 1 : namespaces
.Count
];
1144 foreach(string ns
in list
.Enumerate
) {
1145 ElementAccessor accessor
= new ElementAccessor();
1146 accessor
.Mapping
= mapping
;
1147 accessor
.Any
= true;
1148 accessor
.Namespace
= ns
;
1149 accessors
[count
++] = accessor
;
1157 ElementAccessor anyAccessor
= new ElementAccessor();
1158 anyAccessor
.Mapping
= mapping
;
1159 anyAccessor
.Any
= true;
1160 return new ElementAccessor
[] {anyAccessor}
;
1163 ElementAccessor
ImportArray(XmlSchemaElement element
, string identifier
, string ns
, bool repeats
) {
1164 if (repeats
) return null;
1165 if (element
.SchemaType
== null) return null;
1166 if (element
.IsMultipleOccurrence
) return null;
1167 XmlSchemaType type
= element
.SchemaType
;
1168 ArrayMapping arrayMapping
= ImportArrayMapping(type
, identifier
, ns
, repeats
);
1169 if (arrayMapping
== null) return null;
1170 ElementAccessor arrayAccessor
= new ElementAccessor();
1171 arrayAccessor
.Name
= element
.Name
;
1172 arrayAccessor
.Namespace
= ns
;
1173 arrayAccessor
.Mapping
= arrayMapping
;
1174 if (arrayMapping
.TypeDesc
.IsNullable
)
1175 arrayAccessor
.IsNullable
= element
.IsNillable
;
1176 arrayAccessor
.Form
= ElementForm(ns
, element
);
1177 return arrayAccessor
;
1180 ArrayMapping
ImportArrayMapping(XmlSchemaType type
, string identifier
, string ns
, bool repeats
) {
1181 if (!(type
is XmlSchemaComplexType
)) return null;
1182 if (!type
.DerivedFrom
.IsEmpty
) return null;
1183 if (IsMixed(type
)) return null;
1185 Mapping previousMapping
= (Mapping
)ImportedMappings
[type
];
1186 if (previousMapping
!= null) {
1187 if (previousMapping
is ArrayMapping
)
1188 return (ArrayMapping
)previousMapping
;
1193 TypeItems items
= GetTypeItems(type
);
1195 if (items
.Attributes
!= null && items
.Attributes
.Count
> 0) return null;
1196 if (items
.AnyAttribute
!= null) return null;
1197 if (items
.Particle
== null) return null;
1199 XmlSchemaGroupBase item
= items
.Particle
;
1200 ArrayMapping arrayMapping
= new ArrayMapping();
1202 arrayMapping
.TypeName
= identifier
;
1203 arrayMapping
.Namespace
= ns
;
1205 if (item
is XmlSchemaChoice
) {
1206 XmlSchemaChoice choice
= (XmlSchemaChoice
)item
;
1207 if (!choice
.IsMultipleOccurrence
)
1209 bool needExplicitOrder
= false;
1210 MemberMapping choiceMember
= ImportChoiceGroup(choice
, identifier
, null, null, null, ns
, true, ref needExplicitOrder
, false);
1211 if (choiceMember
.ChoiceIdentifier
!= null) return null;
1212 arrayMapping
.TypeDesc
= choiceMember
.TypeDesc
;
1213 arrayMapping
.Elements
= choiceMember
.Elements
;
1214 arrayMapping
.TypeName
= (type
.Name
== null || type
.Name
.Length
== 0) ? "ArrayOf" + CodeIdentifier
.MakePascal(arrayMapping
.TypeDesc
.Name
) : type
.Name
;
1216 else if (item
is XmlSchemaAll
|| item
is XmlSchemaSequence
) {
1217 if (item
.Items
.Count
!= 1 || !(item
.Items
[0] is XmlSchemaElement
)) return null;
1218 XmlSchemaElement itemElement
= (XmlSchemaElement
)item
.Items
[0];
1219 if (!itemElement
.IsMultipleOccurrence
) return null;
1220 if (IsCyclicReferencedType(itemElement
, new List
<string>(1){identifier}
))
1225 ElementAccessor itemAccessor
= ImportElement(itemElement
, identifier
, typeof(TypeMapping
), null, ns
, false);
1226 if (itemAccessor
.Any
)
1228 arrayMapping
.Elements
= new ElementAccessor
[] { itemAccessor }
;
1229 arrayMapping
.TypeDesc
= ((TypeMapping
)itemAccessor
.Mapping
).TypeDesc
.CreateArrayTypeDesc();
1230 arrayMapping
.TypeName
= (type
.Name
== null || type
.Name
.Length
== 0) ? "ArrayOf" + CodeIdentifier
.MakePascal(itemAccessor
.Mapping
.TypeDesc
.Name
) : type
.Name
;
1236 ImportedMappings
[type
] = arrayMapping
;
1237 Scope
.AddTypeMapping(arrayMapping
);
1238 // for the array-like mappings we need to create a struct mapping for the case when it referenced by the top-level element
1239 arrayMapping
.TopLevelMapping
= ImportStructType(type
, ns
, identifier
, null, true);
1240 arrayMapping
.TopLevelMapping
.ReferencedByTopLevelElement
= true;
1241 if (type
.Name
!= null && type
.Name
.Length
!= 0)
1242 ImportDerivedTypes(new XmlQualifiedName(identifier
, ns
));
1244 return arrayMapping
;
1247 bool IsCyclicReferencedType(XmlSchemaElement element
, List
<string> identifiers
)
1249 if (!element
.RefName
.IsEmpty
)
1251 XmlSchemaElement refElement
= FindElement(element
.RefName
);
1252 string refElementIdentifier
= CodeIdentifier
.MakeValid(Accessor
.UnescapeName(refElement
.Name
));
1253 foreach (string identifier
in identifiers
)
1255 if (refElementIdentifier
== identifier
)
1260 identifiers
.Add(refElementIdentifier
);
1262 XmlSchemaType refType
= refElement
.SchemaType
;
1263 if (refType
is XmlSchemaComplexType
)
1265 TypeItems items
= GetTypeItems(refType
);
1266 if ((items
.Particle
is XmlSchemaSequence
|| items
.Particle
is XmlSchemaAll
) && items
.Particle
.Items
.Count
== 1 && items
.Particle
.Items
[0] is XmlSchemaElement
)
1268 XmlSchemaElement innerRefElement
= (XmlSchemaElement
)items
.Particle
.Items
[0];
1269 if (innerRefElement
.IsMultipleOccurrence
)
1271 return IsCyclicReferencedType(innerRefElement
, identifiers
);
1279 SpecialMapping
ImportAnyMapping(XmlSchemaType type
, string identifier
, string ns
, bool repeats
) {
1280 if (type
== null) return null;
1281 if (!type
.DerivedFrom
.IsEmpty
) return null;
1283 bool mixed
= IsMixed(type
);
1284 TypeItems items
= GetTypeItems(type
);
1285 if (items
.Particle
== null) return null;
1286 if (!(items
.Particle
is XmlSchemaAll
|| items
.Particle
is XmlSchemaSequence
)) return null;
1287 if (items
.Attributes
!= null && items
.Attributes
.Count
> 0) return null;
1288 XmlSchemaGroupBase
group = (XmlSchemaGroupBase
) items
.Particle
;
1290 if (group.Items
.Count
!= 1 || !(group.Items
[0] is XmlSchemaAny
)) return null;
1291 XmlSchemaAny any
= (XmlSchemaAny
)group.Items
[0];
1293 SpecialMapping mapping
= new SpecialMapping();
1294 // check for special named any case
1295 if (items
.AnyAttribute
!= null && any
.IsMultipleOccurrence
&& mixed
) {
1296 mapping
.NamedAny
= true;
1297 mapping
.TypeDesc
= Scope
.GetTypeDesc(typeof(XmlElement
));
1299 else if (items
.AnyAttribute
!= null || any
.IsMultipleOccurrence
) {
1300 // these only work for named any case -- otherwise import as struct
1304 mapping
.TypeDesc
= Scope
.GetTypeDesc(mixed
? typeof(XmlNode
) : typeof(XmlElement
));
1307 TypeFlags flags
= TypeFlags
.CanBeElementValue
;
1308 if (items
.AnyAttribute
!= null || mixed
)
1309 flags
|= TypeFlags
.CanBeTextValue
;
1311 // let the extensions to run
1312 RunSchemaExtensions(mapping
, XmlQualifiedName
.Empty
, null, any
, flags
);
1314 mapping
.TypeName
= mapping
.TypeDesc
.Name
;
1316 mapping
.TypeDesc
= mapping
.TypeDesc
.CreateArrayTypeDesc();
1321 void ImportElementMember(XmlSchemaElement element
, string identifier
, CodeIdentifiers members
, CodeIdentifiers membersScope
, INameScope elementsScope
, string ns
, bool repeats
, ref bool needExplicitOrder
, bool allowDuplicates
, bool allowUnboundedElements
) {
1322 repeats
= repeats
| element
.IsMultipleOccurrence
;
1323 XmlSchemaElement headElement
= GetTopLevelElement(element
);
1324 if (headElement
!= null && ImportSubstitutionGroupMember(headElement
, identifier
, members
, membersScope
, ns
, repeats
, ref needExplicitOrder
, allowDuplicates
)) {
1327 ElementAccessor accessor
;
1328 if ((accessor
= ImportArray(element
, identifier
, ns
, repeats
)) == null) {
1329 accessor
= ImportElement(element
, identifier
, typeof(TypeMapping
), null, ns
, false);
1332 MemberMapping member
= new MemberMapping();
1333 string name
= CodeIdentifier
.MakeValid(Accessor
.UnescapeName(accessor
.Name
));
1334 member
.Name
= membersScope
.AddUnique(name
, member
);
1336 if (member
.Name
.EndsWith("Specified", StringComparison
.Ordinal
)) {
1338 member
.Name
= membersScope
.AddUnique(member
.Name
, member
);
1339 membersScope
.Remove(name
);
1341 members
.Add(member
.Name
, member
);
1342 // we do not support lists for elements
1343 if (accessor
.Mapping
.IsList
) {
1344 accessor
.Mapping
= GetDefaultMapping(TypeFlags
.CanBeElementValue
| TypeFlags
.CanBeTextValue
);
1345 member
.TypeDesc
= accessor
.Mapping
.TypeDesc
;
1348 member
.TypeDesc
= accessor
.Mapping
.TypeDesc
;
1351 AddScopeElement(elementsScope
, accessor
, ref needExplicitOrder
, allowDuplicates
);
1352 member
.Elements
= new ElementAccessor
[] { accessor }
;
1354 if (element
.IsMultipleOccurrence
|| repeats
) {
1355 if (!allowUnboundedElements
&& accessor
.Mapping
is ArrayMapping
) {
1356 accessor
.Mapping
= ((ArrayMapping
)accessor
.Mapping
).TopLevelMapping
;
1357 accessor
.Mapping
.ReferencedByTopLevelElement
= false;
1358 accessor
.Mapping
.ReferencedByElement
= true;
1360 member
.TypeDesc
= accessor
.Mapping
.TypeDesc
.CreateArrayTypeDesc();
1363 if (element
.MinOccurs
== 0 && member
.TypeDesc
.IsValueType
&& !element
.HasDefault
&& !member
.TypeDesc
.HasIsEmpty
) {
1364 member
.CheckSpecified
= SpecifiedAccessor
.ReadWrite
;
1368 void ImportAttributeMember(XmlSchemaAttribute attribute
, string identifier
, CodeIdentifiers members
, CodeIdentifiers membersScope
, string ns
) {
1369 AttributeAccessor accessor
= ImportAttribute(attribute
, identifier
, ns
, attribute
);
1370 if (accessor
== null) return;
1371 MemberMapping member
= new MemberMapping();
1372 member
.Elements
= new ElementAccessor
[0];
1373 member
.Attribute
= accessor
;
1374 member
.Name
= CodeIdentifier
.MakeValid(Accessor
.UnescapeName(accessor
.Name
));
1375 member
.Name
= membersScope
.AddUnique(member
.Name
, member
);
1376 if (member
.Name
.EndsWith("Specified", StringComparison
.Ordinal
)) {
1377 string name
= member
.Name
;
1378 member
.Name
= membersScope
.AddUnique(member
.Name
, member
);
1379 membersScope
.Remove(name
);
1381 members
.Add(member
.Name
, member
);
1382 member
.TypeDesc
= accessor
.IsList
? accessor
.Mapping
.TypeDesc
.CreateArrayTypeDesc() : accessor
.Mapping
.TypeDesc
;
1384 if ((attribute
.Use
== XmlSchemaUse
.Optional
|| attribute
.Use
== XmlSchemaUse
.None
) && member
.TypeDesc
.IsValueType
&& !attribute
.HasDefault
&& !member
.TypeDesc
.HasIsEmpty
) {
1385 member
.CheckSpecified
= SpecifiedAccessor
.ReadWrite
;
1389 void ImportAnyAttributeMember(XmlSchemaAnyAttribute any
, CodeIdentifiers members
, CodeIdentifiers membersScope
) {
1390 SpecialMapping mapping
= new SpecialMapping();
1391 mapping
.TypeDesc
= Scope
.GetTypeDesc(typeof(XmlAttribute
));
1392 mapping
.TypeName
= mapping
.TypeDesc
.Name
;
1394 AttributeAccessor accessor
= new AttributeAccessor();
1395 accessor
.Any
= true;
1396 accessor
.Mapping
= mapping
;
1398 MemberMapping member
= new MemberMapping();
1399 member
.Elements
= new ElementAccessor
[0];
1400 member
.Attribute
= accessor
;
1401 member
.Name
= membersScope
.MakeRightCase("AnyAttr");
1402 member
.Name
= membersScope
.AddUnique(member
.Name
, member
);
1403 members
.Add(member
.Name
, member
);
1404 member
.TypeDesc
= ((TypeMapping
)accessor
.Mapping
).TypeDesc
;
1405 member
.TypeDesc
= member
.TypeDesc
.CreateArrayTypeDesc();
1408 bool KeepXmlnsDeclarations(XmlSchemaType type
, out string xmlnsMemberName
) {
1409 xmlnsMemberName
= null;
1410 if (type
.Annotation
== null)
1412 if (type
.Annotation
.Items
== null || type
.Annotation
.Items
.Count
== 0)
1415 foreach(XmlSchemaObject o
in type
.Annotation
.Items
) {
1416 if (o
is XmlSchemaAppInfo
) {
1417 XmlNode
[] nodes
= ((XmlSchemaAppInfo
)o
).Markup
;
1418 if (nodes
!= null && nodes
.Length
> 0) {
1419 foreach(XmlNode node
in nodes
) {
1420 if (node
is XmlElement
) {
1421 XmlElement e
= (XmlElement
)node
;
1422 if (e
.Name
== "keepNamespaceDeclarations") {
1423 if (e
.LastNode
is XmlText
) {
1424 xmlnsMemberName
= (((XmlText
)e
.LastNode
).Value
).Trim(null);
1436 void ImportXmlnsDeclarationsMember(XmlSchemaType type
, CodeIdentifiers members
, CodeIdentifiers membersScope
) {
1437 string xmlnsMemberName
;
1438 if (!KeepXmlnsDeclarations(type
, out xmlnsMemberName
))
1440 TypeDesc xmlnsTypeDesc
= Scope
.GetTypeDesc(typeof(XmlSerializerNamespaces
));
1441 StructMapping xmlnsMapping
= new StructMapping();
1443 xmlnsMapping
.TypeDesc
= xmlnsTypeDesc
;
1444 xmlnsMapping
.TypeName
= xmlnsMapping
.TypeDesc
.Name
;
1445 xmlnsMapping
.Members
= new MemberMapping
[0];
1446 xmlnsMapping
.IncludeInSchema
= false;
1447 xmlnsMapping
.ReferencedByTopLevelElement
= true;
1449 ElementAccessor xmlns
= new ElementAccessor();
1450 xmlns
.Mapping
= xmlnsMapping
;
1452 MemberMapping member
= new MemberMapping();
1453 member
.Elements
= new ElementAccessor
[] {xmlns}
;
1454 member
.Name
= CodeIdentifier
.MakeValid(xmlnsMemberName
== null ? "Namespaces" : xmlnsMemberName
);
1455 member
.Name
= membersScope
.AddUnique(member
.Name
, member
);
1456 members
.Add(member
.Name
, member
);
1457 member
.TypeDesc
= xmlnsTypeDesc
;
1458 member
.Xmlns
= new XmlnsAccessor();
1459 member
.Ignore
= true;
1462 void ImportAttributeGroupMembers(XmlSchemaAttributeGroup
group, string identifier
, CodeIdentifiers members
, CodeIdentifiers membersScope
, string ns
) {
1463 for (int i
= 0; i
< group.Attributes
.Count
; i
++) {
1464 object item
= group.Attributes
[i
];
1465 if (item
is XmlSchemaAttributeGroup
)
1466 ImportAttributeGroupMembers((XmlSchemaAttributeGroup
)item
, identifier
, members
, membersScope
, ns
);
1467 else if (item
is XmlSchemaAttribute
)
1468 ImportAttributeMember((XmlSchemaAttribute
)item
, identifier
, members
, membersScope
, ns
);
1470 if (group.AnyAttribute
!= null)
1471 ImportAnyAttributeMember(group.AnyAttribute
, members
, membersScope
);
1474 AttributeAccessor
ImportSpecialAttribute(XmlQualifiedName name
, string identifier
) {
1475 PrimitiveMapping mapping
= new PrimitiveMapping();
1476 mapping
.TypeDesc
= Scope
.GetTypeDesc(typeof(string));
1477 mapping
.TypeName
= mapping
.TypeDesc
.DataType
.Name
;
1478 AttributeAccessor accessor
= new AttributeAccessor();
1479 accessor
.Name
= name
.Name
;
1480 accessor
.Namespace
= XmlReservedNs
.NsXml
;
1481 accessor
.CheckSpecial();
1482 accessor
.Mapping
= mapping
;
1486 AttributeAccessor
ImportAttribute(XmlSchemaAttribute attribute
, string identifier
, string ns
, XmlSchemaAttribute defaultValueProvider
) {
1487 if (attribute
.Use
== XmlSchemaUse
.Prohibited
) return null;
1488 if (!attribute
.RefName
.IsEmpty
) {
1489 if (attribute
.RefName
.Namespace
== XmlReservedNs
.NsXml
)
1490 return ImportSpecialAttribute(attribute
.RefName
, identifier
);
1492 return ImportAttribute(FindAttribute(attribute
.RefName
), identifier
, attribute
.RefName
.Namespace
, defaultValueProvider
);
1494 TypeMapping mapping
;
1495 if (attribute
.Name
.Length
== 0) throw new InvalidOperationException(Res
.GetString(Res
.XmlAttributeHasNoName
));
1496 if (identifier
.Length
== 0)
1497 identifier
= CodeIdentifier
.MakeValid(attribute
.Name
);
1499 identifier
+= CodeIdentifier
.MakePascal(attribute
.Name
);
1500 if (!attribute
.SchemaTypeName
.IsEmpty
)
1501 mapping
= (TypeMapping
)ImportType(attribute
.SchemaTypeName
, typeof(TypeMapping
), null, TypeFlags
.CanBeAttributeValue
, false);
1502 else if (attribute
.SchemaType
!= null)
1503 mapping
= ImportDataType((XmlSchemaSimpleType
)attribute
.SchemaType
, ns
, identifier
, null, TypeFlags
.CanBeAttributeValue
, false);
1505 mapping
= GetDefaultMapping(TypeFlags
.CanBeAttributeValue
);
1508 // let the extensions to run
1509 if (mapping
!= null && !mapping
.TypeDesc
.IsMappedType
) {
1510 RunSchemaExtensions(mapping
, attribute
.SchemaTypeName
, attribute
.SchemaType
, attribute
, TypeFlags
.CanBeElementValue
| TypeFlags
.CanBeAttributeValue
| TypeFlags
.CanBeTextValue
);
1512 AttributeAccessor accessor
= new AttributeAccessor();
1513 accessor
.Name
= attribute
.Name
;
1514 accessor
.Namespace
= ns
;
1515 accessor
.Form
= AttributeForm(ns
, attribute
);
1516 accessor
.CheckSpecial();
1517 accessor
.Mapping
= mapping
;
1518 accessor
.IsList
= mapping
.IsList
;
1519 accessor
.IsOptional
= attribute
.Use
!= XmlSchemaUse
.Required
;
1521 if (defaultValueProvider
.DefaultValue
!= null) {
1522 accessor
.Default
= defaultValueProvider
.DefaultValue
;
1524 else if (defaultValueProvider
.FixedValue
!= null) {
1525 accessor
.Default
= defaultValueProvider
.FixedValue
;
1526 accessor
.IsFixed
= true;
1528 else if (attribute
!= defaultValueProvider
) {
1529 if (attribute
.DefaultValue
!= null) {
1530 accessor
.Default
= attribute
.DefaultValue
;
1532 else if (attribute
.FixedValue
!= null) {
1533 accessor
.Default
= attribute
.FixedValue
;
1534 accessor
.IsFixed
= true;
1540 TypeMapping
ImportDataType(XmlSchemaSimpleType dataType
, string typeNs
, string identifier
, Type baseType
, TypeFlags flags
, bool isList
) {
1541 if (baseType
!= null)
1542 return ImportStructDataType(dataType
, typeNs
, identifier
, baseType
);
1544 TypeMapping mapping
= ImportNonXsdPrimitiveDataType(dataType
, typeNs
, flags
);
1545 if (mapping
!= null)
1548 if (dataType
.Content
is XmlSchemaSimpleTypeRestriction
) {
1549 XmlSchemaSimpleTypeRestriction restriction
= (XmlSchemaSimpleTypeRestriction
)dataType
.Content
;
1550 foreach (object o
in restriction
.Facets
) {
1551 if (o
is XmlSchemaEnumerationFacet
) {
1552 return ImportEnumeratedDataType(dataType
, typeNs
, identifier
, flags
, isList
);
1555 if (restriction
.BaseType
!= null) {
1556 return ImportDataType(restriction
.BaseType
, typeNs
, identifier
, null, flags
, false);
1559 AddReference(restriction
.BaseTypeName
, TypesInUse
, Res
.XmlCircularTypeReference
);
1560 mapping
= ImportDataType(FindDataType(restriction
.BaseTypeName
, flags
), restriction
.BaseTypeName
.Namespace
, identifier
, null, flags
, false);
1561 if (restriction
.BaseTypeName
.Namespace
!= XmlSchema
.Namespace
)
1562 RemoveReference(restriction
.BaseTypeName
, TypesInUse
);
1566 else if (dataType
.Content
is XmlSchemaSimpleTypeList
|| dataType
.Content
is XmlSchemaSimpleTypeUnion
) {
1567 if (dataType
.Content
is XmlSchemaSimpleTypeList
) {
1568 // check if we have enumeration list
1569 XmlSchemaSimpleTypeList list
= (XmlSchemaSimpleTypeList
)dataType
.Content
;
1570 if (list
.ItemType
!= null) {
1571 mapping
= ImportDataType(list
.ItemType
, typeNs
, identifier
, null, flags
, true);
1572 if (mapping
!= null) {
1573 mapping
.TypeName
= dataType
.Name
;
1577 else if (list
.ItemTypeName
!= null && !list
.ItemTypeName
.IsEmpty
) {
1578 mapping
= ImportType(list
.ItemTypeName
, typeof(TypeMapping
), null, TypeFlags
.CanBeAttributeValue
, true);
1579 if (mapping
!= null && mapping
is PrimitiveMapping
) {
1580 ((PrimitiveMapping
)mapping
).IsList
= true;
1585 return GetDefaultMapping(flags
);
1587 return ImportPrimitiveDataType(dataType
, flags
);
1590 TypeMapping
ImportEnumeratedDataType(XmlSchemaSimpleType dataType
, string typeNs
, string identifier
, TypeFlags flags
, bool isList
) {
1591 TypeMapping mapping
= (TypeMapping
)ImportedMappings
[dataType
];
1592 if (mapping
!= null)
1595 XmlSchemaType sourceType
= dataType
;
1596 while (!sourceType
.DerivedFrom
.IsEmpty
) {
1597 sourceType
= FindType(sourceType
.DerivedFrom
, TypeFlags
.CanBeElementValue
| TypeFlags
.CanBeAttributeValue
);
1599 if (sourceType
is XmlSchemaComplexType
) return null;
1600 TypeDesc sourceTypeDesc
= Scope
.GetTypeDesc((XmlSchemaSimpleType
)sourceType
);
1601 if (sourceTypeDesc
!= null && sourceTypeDesc
.FullName
!= typeof(string).FullName
)
1602 return ImportPrimitiveDataType(dataType
, flags
);
1603 identifier
= Accessor
.UnescapeName(identifier
);
1604 string typeName
= GenerateUniqueTypeName(identifier
);
1605 EnumMapping enumMapping
= new EnumMapping();
1606 enumMapping
.IsReference
= Schemas
.IsReference(dataType
);
1607 enumMapping
.TypeDesc
= new TypeDesc(typeName
, typeName
, TypeKind
.Enum
, null, 0);
1608 if (dataType
.Name
!= null && dataType
.Name
.Length
> 0)
1609 enumMapping
.TypeName
= identifier
;
1610 enumMapping
.Namespace
= typeNs
;
1611 enumMapping
.IsFlags
= isList
;
1613 CodeIdentifiers constants
= new CodeIdentifiers();
1614 XmlSchemaSimpleTypeContent content
= dataType
.Content
;
1616 if (content
is XmlSchemaSimpleTypeRestriction
) {
1617 XmlSchemaSimpleTypeRestriction restriction
= (XmlSchemaSimpleTypeRestriction
)content
;
1618 for (int i
= 0; i
< restriction
.Facets
.Count
; i
++) {
1619 object facet
= restriction
.Facets
[i
];
1620 if (!(facet
is XmlSchemaEnumerationFacet
)) continue;
1621 XmlSchemaEnumerationFacet enumeration
= (XmlSchemaEnumerationFacet
)facet
;
1622 // validate the enumeration value
1623 if (sourceTypeDesc
!= null && sourceTypeDesc
.HasCustomFormatter
) {
1624 XmlCustomFormatter
.ToDefaultValue(enumeration
.Value
, sourceTypeDesc
.FormatterName
);
1626 ConstantMapping constant
= new ConstantMapping();
1627 string constantName
= CodeIdentifier
.MakeValid(enumeration
.Value
);
1628 constant
.Name
= constants
.AddUnique(constantName
, constant
);
1629 constant
.XmlName
= enumeration
.Value
;
1633 enumMapping
.Constants
= (ConstantMapping
[])constants
.ToArray(typeof(ConstantMapping
));
1634 if (isList
&& enumMapping
.Constants
.Length
> 63) {
1635 // if we have 64+ flag constants we cannot map the type to long enum, we will use string mapping instead.
1636 mapping
= GetDefaultMapping(TypeFlags
.CanBeElementValue
| TypeFlags
.CanBeTextValue
| TypeFlags
.CanBeAttributeValue
);
1637 ImportedMappings
.Add(dataType
, mapping
);
1640 ImportedMappings
.Add(dataType
, enumMapping
);
1641 Scope
.AddTypeMapping(enumMapping
);
1645 internal class ElementComparer
: IComparer
{
1646 public int Compare(object o1
, object o2
) {
1647 ElementAccessor e1
= (ElementAccessor
)o1
;
1648 ElementAccessor e2
= (ElementAccessor
)o2
;
1649 return String
.Compare(e1
.ToString(string.Empty
), e2
.ToString(string.Empty
), StringComparison
.Ordinal
);
1653 EnumMapping
ImportEnumeratedChoice(ElementAccessor
[] choice
, string typeNs
, string typeName
) {
1654 typeName
= GenerateUniqueTypeName(Accessor
.UnescapeName(typeName
), typeNs
);
1655 EnumMapping enumMapping
= new EnumMapping();
1656 enumMapping
.TypeDesc
= new TypeDesc(typeName
, typeName
, TypeKind
.Enum
, null, 0);
1657 enumMapping
.TypeName
= typeName
;
1658 enumMapping
.Namespace
= typeNs
;
1659 enumMapping
.IsFlags
= false;
1660 enumMapping
.IncludeInSchema
= false;
1662 if (GenerateOrder
) {
1663 Array
.Sort(choice
, new ElementComparer());
1665 CodeIdentifiers constants
= new CodeIdentifiers();
1666 for (int i
= 0; i
< choice
.Length
; i
++) {
1667 ElementAccessor element
= choice
[i
];
1668 ConstantMapping constant
= new ConstantMapping();
1669 string constantName
= CodeIdentifier
.MakeValid(element
.Name
);
1670 constant
.Name
= constants
.AddUnique(constantName
, constant
);
1671 constant
.XmlName
= element
.ToString(typeNs
);
1674 enumMapping
.Constants
= (ConstantMapping
[])constants
.ToArray(typeof(ConstantMapping
));
1675 Scope
.AddTypeMapping(enumMapping
);
1679 PrimitiveMapping
ImportPrimitiveDataType(XmlSchemaSimpleType dataType
, TypeFlags flags
) {
1680 TypeDesc sourceTypeDesc
= GetDataTypeSource(dataType
, flags
);
1681 PrimitiveMapping mapping
= new PrimitiveMapping();
1682 mapping
.TypeDesc
= sourceTypeDesc
;
1683 mapping
.TypeName
= sourceTypeDesc
.DataType
.Name
;
1684 mapping
.Namespace
= mapping
.TypeDesc
.IsXsdType
? XmlSchema
.Namespace
: UrtTypes
.Namespace
;
1688 PrimitiveMapping
ImportNonXsdPrimitiveDataType(XmlSchemaSimpleType dataType
, string ns
, TypeFlags flags
) {
1689 PrimitiveMapping mapping
= null;
1690 TypeDesc typeDesc
= null;
1691 if (dataType
.Name
!= null && dataType
.Name
.Length
!= 0) {
1692 typeDesc
= Scope
.GetTypeDesc(dataType
.Name
, ns
, flags
);
1693 if (typeDesc
!= null) {
1694 mapping
= new PrimitiveMapping();
1695 mapping
.TypeDesc
= typeDesc
;
1696 mapping
.TypeName
= typeDesc
.DataType
.Name
;
1697 mapping
.Namespace
= mapping
.TypeDesc
.IsXsdType
? XmlSchema
.Namespace
: ns
;
1703 XmlSchemaGroup
FindGroup(XmlQualifiedName name
) {
1704 XmlSchemaGroup
group = (XmlSchemaGroup
)Schemas
.Find(name
, typeof(XmlSchemaGroup
));
1706 throw new InvalidOperationException(Res
.GetString(Res
.XmlMissingGroup
, name
.Name
));
1711 XmlSchemaAttributeGroup
FindAttributeGroup(XmlQualifiedName name
) {
1712 XmlSchemaAttributeGroup
group = (XmlSchemaAttributeGroup
)Schemas
.Find(name
, typeof(XmlSchemaAttributeGroup
));
1714 throw new InvalidOperationException(Res
.GetString(Res
.XmlMissingAttributeGroup
, name
.Name
));
1719 internal static XmlQualifiedName
BaseTypeName(XmlSchemaSimpleType dataType
) {
1720 XmlSchemaSimpleTypeContent content
= dataType
.Content
;
1721 if (content
is XmlSchemaSimpleTypeRestriction
) {
1722 return ((XmlSchemaSimpleTypeRestriction
)content
).BaseTypeName
;
1724 else if (content
is XmlSchemaSimpleTypeList
) {
1725 XmlSchemaSimpleTypeList list
= (XmlSchemaSimpleTypeList
)content
;
1726 if (list
.ItemTypeName
!= null && !list
.ItemTypeName
.IsEmpty
)
1727 return list
.ItemTypeName
;
1728 if (list
.ItemType
!= null) {
1729 return BaseTypeName(list
.ItemType
);
1732 return new XmlQualifiedName("string", XmlSchema
.Namespace
);
1735 TypeDesc
GetDataTypeSource(XmlSchemaSimpleType dataType
, TypeFlags flags
) {
1736 TypeDesc typeDesc
= null;
1737 if (dataType
.Name
!= null && dataType
.Name
.Length
!= 0) {
1738 typeDesc
= Scope
.GetTypeDesc(dataType
);
1739 if (typeDesc
!= null) return typeDesc
;
1741 XmlQualifiedName qname
= BaseTypeName(dataType
);
1742 AddReference(qname
, TypesInUse
, Res
.XmlCircularTypeReference
);
1743 typeDesc
= GetDataTypeSource(FindDataType(qname
, flags
), flags
);
1744 if (qname
.Namespace
!= XmlSchema
.Namespace
)
1745 RemoveReference(qname
, TypesInUse
);
1750 XmlSchemaSimpleType
FindDataType(XmlQualifiedName name
, TypeFlags flags
) {
1751 if (name
== null || name
.IsEmpty
) {
1752 return (XmlSchemaSimpleType
)Scope
.GetTypeDesc(typeof(string)).DataType
;
1754 TypeDesc typeDesc
= Scope
.GetTypeDesc(name
.Name
, name
.Namespace
, flags
);
1755 if (typeDesc
!= null && typeDesc
.DataType
is XmlSchemaSimpleType
)
1756 return (XmlSchemaSimpleType
)typeDesc
.DataType
;
1757 XmlSchemaSimpleType dataType
= (XmlSchemaSimpleType
)Schemas
.Find(name
, typeof(XmlSchemaSimpleType
));
1758 if (dataType
!= null) {
1761 if (name
.Namespace
== XmlSchema
.Namespace
)
1762 return (XmlSchemaSimpleType
)Scope
.GetTypeDesc("string", XmlSchema
.Namespace
, flags
).DataType
;
1764 if (name
.Name
== Soap
.Array
&& name
.Namespace
== Soap
.Encoding
) {
1765 throw new InvalidOperationException(Res
.GetString(Res
.XmlInvalidEncoding
, name
.ToString()));
1768 throw new InvalidOperationException(Res
.GetString(Res
.XmlMissingDataType
, name
.ToString()));
1773 XmlSchemaType
FindType(XmlQualifiedName name
, TypeFlags flags
) {
1774 if (name
== null || name
.IsEmpty
) {
1775 return Scope
.GetTypeDesc(typeof(string)).DataType
;
1777 object type
= Schemas
.Find(name
, typeof(XmlSchemaComplexType
));
1779 return (XmlSchemaComplexType
)type
;
1781 return FindDataType(name
, flags
);
1784 XmlSchemaElement
FindElement(XmlQualifiedName name
) {
1785 XmlSchemaElement element
= (XmlSchemaElement
)Schemas
.Find(name
, typeof(XmlSchemaElement
));
1786 if (element
== null)
1787 throw new InvalidOperationException(Res
.GetString(Res
.XmlMissingElement
, name
.ToString()));
1791 XmlSchemaAttribute
FindAttribute(XmlQualifiedName name
) {
1792 XmlSchemaAttribute attribute
= (XmlSchemaAttribute
)Schemas
.Find(name
, typeof(XmlSchemaAttribute
));
1793 if (attribute
== null)
1794 throw new InvalidOperationException(Res
.GetString(Res
.XmlMissingAttribute
, name
.Name
));
1799 XmlSchemaForm
ElementForm(string ns
, XmlSchemaElement element
) {
1800 if (element
.Form
== XmlSchemaForm
.None
) {
1801 XmlSchemaObject parent
= element
;
1802 while (parent
.Parent
!= null) {
1803 parent
= parent
.Parent
;
1805 XmlSchema schema
= parent
as XmlSchema
;
1807 if (schema
!= null) {
1808 if (ns
== null || ns
.Length
== 0) {
1809 return schema
.ElementFormDefault
== XmlSchemaForm
.None
? XmlSchemaForm
.Unqualified
: schema
.ElementFormDefault
;
1812 XmlSchemas
.Preprocess(schema
);
1813 return element
.QualifiedName
.Namespace
== null || element
.QualifiedName
.Namespace
.Length
== 0 ? XmlSchemaForm
.Unqualified
: XmlSchemaForm
.Qualified
;
1816 return XmlSchemaForm
.Qualified
;
1818 return element
.Form
;
1821 internal string FindExtendedAnyElement(XmlSchemaAny any
, bool mixed
, CodeCompileUnit compileUnit
, CodeNamespace mainNamespace
, out SchemaImporterExtension extension
) {
1823 foreach (SchemaImporterExtension ex
in Extensions
) {
1824 string typeName
= ex
.ImportAnyElement(any
, mixed
, Schemas
, this, compileUnit
, mainNamespace
, Options
, CodeProvider
);
1825 if (typeName
!= null && typeName
.Length
> 0) {
1833 internal string FindExtendedType(string name
, string ns
, XmlSchemaObject context
, CodeCompileUnit compileUnit
, CodeNamespace mainNamespace
, out SchemaImporterExtension extension
) {
1835 foreach (SchemaImporterExtension ex
in Extensions
) {
1836 string typeName
= ex
.ImportSchemaType(name
, ns
, context
, Schemas
, this, compileUnit
, mainNamespace
, Options
, CodeProvider
);
1837 if (typeName
!= null && typeName
.Length
> 0) {
1845 internal string FindExtendedType(XmlSchemaType type
, XmlSchemaObject context
, CodeCompileUnit compileUnit
, CodeNamespace mainNamespace
, out SchemaImporterExtension extension
) {
1847 foreach (SchemaImporterExtension ex
in Extensions
) {
1848 string typeName
= ex
.ImportSchemaType(type
, context
, Schemas
, this, compileUnit
, mainNamespace
, Options
, CodeProvider
);
1849 if (typeName
!= null && typeName
.Length
> 0) {
1857 XmlSchemaForm
AttributeForm(string ns
, XmlSchemaAttribute attribute
) {
1858 if (attribute
.Form
== XmlSchemaForm
.None
) {
1859 XmlSchemaObject parent
= attribute
;
1860 while (parent
.Parent
!= null) {
1861 parent
= parent
.Parent
;
1863 XmlSchema schema
= parent
as XmlSchema
;
1864 if (schema
!= null) {
1865 if (ns
== null || ns
.Length
== 0) {
1866 return schema
.AttributeFormDefault
== XmlSchemaForm
.None
? XmlSchemaForm
.Unqualified
: schema
.AttributeFormDefault
;
1869 XmlSchemas
.Preprocess(schema
);
1870 return attribute
.QualifiedName
.Namespace
== null || attribute
.QualifiedName
.Namespace
.Length
== 0 ? XmlSchemaForm
.Unqualified
: XmlSchemaForm
.Qualified
;
1873 return XmlSchemaForm
.Unqualified
;
1875 return attribute
.Form
;