//
// System.Xml.Serialization.XmlSchemaExporter
//
// Author:
// Tim Coleman (tim@timcoleman.com)
// Lluis Sanchez Gual (lluis@ximian.com)
//
// Copyright (C) Tim Coleman, 2002
//
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System.Xml;
using System.Xml.Schema;
using System.Collections;
namespace System.Xml.Serialization{
public class XmlSchemaExporter {
#region Fields
XmlSchemas schemas;
Hashtable exportedMaps = new Hashtable();
Hashtable exportedElements = new Hashtable();
bool encodedFormat = false;
XmlDocument xmlDoc;
#endregion
#region Constructors
public XmlSchemaExporter (XmlSchemas schemas)
{
this.schemas = schemas;
}
internal XmlSchemaExporter (XmlSchemas schemas, bool encodedFormat)
{
this.encodedFormat = encodedFormat;
this.schemas = schemas;
}
#endregion // Constructors
#region Methods
[MonoTODO]
public string ExportAnyType (string ns)
{
throw new NotImplementedException ();
}
#if NET_2_0
[MonoNotSupported("")]
public string ExportAnyType (XmlMembersMapping members)
{
throw new NotImplementedException ();
}
#endif
public void ExportMembersMapping (XmlMembersMapping xmlMembersMapping)
{
ExportMembersMapping (xmlMembersMapping, true);
}
#if NET_2_0
public
#else
internal
#endif
void ExportMembersMapping (XmlMembersMapping xmlMembersMapping, bool exportEnclosingType)
{
ClassMap cmap = (ClassMap) xmlMembersMapping.ObjectMap;
if (xmlMembersMapping.HasWrapperElement && exportEnclosingType)
{
XmlSchema schema = GetSchema (xmlMembersMapping.Namespace);
XmlSchemaComplexType stype = new XmlSchemaComplexType ();
XmlSchemaSequence particle;
XmlSchemaAnyAttribute anyAttribute;
ExportMembersMapSchema (schema, cmap, null, stype.Attributes, out particle, out anyAttribute);
stype.Particle = particle;
stype.AnyAttribute = anyAttribute;
if (encodedFormat)
{
stype.Name = xmlMembersMapping.ElementName;
schema.Items.Add (stype);
}
else
{
XmlSchemaElement selem = new XmlSchemaElement ();
selem.Name = xmlMembersMapping.ElementName;
selem.SchemaType = stype;
schema.Items.Add (selem);
}
}
else
{
ICollection members = cmap.ElementMembers;
if (members != null)
{
foreach (XmlTypeMapMemberElement member in members)
{
if (member is XmlTypeMapMemberAnyElement && member.TypeData.IsListType)
{
XmlSchema mschema = GetSchema (xmlMembersMapping.Namespace);
XmlSchemaParticle par = GetSchemaArrayElement (mschema, member.ElementInfo);
if (par is XmlSchemaAny)
{
XmlSchemaComplexType ct = FindComplexType (mschema.Items, "any");
if (ct != null) continue;
ct = new XmlSchemaComplexType ();
ct.Name = "any";
ct.IsMixed = true;
XmlSchemaSequence seq = new XmlSchemaSequence ();
ct.Particle = seq;
seq.Items.Add (par);
mschema.Items.Add (ct);
continue;
}
}
XmlTypeMapElementInfo einfo = (XmlTypeMapElementInfo) member.ElementInfo [0];
XmlSchema schema;
if (encodedFormat)
{
schema = GetSchema (xmlMembersMapping.Namespace);
ImportNamespace (schema, XmlSerializer.EncodingNamespace);
}
else
schema = GetSchema (einfo.Namespace);
XmlSchemaElement exe = FindElement (schema.Items, einfo.ElementName);
XmlSchemaElement elem;
XmlSchemaObjectContainer container = null;
// In encoded format, the schema elements are not needed
if (!encodedFormat)
container = new XmlSchemaObjectContainer (schema);
Type memType = member.GetType();
if (member is XmlTypeMapMemberFlatList)
throw new InvalidOperationException ("Unwrapped arrays not supported as parameters");
else if (memType == typeof(XmlTypeMapMemberElement))
elem = (XmlSchemaElement) GetSchemaElement (schema,
einfo, member.DefaultValue, false, container);
else
elem = (XmlSchemaElement) GetSchemaElement (schema,
einfo, false, container);
if (exe != null)
{
if (exe.SchemaTypeName.Equals (elem.SchemaTypeName))
schema.Items.Remove (elem);
else
{
string s = "The XML element named '" + einfo.ElementName + "' ";
s += "from namespace '" + schema.TargetNamespace + "' references distinct types " + elem.SchemaTypeName.Name + " and " + exe.SchemaTypeName.Name + ". ";
s += "Use XML attributes to specify another XML name or namespace for the element or types.";
throw new InvalidOperationException (s);
}
}
}
}
}
CompileSchemas ();
}
[MonoTODO]
public XmlQualifiedName ExportTypeMapping (XmlMembersMapping xmlMembersMapping)
{
throw new NotImplementedException ();
}
public void ExportTypeMapping (XmlTypeMapping xmlTypeMapping)
{
if (!xmlTypeMapping.IncludeInSchema) return;
if (IsElementExported (xmlTypeMapping)) return;
if (encodedFormat)
{
ExportClassSchema (xmlTypeMapping);
XmlSchema schema = GetSchema (xmlTypeMapping.XmlTypeNamespace);
ImportNamespace (schema, XmlSerializer.EncodingNamespace);
}
else
{
XmlSchema schema = GetSchema (xmlTypeMapping.Namespace);
XmlTypeMapElementInfo einfo = new XmlTypeMapElementInfo (null, xmlTypeMapping.TypeData);
einfo.Namespace = xmlTypeMapping.Namespace;
einfo.ElementName = xmlTypeMapping.ElementName;
if (xmlTypeMapping.TypeData.IsComplexType)
einfo.MappedType = xmlTypeMapping;
einfo.IsNullable = xmlTypeMapping.IsNullable;
GetSchemaElement (schema, einfo, false, new XmlSchemaObjectContainer (schema));
SetElementExported (xmlTypeMapping);
}
CompileSchemas ();
}
void ExportXmlSerializableSchema (XmlSchema currentSchema, XmlSerializableMapping map)
{
if (IsMapExported (map)) return;
SetMapExported (map);
if (map.Schema == null) return;
string targetNs = map.Schema.TargetNamespace;
XmlSchema existingSchema = schemas [targetNs];
if (existingSchema == null)
{
schemas.Add (map.Schema);
ImportNamespace (currentSchema, targetNs);
}
else if (existingSchema != map.Schema && !CanBeDuplicated (existingSchema, map.Schema))
{
throw new InvalidOperationException("The namespace '" + targetNs +"' defined by the class '" + map.TypeFullName + "' is a duplicate.");
}
}
private static bool CanBeDuplicated (XmlSchema existingSchema, XmlSchema schema)
{
if(XmlSchemas.IsDataSet (existingSchema) && XmlSchemas.IsDataSet (schema)
&& existingSchema.Id == schema.Id)
return true;
return false;
}
void ExportClassSchema (XmlTypeMapping map)
{
if (IsMapExported (map)) return;
SetMapExported (map);
if (map.TypeData.Type == typeof(object))
{
foreach (XmlTypeMapping dmap in map.DerivedTypes)
if (dmap.TypeData.SchemaType == SchemaTypes.Class) ExportClassSchema (dmap);
return;
}
XmlSchema schema = GetSchema (map.XmlTypeNamespace);
XmlSchemaComplexType stype = new XmlSchemaComplexType ();
stype.Name = map.XmlType;
schema.Items.Add (stype);
ClassMap cmap = (ClassMap)map.ObjectMap;
if (cmap.HasSimpleContent)
{
XmlSchemaSimpleContent simple = new XmlSchemaSimpleContent ();
stype.ContentModel = simple;
XmlSchemaSimpleContentExtension ext = new XmlSchemaSimpleContentExtension ();
simple.Content = ext;
XmlSchemaSequence particle;
XmlSchemaAnyAttribute anyAttribute;
ExportMembersMapSchema (schema, cmap, map.BaseMap, ext.Attributes, out particle, out anyAttribute);
ext.AnyAttribute = anyAttribute;
if (map.BaseMap == null)
ext.BaseTypeName = cmap.SimpleContentBaseType;
else {
ext.BaseTypeName = new XmlQualifiedName (map.BaseMap.XmlType, map.BaseMap.XmlTypeNamespace);
ImportNamespace (schema, map.BaseMap.XmlTypeNamespace);
ExportClassSchema (map.BaseMap);
}
}
else if (map.BaseMap != null && map.BaseMap.IncludeInSchema)
{
XmlSchemaComplexContent cstype = new XmlSchemaComplexContent ();
XmlSchemaComplexContentExtension ext = new XmlSchemaComplexContentExtension ();
ext.BaseTypeName = new XmlQualifiedName (map.BaseMap.XmlType, map.BaseMap.XmlTypeNamespace);
cstype.Content = ext;
stype.ContentModel = cstype;
XmlSchemaSequence particle;
XmlSchemaAnyAttribute anyAttribute;
ExportMembersMapSchema (schema, cmap, map.BaseMap, ext.Attributes, out particle, out anyAttribute);
ext.Particle = particle;
ext.AnyAttribute = anyAttribute;
stype.IsMixed = HasMixedContent (map);
cstype.IsMixed = BaseHasMixedContent (map);
ImportNamespace (schema, map.BaseMap.XmlTypeNamespace);
ExportClassSchema (map.BaseMap);
}
else
{
XmlSchemaSequence particle;
XmlSchemaAnyAttribute anyAttribute;
ExportMembersMapSchema (schema, cmap, map.BaseMap, stype.Attributes, out particle, out anyAttribute);
stype.Particle = particle;
stype.AnyAttribute = anyAttribute;
stype.IsMixed = cmap.XmlTextCollector != null;
}
foreach (XmlTypeMapping dmap in map.DerivedTypes)
if (dmap.TypeData.SchemaType == SchemaTypes.Class) ExportClassSchema (dmap);
}
bool BaseHasMixedContent (XmlTypeMapping map)
{
ClassMap cmap = (ClassMap)map.ObjectMap;
return (cmap.XmlTextCollector != null && (map.BaseMap != null && DefinedInBaseMap (map.BaseMap, cmap.XmlTextCollector)));
}
bool HasMixedContent (XmlTypeMapping map)
{
ClassMap cmap = (ClassMap)map.ObjectMap;
return (cmap.XmlTextCollector != null && (map.BaseMap == null || !DefinedInBaseMap (map.BaseMap, cmap.XmlTextCollector)));
}
void ExportMembersMapSchema (XmlSchema schema, ClassMap map, XmlTypeMapping baseMap, XmlSchemaObjectCollection outAttributes, out XmlSchemaSequence particle, out XmlSchemaAnyAttribute anyAttribute)
{
particle = null;
XmlSchemaSequence seq = new XmlSchemaSequence ();
ICollection members = map.ElementMembers;
if (members != null && !map.HasSimpleContent)
{
foreach (XmlTypeMapMemberElement member in members)
{
if (baseMap != null && DefinedInBaseMap (baseMap, member)) continue;
Type memType = member.GetType();
if (memType == typeof(XmlTypeMapMemberFlatList))
{
XmlSchemaParticle part = GetSchemaArrayElement (schema, member.ElementInfo);
if (part != null) seq.Items.Add (part);
}
else if (memType == typeof(XmlTypeMapMemberAnyElement))
{
seq.Items.Add (GetSchemaArrayElement (schema, member.ElementInfo));
}
else if (memType == typeof(XmlTypeMapMemberElement))
{
GetSchemaElement (schema, (XmlTypeMapElementInfo) member.ElementInfo [0],
member.DefaultValue, true, new XmlSchemaObjectContainer (seq));
}
else
{
GetSchemaElement (schema, (XmlTypeMapElementInfo) member.ElementInfo[0],
true, new XmlSchemaObjectContainer (seq));
}
}
}
if (seq.Items.Count > 0)
particle = seq;
// Write attributes
ICollection attributes = map.AttributeMembers;
if (attributes != null)
{
foreach (XmlTypeMapMemberAttribute attr in attributes) {
if (baseMap != null && DefinedInBaseMap (baseMap, attr)) continue;
outAttributes.Add (GetSchemaAttribute (schema, attr, true));
}
}
XmlTypeMapMember anyAttrMember = map.DefaultAnyAttributeMember;
if (anyAttrMember != null)
anyAttribute = new XmlSchemaAnyAttribute ();
else
anyAttribute = null;
}
XmlSchemaElement FindElement (XmlSchemaObjectCollection col, string name)
{
foreach (XmlSchemaObject ob in col)
{
XmlSchemaElement elem = ob as XmlSchemaElement;
if (elem != null && elem.Name == name) return elem;
}
return null;
}
XmlSchemaComplexType FindComplexType (XmlSchemaObjectCollection col, string name)
{
foreach (XmlSchemaObject ob in col)
{
XmlSchemaComplexType ctype = ob as XmlSchemaComplexType;
if (ctype != null && ctype.Name == name) return ctype;
}
return null;
}
XmlSchemaAttribute GetSchemaAttribute (XmlSchema currentSchema, XmlTypeMapMemberAttribute attinfo, bool isTypeMember)
{
XmlSchemaAttribute sat = new XmlSchemaAttribute ();
if (attinfo.DefaultValue != System.DBNull.Value) {
sat.DefaultValue = ExportDefaultValue (attinfo.TypeData,
attinfo.MappedType, attinfo.DefaultValue);
} else {
if (!attinfo.IsOptionalValueType && attinfo.TypeData.IsValueType)
sat.Use = XmlSchemaUse.Required;
}
ImportNamespace (currentSchema, attinfo.Namespace);
XmlSchema memberSchema;
if (attinfo.Namespace.Length == 0 && attinfo.Form != XmlSchemaForm.Qualified)
memberSchema = currentSchema;
else
memberSchema = GetSchema (attinfo.Namespace);
if (currentSchema == memberSchema || encodedFormat)
{
sat.Name = attinfo.AttributeName;
if (isTypeMember) sat.Form = attinfo.Form;
if (attinfo.TypeData.SchemaType == SchemaTypes.Enum)
{
ImportNamespace (currentSchema, attinfo.DataTypeNamespace);
ExportEnumSchema (attinfo.MappedType);
sat.SchemaTypeName = new XmlQualifiedName (attinfo.TypeData.XmlType, attinfo.DataTypeNamespace);
}
else if (attinfo.TypeData.SchemaType == SchemaTypes.Array && TypeTranslator.IsPrimitive (attinfo.TypeData.ListItemType))
{
sat.SchemaType = GetSchemaSimpleListType (attinfo.TypeData);
}
else
sat.SchemaTypeName = new XmlQualifiedName (attinfo.TypeData.XmlType, attinfo.DataTypeNamespace);;
}
else
{
sat.RefName = new XmlQualifiedName (attinfo.AttributeName, attinfo.Namespace);
foreach (XmlSchemaObject ob in memberSchema.Items)
if (ob is XmlSchemaAttribute && ((XmlSchemaAttribute)ob).Name == attinfo.AttributeName)
return sat;
memberSchema.Items.Add (GetSchemaAttribute (memberSchema, attinfo, false));
}
return sat;
}
XmlSchemaParticle GetSchemaElement (XmlSchema currentSchema, XmlTypeMapElementInfo einfo, bool isTypeMember)
{
return GetSchemaElement (currentSchema, einfo, System.DBNull.Value,
isTypeMember, (XmlSchemaObjectContainer) null);
}
XmlSchemaParticle GetSchemaElement (XmlSchema currentSchema, XmlTypeMapElementInfo einfo, bool isTypeMember, XmlSchemaObjectContainer container)
{
return GetSchemaElement (currentSchema, einfo, System.DBNull.Value, isTypeMember, container);
}
XmlSchemaParticle GetSchemaElement (XmlSchema currentSchema, XmlTypeMapElementInfo einfo, object defaultValue, bool isTypeMember, XmlSchemaObjectContainer container)
{
if (einfo.IsTextElement) return null;
if (einfo.IsUnnamedAnyElement)
{
XmlSchemaAny any = new XmlSchemaAny ();
any.MinOccurs = 0;
any.MaxOccurs = 1;
if (container != null)
container.Items.Add (any);
return any;
}
XmlSchemaElement selem = new XmlSchemaElement ();
selem.IsNillable = einfo.IsNullable;
if (container != null)
container.Items.Add (selem);
if (isTypeMember)
{
selem.MaxOccurs = 1;
selem.MinOccurs = einfo.IsNullable ? 1 : 0;
if ((defaultValue == DBNull.Value && einfo.TypeData.IsValueType && einfo.Member != null && !einfo.Member.IsOptionalValueType) || encodedFormat)
selem.MinOccurs = 1;
}
XmlSchema memberSchema = null;
if (!encodedFormat)
{
memberSchema = GetSchema (einfo.Namespace);
ImportNamespace (currentSchema, einfo.Namespace);
}
if (currentSchema == memberSchema || encodedFormat || !isTypeMember)
{
if (isTypeMember) selem.IsNillable = einfo.IsNullable;
selem.Name = einfo.ElementName;
if (defaultValue != System.DBNull.Value)
selem.DefaultValue = ExportDefaultValue (einfo.TypeData,
einfo.MappedType, defaultValue);
if (einfo.Form != XmlSchemaForm.Qualified)
selem.Form = einfo.Form;
switch (einfo.TypeData.SchemaType)
{
case SchemaTypes.XmlNode:
selem.SchemaType = GetSchemaXmlNodeType ();
break;
case SchemaTypes.XmlSerializable:
SetSchemaXmlSerializableType (einfo.MappedType as XmlSerializableMapping, selem);
ExportXmlSerializableSchema (currentSchema, einfo.MappedType as XmlSerializableMapping);
break;
case SchemaTypes.Enum:
selem.SchemaTypeName = new XmlQualifiedName (einfo.MappedType.XmlType, einfo.MappedType.XmlTypeNamespace);
ImportNamespace (currentSchema, einfo.MappedType.XmlTypeNamespace);
ExportEnumSchema (einfo.MappedType);
break;
case SchemaTypes.Array:
XmlQualifiedName atypeName = ExportArraySchema (einfo.MappedType, currentSchema.TargetNamespace);
selem.SchemaTypeName = atypeName;
ImportNamespace (currentSchema, atypeName.Namespace);
break;
case SchemaTypes.Class:
if (einfo.MappedType.TypeData.Type != typeof(object)) {
selem.SchemaTypeName = new XmlQualifiedName (einfo.MappedType.XmlType, einfo.MappedType.XmlTypeNamespace);
ImportNamespace (currentSchema, einfo.MappedType.XmlTypeNamespace);
}
else if (encodedFormat)
selem.SchemaTypeName = new XmlQualifiedName (einfo.MappedType.XmlType, einfo.MappedType.XmlTypeNamespace);
ExportClassSchema (einfo.MappedType);
break;
case SchemaTypes.Primitive:
selem.SchemaTypeName = new XmlQualifiedName (einfo.TypeData.XmlType, einfo.DataTypeNamespace);
if (!einfo.TypeData.IsXsdType) {
ImportNamespace (currentSchema, einfo.MappedType.XmlTypeNamespace);
ExportDerivedSchema (einfo.MappedType);
}
break;
}
}
else
{
selem.RefName = new XmlQualifiedName (einfo.ElementName, einfo.Namespace);
foreach (XmlSchemaObject ob in memberSchema.Items)
if (ob is XmlSchemaElement && ((XmlSchemaElement)ob).Name == einfo.ElementName)
return selem;
GetSchemaElement (memberSchema, einfo, defaultValue, false,
new XmlSchemaObjectContainer (memberSchema));
}
return selem;
}
void ImportNamespace (XmlSchema schema, string ns)
{
if (ns == null || ns.Length == 0 ||
ns == schema.TargetNamespace || ns == XmlSchema.Namespace) return;
foreach (XmlSchemaObject sob in schema.Includes)
if ((sob is XmlSchemaImport) && ((XmlSchemaImport)sob).Namespace == ns) return;
XmlSchemaImport imp = new XmlSchemaImport ();
imp.Namespace = ns;
schema.Includes.Add (imp);
}
bool DefinedInBaseMap (XmlTypeMapping map, XmlTypeMapMember member)
{
if (((ClassMap)map.ObjectMap).FindMember (member.Name) != null)
return true;
else if (map.BaseMap != null)
return DefinedInBaseMap (map.BaseMap, member);
else
return false;
}
XmlSchemaType GetSchemaXmlNodeType ()
{
XmlSchemaComplexType stype = new XmlSchemaComplexType ();
stype.IsMixed = true;
XmlSchemaSequence seq = new XmlSchemaSequence ();
seq.Items.Add (new XmlSchemaAny ());
stype.Particle = seq;
return stype;
}
void SetSchemaXmlSerializableType (XmlSerializableMapping map, XmlSchemaElement elem)
{
#if NET_2_0
if (map.SchemaType != null && map.Schema != null) {
elem.SchemaType = map.SchemaType;
return;
}
if (map.SchemaType == null && map.SchemaTypeName != null) {
elem.SchemaTypeName = map.SchemaTypeName;
elem.Name = map.SchemaTypeName.Name;
return;
}
#endif
XmlSchemaComplexType stype = new XmlSchemaComplexType ();
XmlSchemaSequence seq = new XmlSchemaSequence ();
if (map.Schema == null) {
XmlSchemaElement selem = new XmlSchemaElement ();
selem.RefName = new XmlQualifiedName ("schema",XmlSchema.Namespace);
seq.Items.Add (selem);
seq.Items.Add (new XmlSchemaAny ());
} else {
XmlSchemaAny any = new XmlSchemaAny ();
any.Namespace = map.Schema.TargetNamespace;
seq.Items.Add (any);
}
stype.Particle = seq;
elem.SchemaType = stype;
}
XmlSchemaSimpleType GetSchemaSimpleListType (TypeData typeData)
{
XmlSchemaSimpleType stype = new XmlSchemaSimpleType ();
XmlSchemaSimpleTypeList list = new XmlSchemaSimpleTypeList ();
TypeData itemTypeData = TypeTranslator.GetTypeData (typeData.ListItemType);
list.ItemTypeName = new XmlQualifiedName (itemTypeData.XmlType, XmlSchema.Namespace);
stype.Content = list;
return stype;
}
XmlSchemaParticle GetSchemaArrayElement (XmlSchema currentSchema, XmlTypeMapElementInfoList infos)
{
int numInfos = infos.Count;
if (numInfos > 0 && ((XmlTypeMapElementInfo)infos[0]).IsTextElement) numInfos--;
if (numInfos == 0) return null;
if (numInfos == 1)
{
XmlSchemaParticle selem = GetSchemaElement (currentSchema, (XmlTypeMapElementInfo) infos[infos.Count-1], true);
selem.MinOccursString = "0";
selem.MaxOccursString = "unbounded";
return selem;
}
else
{
XmlSchemaChoice schoice = new XmlSchemaChoice ();
schoice.MinOccursString = "0";
schoice.MaxOccursString = "unbounded";
foreach (XmlTypeMapElementInfo einfo in infos)
{
if (einfo.IsTextElement) continue;
schoice.Items.Add (GetSchemaElement (currentSchema, einfo, true));
}
return schoice;
}
}
string ExportDefaultValue (TypeData typeData, XmlTypeMapping map, object defaultValue)
{
if (typeData.SchemaType == SchemaTypes.Enum) {
EnumMap enumMap = (EnumMap) map.ObjectMap;
// get corresponding xml name
return enumMap.GetXmlName (map.TypeFullName, defaultValue);
}
return XmlCustomFormatter.ToXmlString (typeData, defaultValue);
}
void ExportDerivedSchema(XmlTypeMapping map) {
if (IsMapExported (map)) return;
SetMapExported (map);
XmlSchema schema = GetSchema (map.XmlTypeNamespace);
for (int i = 0; i < schema.Items.Count; i++) {
XmlSchemaSimpleType item = schema.Items [i] as XmlSchemaSimpleType;
if (item != null && item.Name == map.ElementName)
return;
}
XmlSchemaSimpleType stype = new XmlSchemaSimpleType ();
stype.Name = map.ElementName;
schema.Items.Add (stype);
XmlSchemaSimpleTypeRestriction rest = new XmlSchemaSimpleTypeRestriction ();
rest.BaseTypeName = new XmlQualifiedName (map.TypeData.MappedType.XmlType, XmlSchema.Namespace);
XmlSchemaPatternFacet facet = map.TypeData.XmlSchemaPatternFacet;
if (facet != null)
rest.Facets.Add(facet);
stype.Content = rest;
}
void ExportEnumSchema (XmlTypeMapping map)
{
if (IsMapExported (map)) return;
SetMapExported (map);
XmlSchema schema = GetSchema (map.XmlTypeNamespace);
XmlSchemaSimpleType stype = new XmlSchemaSimpleType ();
stype.Name = map.ElementName;
schema.Items.Add (stype);
XmlSchemaSimpleTypeRestriction rest = new XmlSchemaSimpleTypeRestriction ();
rest.BaseTypeName = new XmlQualifiedName ("string",XmlSchema.Namespace);
EnumMap emap = (EnumMap) map.ObjectMap;
foreach (EnumMap.EnumMapMember emem in emap.Members)
{
XmlSchemaEnumerationFacet ef = new XmlSchemaEnumerationFacet ();
ef.Value = emem.XmlName;
rest.Facets.Add (ef);
}
if (emap.IsFlags) {
XmlSchemaSimpleTypeList slist = new XmlSchemaSimpleTypeList ();
XmlSchemaSimpleType restrictionType = new XmlSchemaSimpleType ();
restrictionType.Content = rest;
slist.ItemType = restrictionType;
stype.Content = slist;
} else {
stype.Content = rest;
}
}
XmlQualifiedName ExportArraySchema (XmlTypeMapping map, string defaultNamespace)
{
ListMap lmap = (ListMap) map.ObjectMap;
if (encodedFormat)
{
string name, ns, schemaNs;
lmap.GetArrayType (-1, out name, out ns);
if (ns == XmlSchema.Namespace) schemaNs = defaultNamespace;
else schemaNs = ns;
if (IsMapExported (map)) return new XmlQualifiedName (lmap.GetSchemaArrayName (), schemaNs);
SetMapExported (map);
XmlSchema schema = GetSchema (schemaNs);
XmlSchemaComplexType stype = new XmlSchemaComplexType ();
stype.Name = lmap.GetSchemaArrayName ();
schema.Items.Add (stype);
XmlSchemaComplexContent content = new XmlSchemaComplexContent();
content.IsMixed = false;
stype.ContentModel = content;
XmlSchemaComplexContentRestriction rest = new XmlSchemaComplexContentRestriction ();
content.Content = rest;
rest.BaseTypeName = new XmlQualifiedName ("Array", XmlSerializer.EncodingNamespace);
XmlSchemaAttribute at = new XmlSchemaAttribute ();
rest.Attributes.Add (at);
at.RefName = new XmlQualifiedName ("arrayType", XmlSerializer.EncodingNamespace);
XmlAttribute arrayType = Document.CreateAttribute ("arrayType", XmlSerializer.WsdlNamespace);
arrayType.Value = ns + (ns != "" ? ":" : "") + name;
at.UnhandledAttributes = new XmlAttribute [] { arrayType };
ImportNamespace (schema, XmlSerializer.WsdlNamespace);
XmlTypeMapElementInfo einfo = (XmlTypeMapElementInfo) lmap.ItemInfo[0];
if (einfo.MappedType != null)
{
switch (einfo.TypeData.SchemaType)
{
case SchemaTypes.Enum:
ExportEnumSchema (einfo.MappedType);
break;
case SchemaTypes.Array:
ExportArraySchema (einfo.MappedType, schemaNs);
break;
case SchemaTypes.Class:
ExportClassSchema (einfo.MappedType);
break;
}
}
return new XmlQualifiedName (lmap.GetSchemaArrayName (), schemaNs);
}
else
{
if (IsMapExported (map)) return new XmlQualifiedName (map.XmlType, map.XmlTypeNamespace);
SetMapExported (map);
XmlSchema schema = GetSchema (map.XmlTypeNamespace);
XmlSchemaComplexType stype = new XmlSchemaComplexType ();
stype.Name = map.ElementName;
schema.Items.Add (stype);
XmlSchemaParticle spart = GetSchemaArrayElement (schema, lmap.ItemInfo);
if (spart is XmlSchemaChoice)
stype.Particle = spart;
else
{
XmlSchemaSequence seq = new XmlSchemaSequence ();
seq.Items.Add (spart);
stype.Particle = seq;
}
return new XmlQualifiedName (map.XmlType, map.XmlTypeNamespace);
}
}
XmlDocument Document
{
get
{
if (xmlDoc == null) xmlDoc = new XmlDocument ();
return xmlDoc;
}
}
bool IsMapExported (XmlTypeMapping map)
{
if (exportedMaps.ContainsKey (GetMapKey(map))) return true;
return false;
}
void SetMapExported (XmlTypeMapping map)
{
exportedMaps [GetMapKey(map)] = map;
}
bool IsElementExported (XmlTypeMapping map)
{
if (exportedElements.ContainsKey (GetMapKey(map))) return true;
if (map.TypeData.Type == typeof(object)) return true;
return false;
}
void SetElementExported (XmlTypeMapping map)
{
exportedElements [GetMapKey(map)] = map;
}
string GetMapKey (XmlTypeMapping map)
{
// Don't use type name for array types, since we can have different
// classes that represent the same array type (for example
// StringCollection and string[]).
if (map.TypeData.IsListType)
return GetArrayKeyName (map.TypeData) + " " + map.XmlType + " " + map.XmlTypeNamespace;
else
return map.TypeData.FullTypeName + " " + map.XmlType + " " + map.XmlTypeNamespace;
}
string GetArrayKeyName (TypeData td)
{
TypeData etd = td.ListItemTypeData;
return "*arrayof*" + (etd.IsListType ? GetArrayKeyName (etd) : etd.FullTypeName);
}
void CompileSchemas ()
{
// foreach (XmlSchema sc in schemas)
// sc.Compile (null);
}
XmlSchema GetSchema (string ns)
{
XmlSchema schema = schemas [ns];
if (schema == null)
{
schema = new XmlSchema ();
if (ns != null && ns.Length > 0)
schema.TargetNamespace = ns;
if (!encodedFormat)
schema.ElementFormDefault = XmlSchemaForm.Qualified;
schemas.Add (schema);
}
return schema;
}
#endregion // Methods
private class XmlSchemaObjectContainer
{
private readonly XmlSchemaObject _xmlSchemaObject;
public XmlSchemaObjectContainer (XmlSchema schema)
{
_xmlSchemaObject = schema;
}
public XmlSchemaObjectContainer (XmlSchemaGroupBase group)
{
_xmlSchemaObject = group;
}
public XmlSchemaObjectCollection Items {
get {
if (_xmlSchemaObject is XmlSchema) {
return ((XmlSchema) _xmlSchemaObject).Items;
} else {
return ((XmlSchemaGroupBase) _xmlSchemaObject).Items;
}
}
}
}
}
}
|