1 // 2 // System.Xml.Serialization.XmlSchemaExporter 3 // 4 // Author: 5 // Tim Coleman (tim@timcoleman.com) 6 // Lluis Sanchez Gual (lluis@ximian.com) 7 // 8 // Copyright (C) Tim Coleman, 2002 9 // 10 11 // 12 // Permission is hereby granted, free of charge, to any person obtaining 13 // a copy of this software and associated documentation files (the 14 // "Software"), to deal in the Software without restriction, including 15 // without limitation the rights to use, copy, modify, merge, publish, 16 // distribute, sublicense, and/or sell copies of the Software, and to 17 // permit persons to whom the Software is furnished to do so, subject to 18 // the following conditions: 19 // 20 // The above copyright notice and this permission notice shall be 21 // included in all copies or substantial portions of the Software. 22 // 23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 30 // 31 32 using System.Xml; 33 using System.Xml.Schema; 34 using System.Collections; 35 36 namespace System.Xml.Serialization { 37 public class XmlSchemaExporter { 38 39 #region Fields 40 41 XmlSchemas schemas; 42 Hashtable exportedMaps = new Hashtable(); 43 Hashtable exportedElements = new Hashtable(); 44 bool encodedFormat = false; 45 XmlDocument xmlDoc; 46 47 #endregion 48 49 #region Constructors 50 XmlSchemaExporter(XmlSchemas schemas)51 public XmlSchemaExporter (XmlSchemas schemas) 52 { 53 this.schemas = schemas; 54 } 55 XmlSchemaExporter(XmlSchemas schemas, bool encodedFormat)56 internal XmlSchemaExporter (XmlSchemas schemas, bool encodedFormat) 57 { 58 this.encodedFormat = encodedFormat; 59 this.schemas = schemas; 60 } 61 62 #endregion // Constructors 63 64 #region Methods 65 66 [MonoTODO] ExportAnyType(string ns)67 public string ExportAnyType (string ns) 68 { 69 throw new NotImplementedException (); 70 } 71 72 [MonoNotSupported("")] ExportAnyType(XmlMembersMapping members)73 public string ExportAnyType (XmlMembersMapping members) 74 { 75 throw new NotImplementedException (); 76 } 77 ExportMembersMapping(XmlMembersMapping xmlMembersMapping)78 public void ExportMembersMapping (XmlMembersMapping xmlMembersMapping) 79 { 80 ExportMembersMapping (xmlMembersMapping, true); 81 } 82 83 public ExportMembersMapping(XmlMembersMapping xmlMembersMapping, bool exportEnclosingType)84 void ExportMembersMapping (XmlMembersMapping xmlMembersMapping, bool exportEnclosingType) 85 { 86 ClassMap cmap = (ClassMap) xmlMembersMapping.ObjectMap; 87 88 if (xmlMembersMapping.HasWrapperElement && exportEnclosingType) 89 { 90 XmlSchema schema = GetSchema (xmlMembersMapping.Namespace); 91 XmlSchemaComplexType stype = new XmlSchemaComplexType (); 92 93 XmlSchemaSequence particle; 94 XmlSchemaAnyAttribute anyAttribute; 95 ExportMembersMapSchema (schema, cmap, null, stype.Attributes, out particle, out anyAttribute); 96 stype.Particle = particle; 97 stype.AnyAttribute = anyAttribute; 98 99 if (encodedFormat) 100 { 101 stype.Name = xmlMembersMapping.ElementName; 102 schema.Items.Add (stype); 103 } 104 else 105 { 106 XmlSchemaElement selem = new XmlSchemaElement (); 107 selem.Name = xmlMembersMapping.ElementName; 108 selem.SchemaType = stype; 109 schema.Items.Add (selem); 110 } 111 } 112 else 113 { 114 ICollection members = cmap.ElementMembers; 115 if (members != null) 116 { 117 foreach (XmlTypeMapMemberElement member in members) 118 { 119 if (member is XmlTypeMapMemberAnyElement && member.TypeData.IsListType) 120 { 121 XmlSchema mschema = GetSchema (xmlMembersMapping.Namespace); 122 XmlSchemaParticle par = GetSchemaArrayElement (mschema, member.ElementInfo); 123 if (par is XmlSchemaAny) 124 { 125 XmlSchemaComplexType ct = FindComplexType (mschema.Items, "any"); 126 if (ct != null) continue; 127 128 ct = new XmlSchemaComplexType (); 129 ct.Name = "any"; 130 ct.IsMixed = true; 131 XmlSchemaSequence seq = new XmlSchemaSequence (); 132 ct.Particle = seq; 133 seq.Items.Add (par); 134 mschema.Items.Add (ct); 135 continue; 136 } 137 } 138 139 140 XmlTypeMapElementInfo einfo = (XmlTypeMapElementInfo) member.ElementInfo [0]; 141 XmlSchema schema; 142 143 if (encodedFormat) 144 { 145 schema = GetSchema (xmlMembersMapping.Namespace); 146 ImportNamespace (schema, XmlSerializer.EncodingNamespace); 147 } 148 else 149 schema = GetSchema (einfo.Namespace); 150 151 152 XmlSchemaElement exe = FindElement (schema.Items, einfo.ElementName); 153 XmlSchemaElement elem; 154 155 XmlSchemaObjectContainer container = null; 156 // In encoded format, the schema elements are not needed 157 if (!encodedFormat) 158 container = new XmlSchemaObjectContainer (schema); 159 160 Type memType = member.GetType(); 161 if (member is XmlTypeMapMemberFlatList) 162 throw new InvalidOperationException ("Unwrapped arrays not supported as parameters"); 163 else if (memType == typeof(XmlTypeMapMemberElement)) 164 elem = (XmlSchemaElement) GetSchemaElement (schema, 165 einfo, member.DefaultValue, false, container); 166 else 167 elem = (XmlSchemaElement) GetSchemaElement (schema, 168 einfo, false, container); 169 170 if (exe != null) 171 { 172 if (exe.SchemaTypeName.Equals (elem.SchemaTypeName)) 173 schema.Items.Remove (elem); 174 else 175 { 176 string s = "The XML element named '" + einfo.ElementName + "' "; 177 s += "from namespace '" + schema.TargetNamespace + "' references distinct types " + elem.SchemaTypeName.Name + " and " + exe.SchemaTypeName.Name + ". "; 178 s += "Use XML attributes to specify another XML name or namespace for the element or types."; 179 throw new InvalidOperationException (s); 180 } 181 } 182 } 183 } 184 } 185 186 CompileSchemas (); 187 } 188 189 [MonoTODO] ExportTypeMapping(XmlMembersMapping xmlMembersMapping)190 public XmlQualifiedName ExportTypeMapping (XmlMembersMapping xmlMembersMapping) 191 { 192 throw new NotImplementedException (); 193 } 194 ExportTypeMapping(XmlTypeMapping xmlTypeMapping)195 public void ExportTypeMapping (XmlTypeMapping xmlTypeMapping) 196 { 197 if (!xmlTypeMapping.IncludeInSchema) return; 198 if (IsElementExported (xmlTypeMapping)) return; 199 200 if (encodedFormat) 201 { 202 ExportClassSchema (xmlTypeMapping); 203 XmlSchema schema = GetSchema (xmlTypeMapping.XmlTypeNamespace); 204 ImportNamespace (schema, XmlSerializer.EncodingNamespace); 205 } 206 else 207 { 208 XmlSchema schema = GetSchema (xmlTypeMapping.Namespace); 209 XmlTypeMapElementInfo einfo = new XmlTypeMapElementInfo (null, xmlTypeMapping.TypeData); 210 einfo.Namespace = xmlTypeMapping.Namespace; 211 einfo.ElementName = xmlTypeMapping.ElementName; 212 if (xmlTypeMapping.TypeData.IsComplexType) 213 einfo.MappedType = xmlTypeMapping; 214 einfo.IsNullable = xmlTypeMapping.IsNullable; 215 GetSchemaElement (schema, einfo, false, new XmlSchemaObjectContainer (schema)); 216 SetElementExported (xmlTypeMapping); 217 } 218 219 CompileSchemas (); 220 } 221 ExportXmlSerializableSchema(XmlSchema currentSchema, XmlSerializableMapping map)222 void ExportXmlSerializableSchema (XmlSchema currentSchema, XmlSerializableMapping map) 223 { 224 if (IsMapExported (map)) return; 225 SetMapExported (map); 226 227 if (map.Schema == null) return; 228 229 string targetNs = map.Schema.TargetNamespace; 230 XmlSchema existingSchema = schemas [targetNs]; 231 if (existingSchema == null) 232 { 233 schemas.Add (map.Schema); 234 ImportNamespace (currentSchema, targetNs); 235 } 236 else if (existingSchema != map.Schema && !CanBeDuplicated (existingSchema, map.Schema)) 237 { 238 throw new InvalidOperationException("The namespace '" + targetNs +"' defined by the class '" + map.TypeFullName + "' is a duplicate."); 239 } 240 } 241 CanBeDuplicated(XmlSchema existingSchema, XmlSchema schema)242 private static bool CanBeDuplicated (XmlSchema existingSchema, XmlSchema schema) 243 { 244 if(XmlSchemas.IsDataSet (existingSchema) && XmlSchemas.IsDataSet (schema) 245 && existingSchema.Id == schema.Id) 246 return true; 247 return false; 248 } 249 ExportClassSchema(XmlTypeMapping map)250 void ExportClassSchema (XmlTypeMapping map) 251 { 252 if (IsMapExported (map)) return; 253 SetMapExported (map); 254 255 if (map.TypeData.Type == typeof(object)) 256 { 257 foreach (XmlTypeMapping dmap in map.DerivedTypes) 258 if (dmap.TypeData.SchemaType == SchemaTypes.Class) ExportClassSchema (dmap); 259 return; 260 } 261 262 XmlSchema schema = GetSchema (map.XmlTypeNamespace); 263 XmlSchemaComplexType stype = new XmlSchemaComplexType (); 264 stype.Name = map.XmlType; 265 schema.Items.Add (stype); 266 267 ClassMap cmap = (ClassMap)map.ObjectMap; 268 269 if (cmap.HasSimpleContent) 270 { 271 XmlSchemaSimpleContent simple = new XmlSchemaSimpleContent (); 272 stype.ContentModel = simple; 273 XmlSchemaSimpleContentExtension ext = new XmlSchemaSimpleContentExtension (); 274 simple.Content = ext; 275 XmlSchemaSequence particle; 276 XmlSchemaAnyAttribute anyAttribute; 277 ExportMembersMapSchema (schema, cmap, map.BaseMap, ext.Attributes, out particle, out anyAttribute); 278 ext.AnyAttribute = anyAttribute; 279 if (map.BaseMap == null) 280 ext.BaseTypeName = cmap.SimpleContentBaseType; 281 else { 282 ext.BaseTypeName = new XmlQualifiedName (map.BaseMap.XmlType, map.BaseMap.XmlTypeNamespace); 283 ImportNamespace (schema, map.BaseMap.XmlTypeNamespace); 284 ExportClassSchema (map.BaseMap); 285 } 286 } 287 else if (map.BaseMap != null && map.BaseMap.IncludeInSchema) 288 { 289 XmlSchemaComplexContent cstype = new XmlSchemaComplexContent (); 290 XmlSchemaComplexContentExtension ext = new XmlSchemaComplexContentExtension (); 291 ext.BaseTypeName = new XmlQualifiedName (map.BaseMap.XmlType, map.BaseMap.XmlTypeNamespace); 292 cstype.Content = ext; 293 stype.ContentModel = cstype; 294 295 XmlSchemaSequence particle; 296 XmlSchemaAnyAttribute anyAttribute; 297 ExportMembersMapSchema (schema, cmap, map.BaseMap, ext.Attributes, out particle, out anyAttribute); 298 ext.Particle = particle; 299 ext.AnyAttribute = anyAttribute; 300 stype.IsMixed = HasMixedContent (map); 301 cstype.IsMixed = BaseHasMixedContent (map); 302 303 ImportNamespace (schema, map.BaseMap.XmlTypeNamespace); 304 ExportClassSchema (map.BaseMap); 305 } 306 else 307 { 308 XmlSchemaSequence particle; 309 XmlSchemaAnyAttribute anyAttribute; 310 ExportMembersMapSchema (schema, cmap, map.BaseMap, stype.Attributes, out particle, out anyAttribute); 311 stype.Particle = particle; 312 stype.AnyAttribute = anyAttribute; 313 stype.IsMixed = cmap.XmlTextCollector != null; 314 } 315 316 foreach (XmlTypeMapping dmap in map.DerivedTypes) 317 if (dmap.TypeData.SchemaType == SchemaTypes.Class) ExportClassSchema (dmap); 318 } 319 BaseHasMixedContent(XmlTypeMapping map)320 bool BaseHasMixedContent (XmlTypeMapping map) 321 { 322 ClassMap cmap = (ClassMap)map.ObjectMap; 323 return (cmap.XmlTextCollector != null && (map.BaseMap != null && DefinedInBaseMap (map.BaseMap, cmap.XmlTextCollector))); 324 } 325 HasMixedContent(XmlTypeMapping map)326 bool HasMixedContent (XmlTypeMapping map) 327 { 328 ClassMap cmap = (ClassMap)map.ObjectMap; 329 return (cmap.XmlTextCollector != null && (map.BaseMap == null || !DefinedInBaseMap (map.BaseMap, cmap.XmlTextCollector))); 330 } 331 ExportMembersMapSchema(XmlSchema schema, ClassMap map, XmlTypeMapping baseMap, XmlSchemaObjectCollection outAttributes, out XmlSchemaSequence particle, out XmlSchemaAnyAttribute anyAttribute)332 void ExportMembersMapSchema (XmlSchema schema, ClassMap map, XmlTypeMapping baseMap, XmlSchemaObjectCollection outAttributes, out XmlSchemaSequence particle, out XmlSchemaAnyAttribute anyAttribute) 333 { 334 particle = null; 335 XmlSchemaSequence seq = new XmlSchemaSequence (); 336 337 ICollection members = map.ElementMembers; 338 if (members != null && !map.HasSimpleContent) 339 { 340 foreach (XmlTypeMapMemberElement member in members) 341 { 342 if (baseMap != null && DefinedInBaseMap (baseMap, member)) continue; 343 344 Type memType = member.GetType(); 345 if (memType == typeof(XmlTypeMapMemberFlatList)) 346 { 347 XmlSchemaParticle part = GetSchemaArrayElement (schema, member.ElementInfo); 348 if (part != null) seq.Items.Add (part); 349 } 350 else if (memType == typeof(XmlTypeMapMemberAnyElement)) 351 { 352 seq.Items.Add (GetSchemaArrayElement (schema, member.ElementInfo)); 353 } 354 else if (memType == typeof(XmlTypeMapMemberElement)) 355 { 356 GetSchemaElement (schema, (XmlTypeMapElementInfo) member.ElementInfo [0], 357 member.DefaultValue, true, new XmlSchemaObjectContainer (seq)); 358 } 359 else 360 { 361 GetSchemaElement (schema, (XmlTypeMapElementInfo) member.ElementInfo[0], 362 true, new XmlSchemaObjectContainer (seq)); 363 } 364 } 365 } 366 367 if (seq.Items.Count > 0) 368 particle = seq; 369 370 // Write attributes 371 372 ICollection attributes = map.AttributeMembers; 373 if (attributes != null) 374 { 375 foreach (XmlTypeMapMemberAttribute attr in attributes) { 376 if (baseMap != null && DefinedInBaseMap (baseMap, attr)) continue; 377 outAttributes.Add (GetSchemaAttribute (schema, attr, true)); 378 } 379 } 380 381 XmlTypeMapMember anyAttrMember = map.DefaultAnyAttributeMember; 382 if (anyAttrMember != null) 383 anyAttribute = new XmlSchemaAnyAttribute (); 384 else 385 anyAttribute = null; 386 } 387 FindElement(XmlSchemaObjectCollection col, string name)388 XmlSchemaElement FindElement (XmlSchemaObjectCollection col, string name) 389 { 390 foreach (XmlSchemaObject ob in col) 391 { 392 XmlSchemaElement elem = ob as XmlSchemaElement; 393 if (elem != null && elem.Name == name) return elem; 394 } 395 return null; 396 } 397 FindComplexType(XmlSchemaObjectCollection col, string name)398 XmlSchemaComplexType FindComplexType (XmlSchemaObjectCollection col, string name) 399 { 400 foreach (XmlSchemaObject ob in col) 401 { 402 XmlSchemaComplexType ctype = ob as XmlSchemaComplexType; 403 if (ctype != null && ctype.Name == name) return ctype; 404 } 405 return null; 406 } 407 GetSchemaAttribute(XmlSchema currentSchema, XmlTypeMapMemberAttribute attinfo, bool isTypeMember)408 XmlSchemaAttribute GetSchemaAttribute (XmlSchema currentSchema, XmlTypeMapMemberAttribute attinfo, bool isTypeMember) 409 { 410 XmlSchemaAttribute sat = new XmlSchemaAttribute (); 411 if (attinfo.DefaultValue != System.DBNull.Value) { 412 sat.DefaultValue = ExportDefaultValue (attinfo.TypeData, 413 attinfo.MappedType, attinfo.DefaultValue); 414 } else { 415 if (!attinfo.IsOptionalValueType && attinfo.TypeData.IsValueType) 416 sat.Use = XmlSchemaUse.Required; 417 } 418 419 ImportNamespace (currentSchema, attinfo.Namespace); 420 421 XmlSchema memberSchema; 422 if (attinfo.Namespace.Length == 0 && attinfo.Form != XmlSchemaForm.Qualified) 423 memberSchema = currentSchema; 424 else 425 memberSchema = GetSchema (attinfo.Namespace); 426 427 if (currentSchema == memberSchema || encodedFormat) 428 { 429 sat.Name = attinfo.AttributeName; 430 if (isTypeMember) sat.Form = attinfo.Form; 431 if (attinfo.TypeData.SchemaType == SchemaTypes.Enum) 432 { 433 ImportNamespace (currentSchema, attinfo.DataTypeNamespace); 434 ExportEnumSchema (attinfo.MappedType); 435 sat.SchemaTypeName = new XmlQualifiedName (attinfo.TypeData.XmlType, attinfo.DataTypeNamespace); 436 } 437 else if (attinfo.TypeData.SchemaType == SchemaTypes.Array && TypeTranslator.IsPrimitive (attinfo.TypeData.ListItemType)) 438 { 439 sat.SchemaType = GetSchemaSimpleListType (attinfo.TypeData); 440 } 441 else 442 sat.SchemaTypeName = new XmlQualifiedName (attinfo.TypeData.XmlType, attinfo.DataTypeNamespace);; 443 } 444 else 445 { 446 sat.RefName = new XmlQualifiedName (attinfo.AttributeName, attinfo.Namespace); 447 foreach (XmlSchemaObject ob in memberSchema.Items) 448 if (ob is XmlSchemaAttribute && ((XmlSchemaAttribute)ob).Name == attinfo.AttributeName) 449 return sat; 450 451 memberSchema.Items.Add (GetSchemaAttribute (memberSchema, attinfo, false)); 452 } 453 return sat; 454 } 455 GetSchemaElement(XmlSchema currentSchema, XmlTypeMapElementInfo einfo, bool isTypeMember)456 XmlSchemaParticle GetSchemaElement (XmlSchema currentSchema, XmlTypeMapElementInfo einfo, bool isTypeMember) 457 { 458 return GetSchemaElement (currentSchema, einfo, System.DBNull.Value, 459 isTypeMember, (XmlSchemaObjectContainer) null); 460 } 461 GetSchemaElement(XmlSchema currentSchema, XmlTypeMapElementInfo einfo, bool isTypeMember, XmlSchemaObjectContainer container)462 XmlSchemaParticle GetSchemaElement (XmlSchema currentSchema, XmlTypeMapElementInfo einfo, bool isTypeMember, XmlSchemaObjectContainer container) 463 { 464 return GetSchemaElement (currentSchema, einfo, System.DBNull.Value, isTypeMember, container); 465 } 466 GetSchemaElement(XmlSchema currentSchema, XmlTypeMapElementInfo einfo, object defaultValue, bool isTypeMember, XmlSchemaObjectContainer container)467 XmlSchemaParticle GetSchemaElement (XmlSchema currentSchema, XmlTypeMapElementInfo einfo, object defaultValue, bool isTypeMember, XmlSchemaObjectContainer container) 468 { 469 if (einfo.IsTextElement) return null; 470 471 if (einfo.IsUnnamedAnyElement) 472 { 473 XmlSchemaAny any = new XmlSchemaAny (); 474 any.MinOccurs = 0; 475 any.MaxOccurs = 1; 476 if (container != null) 477 container.Items.Add (any); 478 return any; 479 } 480 481 XmlSchemaElement selem = new XmlSchemaElement (); 482 selem.IsNillable = einfo.IsNullable; 483 if (container != null) 484 container.Items.Add (selem); 485 486 if (isTypeMember) 487 { 488 selem.MaxOccurs = 1; 489 selem.MinOccurs = einfo.IsNullable ? 1 : 0; 490 491 if ((defaultValue == DBNull.Value && einfo.TypeData.IsValueType && einfo.Member != null && !einfo.Member.IsOptionalValueType) || encodedFormat) 492 selem.MinOccurs = 1; 493 } 494 495 XmlSchema memberSchema = null; 496 497 if (!encodedFormat) 498 { 499 memberSchema = GetSchema (einfo.Namespace); 500 ImportNamespace (currentSchema, einfo.Namespace); 501 } 502 503 if (currentSchema == memberSchema || encodedFormat || !isTypeMember) 504 { 505 if (isTypeMember) selem.IsNillable = einfo.IsNullable; 506 selem.Name = einfo.ElementName; 507 508 if (defaultValue != System.DBNull.Value) 509 selem.DefaultValue = ExportDefaultValue (einfo.TypeData, 510 einfo.MappedType, defaultValue); 511 512 if (einfo.Form != XmlSchemaForm.Qualified) 513 selem.Form = einfo.Form; 514 515 switch (einfo.TypeData.SchemaType) 516 { 517 case SchemaTypes.XmlNode: 518 selem.SchemaType = GetSchemaXmlNodeType (); 519 break; 520 521 case SchemaTypes.XmlSerializable: 522 SetSchemaXmlSerializableType (einfo.MappedType as XmlSerializableMapping, selem); 523 ExportXmlSerializableSchema (currentSchema, einfo.MappedType as XmlSerializableMapping); 524 break; 525 526 case SchemaTypes.Enum: 527 selem.SchemaTypeName = new XmlQualifiedName (einfo.MappedType.XmlType, einfo.MappedType.XmlTypeNamespace); 528 ImportNamespace (currentSchema, einfo.MappedType.XmlTypeNamespace); 529 ExportEnumSchema (einfo.MappedType); 530 break; 531 532 case SchemaTypes.Array: 533 XmlQualifiedName atypeName = ExportArraySchema (einfo.MappedType, currentSchema.TargetNamespace); 534 selem.SchemaTypeName = atypeName; 535 ImportNamespace (currentSchema, atypeName.Namespace); 536 break; 537 538 case SchemaTypes.Class: 539 if (einfo.MappedType.TypeData.Type != typeof(object)) { 540 selem.SchemaTypeName = new XmlQualifiedName (einfo.MappedType.XmlType, einfo.MappedType.XmlTypeNamespace); 541 ImportNamespace (currentSchema, einfo.MappedType.XmlTypeNamespace); 542 } 543 else if (encodedFormat) 544 selem.SchemaTypeName = new XmlQualifiedName (einfo.MappedType.XmlType, einfo.MappedType.XmlTypeNamespace); 545 546 ExportClassSchema (einfo.MappedType); 547 break; 548 549 case SchemaTypes.Primitive: 550 selem.SchemaTypeName = new XmlQualifiedName (einfo.TypeData.XmlType, einfo.DataTypeNamespace); 551 if (!einfo.TypeData.IsXsdType) { 552 ImportNamespace (currentSchema, einfo.MappedType.XmlTypeNamespace); 553 ExportDerivedSchema (einfo.MappedType); 554 } 555 break; 556 } 557 } 558 else 559 { 560 selem.RefName = new XmlQualifiedName (einfo.ElementName, einfo.Namespace); 561 foreach (XmlSchemaObject ob in memberSchema.Items) 562 if (ob is XmlSchemaElement && ((XmlSchemaElement)ob).Name == einfo.ElementName) 563 return selem; 564 565 GetSchemaElement (memberSchema, einfo, defaultValue, false, 566 new XmlSchemaObjectContainer (memberSchema)); 567 } 568 return selem; 569 } 570 ImportNamespace(XmlSchema schema, string ns)571 void ImportNamespace (XmlSchema schema, string ns) 572 { 573 if (ns == null || ns.Length == 0 || 574 ns == schema.TargetNamespace || ns == XmlSchema.Namespace) return; 575 576 foreach (XmlSchemaObject sob in schema.Includes) 577 if ((sob is XmlSchemaImport) && ((XmlSchemaImport)sob).Namespace == ns) return; 578 579 XmlSchemaImport imp = new XmlSchemaImport (); 580 imp.Namespace = ns; 581 schema.Includes.Add (imp); 582 } 583 DefinedInBaseMap(XmlTypeMapping map, XmlTypeMapMember member)584 bool DefinedInBaseMap (XmlTypeMapping map, XmlTypeMapMember member) 585 { 586 if (((ClassMap)map.ObjectMap).FindMember (member.Name) != null) 587 return true; 588 else if (map.BaseMap != null) 589 return DefinedInBaseMap (map.BaseMap, member); 590 else 591 return false; 592 } 593 GetSchemaXmlNodeType()594 XmlSchemaType GetSchemaXmlNodeType () 595 { 596 XmlSchemaComplexType stype = new XmlSchemaComplexType (); 597 stype.IsMixed = true; 598 XmlSchemaSequence seq = new XmlSchemaSequence (); 599 seq.Items.Add (new XmlSchemaAny ()); 600 stype.Particle = seq; 601 return stype; 602 } 603 SetSchemaXmlSerializableType(XmlSerializableMapping map, XmlSchemaElement elem)604 void SetSchemaXmlSerializableType (XmlSerializableMapping map, XmlSchemaElement elem) 605 { 606 if (map.SchemaType != null && map.Schema != null) { 607 elem.SchemaType = map.SchemaType; 608 return; 609 } 610 611 if (map.SchemaType == null && map.SchemaTypeName != null) { 612 elem.SchemaTypeName = map.SchemaTypeName; 613 elem.Name = map.SchemaTypeName.Name; 614 return; 615 } 616 XmlSchemaComplexType stype = new XmlSchemaComplexType (); 617 XmlSchemaSequence seq = new XmlSchemaSequence (); 618 if (map.Schema == null) { 619 XmlSchemaElement selem = new XmlSchemaElement (); 620 selem.RefName = new XmlQualifiedName ("schema",XmlSchema.Namespace); 621 seq.Items.Add (selem); 622 seq.Items.Add (new XmlSchemaAny ()); 623 } else { 624 XmlSchemaAny any = new XmlSchemaAny (); 625 any.Namespace = map.Schema.TargetNamespace; 626 seq.Items.Add (any); 627 } 628 stype.Particle = seq; 629 elem.SchemaType = stype; 630 } 631 GetSchemaSimpleListType(TypeData typeData)632 XmlSchemaSimpleType GetSchemaSimpleListType (TypeData typeData) 633 { 634 XmlSchemaSimpleType stype = new XmlSchemaSimpleType (); 635 XmlSchemaSimpleTypeList list = new XmlSchemaSimpleTypeList (); 636 TypeData itemTypeData = TypeTranslator.GetTypeData (typeData.ListItemType); 637 list.ItemTypeName = new XmlQualifiedName (itemTypeData.XmlType, XmlSchema.Namespace); 638 stype.Content = list; 639 return stype; 640 } 641 GetSchemaArrayElement(XmlSchema currentSchema, XmlTypeMapElementInfoList infos)642 XmlSchemaParticle GetSchemaArrayElement (XmlSchema currentSchema, XmlTypeMapElementInfoList infos) 643 { 644 int numInfos = infos.Count; 645 if (numInfos > 0 && ((XmlTypeMapElementInfo)infos[0]).IsTextElement) numInfos--; 646 if (numInfos == 0) return null; 647 648 if (numInfos == 1) 649 { 650 XmlSchemaParticle selem = GetSchemaElement (currentSchema, (XmlTypeMapElementInfo) infos[infos.Count-1], true); 651 selem.MinOccursString = "0"; 652 selem.MaxOccursString = "unbounded"; 653 return selem; 654 } 655 else 656 { 657 XmlSchemaChoice schoice = new XmlSchemaChoice (); 658 schoice.MinOccursString = "0"; 659 schoice.MaxOccursString = "unbounded"; 660 foreach (XmlTypeMapElementInfo einfo in infos) 661 { 662 if (einfo.IsTextElement) continue; 663 schoice.Items.Add (GetSchemaElement (currentSchema, einfo, true)); 664 } 665 return schoice; 666 } 667 } 668 ExportDefaultValue(TypeData typeData, XmlTypeMapping map, object defaultValue)669 string ExportDefaultValue (TypeData typeData, XmlTypeMapping map, object defaultValue) 670 { 671 if (typeData.SchemaType == SchemaTypes.Enum) { 672 EnumMap enumMap = (EnumMap) map.ObjectMap; 673 // get corresponding xml name 674 return enumMap.GetXmlName (map.TypeFullName, defaultValue); 675 } 676 return XmlCustomFormatter.ToXmlString (typeData, defaultValue); 677 } 678 ExportDerivedSchema(XmlTypeMapping map)679 void ExportDerivedSchema(XmlTypeMapping map) { 680 if (IsMapExported (map)) return; 681 SetMapExported (map); 682 683 XmlSchema schema = GetSchema (map.XmlTypeNamespace); 684 for (int i = 0; i < schema.Items.Count; i++) { 685 XmlSchemaSimpleType item = schema.Items [i] as XmlSchemaSimpleType; 686 if (item != null && item.Name == map.ElementName) 687 return; 688 } 689 XmlSchemaSimpleType stype = new XmlSchemaSimpleType (); 690 stype.Name = map.ElementName; 691 schema.Items.Add (stype); 692 693 XmlSchemaSimpleTypeRestriction rest = new XmlSchemaSimpleTypeRestriction (); 694 rest.BaseTypeName = new XmlQualifiedName (map.TypeData.MappedType.XmlType, XmlSchema.Namespace); 695 XmlSchemaPatternFacet facet = map.TypeData.XmlSchemaPatternFacet; 696 if (facet != null) 697 rest.Facets.Add(facet); 698 stype.Content = rest; 699 } 700 ExportEnumSchema(XmlTypeMapping map)701 void ExportEnumSchema (XmlTypeMapping map) 702 { 703 if (IsMapExported (map)) return; 704 SetMapExported (map); 705 706 XmlSchema schema = GetSchema (map.XmlTypeNamespace); 707 XmlSchemaSimpleType stype = new XmlSchemaSimpleType (); 708 stype.Name = map.ElementName; 709 schema.Items.Add (stype); 710 711 XmlSchemaSimpleTypeRestriction rest = new XmlSchemaSimpleTypeRestriction (); 712 rest.BaseTypeName = new XmlQualifiedName ("string",XmlSchema.Namespace); 713 EnumMap emap = (EnumMap) map.ObjectMap; 714 715 foreach (EnumMap.EnumMapMember emem in emap.Members) 716 { 717 XmlSchemaEnumerationFacet ef = new XmlSchemaEnumerationFacet (); 718 ef.Value = emem.XmlName; 719 rest.Facets.Add (ef); 720 } 721 722 if (emap.IsFlags) { 723 XmlSchemaSimpleTypeList slist = new XmlSchemaSimpleTypeList (); 724 XmlSchemaSimpleType restrictionType = new XmlSchemaSimpleType (); 725 restrictionType.Content = rest; 726 slist.ItemType = restrictionType; 727 stype.Content = slist; 728 } else { 729 stype.Content = rest; 730 } 731 } 732 ExportArraySchema(XmlTypeMapping map, string defaultNamespace)733 XmlQualifiedName ExportArraySchema (XmlTypeMapping map, string defaultNamespace) 734 { 735 ListMap lmap = (ListMap) map.ObjectMap; 736 737 if (encodedFormat) 738 { 739 string name, ns, schemaNs; 740 lmap.GetArrayType (-1, out name, out ns); 741 if (ns == XmlSchema.Namespace) schemaNs = defaultNamespace; 742 else schemaNs = ns; 743 744 if (IsMapExported (map)) return new XmlQualifiedName (lmap.GetSchemaArrayName (), schemaNs); 745 SetMapExported (map); 746 747 XmlSchema schema = GetSchema (schemaNs); 748 XmlSchemaComplexType stype = new XmlSchemaComplexType (); 749 stype.Name = lmap.GetSchemaArrayName (); 750 schema.Items.Add (stype); 751 752 XmlSchemaComplexContent content = new XmlSchemaComplexContent(); 753 content.IsMixed = false; 754 stype.ContentModel = content; 755 756 XmlSchemaComplexContentRestriction rest = new XmlSchemaComplexContentRestriction (); 757 content.Content = rest; 758 rest.BaseTypeName = new XmlQualifiedName ("Array", XmlSerializer.EncodingNamespace); 759 XmlSchemaAttribute at = new XmlSchemaAttribute (); 760 rest.Attributes.Add (at); 761 at.RefName = new XmlQualifiedName ("arrayType", XmlSerializer.EncodingNamespace); 762 763 XmlAttribute arrayType = Document.CreateAttribute ("arrayType", XmlSerializer.WsdlNamespace); 764 arrayType.Value = ns + (ns != "" ? ":" : "") + name; 765 at.UnhandledAttributes = new XmlAttribute [] { arrayType }; 766 ImportNamespace (schema, XmlSerializer.WsdlNamespace); 767 768 XmlTypeMapElementInfo einfo = (XmlTypeMapElementInfo) lmap.ItemInfo[0]; 769 if (einfo.MappedType != null) 770 { 771 switch (einfo.TypeData.SchemaType) 772 { 773 case SchemaTypes.Enum: 774 ExportEnumSchema (einfo.MappedType); 775 break; 776 case SchemaTypes.Array: 777 ExportArraySchema (einfo.MappedType, schemaNs); 778 break; 779 case SchemaTypes.Class: 780 ExportClassSchema (einfo.MappedType); 781 break; 782 } 783 } 784 785 return new XmlQualifiedName (lmap.GetSchemaArrayName (), schemaNs); 786 } 787 else 788 { 789 if (IsMapExported (map)) return new XmlQualifiedName (map.XmlType, map.XmlTypeNamespace); 790 791 SetMapExported (map); 792 XmlSchema schema = GetSchema (map.XmlTypeNamespace); 793 XmlSchemaComplexType stype = new XmlSchemaComplexType (); 794 stype.Name = map.ElementName; 795 schema.Items.Add (stype); 796 797 XmlSchemaParticle spart = GetSchemaArrayElement (schema, lmap.ItemInfo); 798 if (spart is XmlSchemaChoice) 799 stype.Particle = spart; 800 else 801 { 802 XmlSchemaSequence seq = new XmlSchemaSequence (); 803 seq.Items.Add (spart); 804 stype.Particle = seq; 805 } 806 807 return new XmlQualifiedName (map.XmlType, map.XmlTypeNamespace); 808 } 809 } 810 811 XmlDocument Document 812 { 813 get 814 { 815 if (xmlDoc == null) xmlDoc = new XmlDocument (); 816 return xmlDoc; 817 } 818 } 819 IsMapExported(XmlTypeMapping map)820 bool IsMapExported (XmlTypeMapping map) 821 { 822 if (exportedMaps.ContainsKey (GetMapKey(map))) return true; 823 return false; 824 } 825 SetMapExported(XmlTypeMapping map)826 void SetMapExported (XmlTypeMapping map) 827 { 828 exportedMaps [GetMapKey(map)] = map; 829 } 830 IsElementExported(XmlTypeMapping map)831 bool IsElementExported (XmlTypeMapping map) 832 { 833 if (exportedElements.ContainsKey (GetMapKey(map))) return true; 834 if (map.TypeData.Type == typeof(object)) return true; 835 return false; 836 } 837 SetElementExported(XmlTypeMapping map)838 void SetElementExported (XmlTypeMapping map) 839 { 840 exportedElements [GetMapKey(map)] = map; 841 } 842 GetMapKey(XmlTypeMapping map)843 string GetMapKey (XmlTypeMapping map) 844 { 845 // Don't use type name for array types, since we can have different 846 // classes that represent the same array type (for example 847 // StringCollection and string[]). 848 849 if (map.TypeData.IsListType) 850 return GetArrayKeyName (map.TypeData) + " " + map.XmlType + " " + map.XmlTypeNamespace; 851 else 852 return map.TypeData.FullTypeName + " " + map.XmlType + " " + map.XmlTypeNamespace; 853 } 854 GetArrayKeyName(TypeData td)855 string GetArrayKeyName (TypeData td) 856 { 857 TypeData etd = td.ListItemTypeData; 858 return "*arrayof*" + (etd.IsListType ? GetArrayKeyName (etd) : etd.FullTypeName); 859 } 860 CompileSchemas()861 void CompileSchemas () 862 { 863 // foreach (XmlSchema sc in schemas) 864 // sc.Compile (null); 865 } 866 GetSchema(string ns)867 XmlSchema GetSchema (string ns) 868 { 869 XmlSchema schema = schemas [ns]; 870 if (schema == null) 871 { 872 schema = new XmlSchema (); 873 if (ns != null && ns.Length > 0) 874 schema.TargetNamespace = ns; 875 if (!encodedFormat) 876 schema.ElementFormDefault = XmlSchemaForm.Qualified; 877 schemas.Add (schema); 878 } 879 return schema; 880 } 881 882 #endregion // Methods 883 884 private class XmlSchemaObjectContainer 885 { 886 private readonly XmlSchemaObject _xmlSchemaObject; 887 XmlSchemaObjectContainer(XmlSchema schema)888 public XmlSchemaObjectContainer (XmlSchema schema) 889 { 890 _xmlSchemaObject = schema; 891 } 892 XmlSchemaObjectContainer(XmlSchemaGroupBase group)893 public XmlSchemaObjectContainer (XmlSchemaGroupBase group) 894 { 895 _xmlSchemaObject = group; 896 } 897 898 public XmlSchemaObjectCollection Items { 899 get { 900 if (_xmlSchemaObject is XmlSchema) { 901 return ((XmlSchema) _xmlSchemaObject).Items; 902 } else { 903 return ((XmlSchemaGroupBase) _xmlSchemaObject).Items; 904 } 905 } 906 } 907 } 908 } 909 } 910