Make some S.X.S types compatible with the SL API (for SDK)
[mono.git] / mcs / class / System.XML / System.Xml.Serialization / XmlSerializationWriterInterpreter.cs
1 //
2 // XmlSerializationWriterInterpreter.cs: 
3 //
4 // Author:
5 //   Lluis Sanchez Gual (lluis@ximian.com)
6 //
7 // (C) 2002, 2003 Ximian, Inc.  http://www.ximian.com
8 //
9
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 // 
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 // 
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30
31 using System;
32 using System.Text;
33 using System.Collections;
34 using System.Reflection;
35 using System.Xml.Schema;
36
37 namespace System.Xml.Serialization
38 {
39         internal class XmlSerializationWriterInterpreter: XmlSerializationWriter
40         {
41                 XmlMapping _typeMap;
42                 SerializationFormat _format;
43                 const string xmlNamespace = "http://www.w3.org/2000/xmlns/";
44
45                 public XmlSerializationWriterInterpreter (XmlMapping typeMap)
46                 {
47                         _typeMap = typeMap;
48                         _format = typeMap.Format;
49                 }
50
51                 protected override void InitCallbacks ()
52                 {
53                         ArrayList maps = _typeMap.RelatedMaps;
54                         if (maps != null)
55                         {
56                                 foreach (XmlTypeMapping map in maps)  {
57                                         CallbackInfo info = new CallbackInfo (this, map);
58                                         if (map.TypeData.SchemaType == SchemaTypes.Enum) AddWriteCallback(map.TypeData.Type, map.XmlType, map.Namespace, new XmlSerializationWriteCallback (info.WriteEnum));
59                                         else AddWriteCallback(map.TypeData.Type, map.XmlType, map.Namespace, new XmlSerializationWriteCallback (info.WriteObject));
60                                 }
61                         }
62                 }
63
64                 public void WriteRoot (object ob)
65                 {
66                         WriteStartDocument ();
67
68                         if (_typeMap is XmlTypeMapping)
69                         {
70                                 XmlTypeMapping mp = (XmlTypeMapping) _typeMap;
71                                 if (mp.TypeData.SchemaType == SchemaTypes.Class || mp.TypeData.SchemaType == SchemaTypes.Array) 
72                                         TopLevelElement ();
73
74                                 if (_format == SerializationFormat.Literal)
75                                         WriteObject (mp, ob, mp.ElementName, mp.Namespace, true, false, true);
76                                 else
77                                         WritePotentiallyReferencingElement (mp.ElementName, mp.Namespace, ob, mp.TypeData.Type, true, false);
78                         }
79                         else if (ob is object[])
80                                 WriteMessage ((XmlMembersMapping)_typeMap, (object[]) ob);
81                         else
82                                 throw CreateUnknownTypeException (ob);
83
84                         WriteReferencedElements ();
85                 }
86                 
87                 protected XmlTypeMapping GetTypeMap (Type type)
88                 {
89                         ArrayList maps = _typeMap.RelatedMaps;
90                         if (maps != null)
91                         {
92                                 foreach (XmlTypeMapping map in maps)
93                                         if (map.TypeData.Type == type) return map;
94                         }
95                         throw new InvalidOperationException ("Type " + type + " not mapped");
96                 }
97
98                 protected virtual void WriteObject (XmlTypeMapping typeMap, object ob, string element, string namesp, bool isNullable, bool needType, bool writeWrappingElem)
99                 {
100                         if (ob == null)
101                         {
102                                 if (isNullable) 
103                                 {
104                                         if (_format == SerializationFormat.Literal) WriteNullTagLiteral(element, namesp);
105                                         else WriteNullTagEncoded (element, namesp);
106                                 }
107                                 return;
108                         }
109
110 #if !MOONLIGHT
111                         if (ob is XmlNode)
112                         {
113                                 if (_format == SerializationFormat.Literal) WriteElementLiteral((XmlNode)ob, "", "", true, false);
114                                 else WriteElementEncoded((XmlNode)ob, "", "", true, false);
115                                 return;
116                         }
117 #endif
118
119                         if (typeMap.TypeData.SchemaType == SchemaTypes.XmlSerializable)
120                         {
121                                 WriteSerializable ((IXmlSerializable)ob, element, namesp, isNullable);
122                                 return;
123                         }
124
125                         XmlTypeMapping map = typeMap.GetRealTypeMap (ob.GetType());
126
127                         if (map == null) 
128                         {
129 #if !MOONLIGHT
130                                 // bug #81539
131                                 if (ob.GetType ().IsArray && typeof (XmlNode).IsAssignableFrom (ob.GetType ().GetElementType ())) {
132                                         Writer.WriteStartElement (element, namesp);
133                                         foreach (XmlNode node in (IEnumerable) ob)
134                                                 node.WriteTo (Writer);
135                                         Writer.WriteEndElement ();
136                                 }
137                                 else
138 #endif
139                                         WriteTypedPrimitive (element, namesp, ob, true);
140                                 return;
141                         }
142
143                         if (writeWrappingElem)
144                         {
145                                 if (map != typeMap || _format == SerializationFormat.Encoded) needType = true;
146                                 WriteStartElement (element, namesp, ob);
147                         }
148
149                         if (needType) 
150                                 WriteXsiType(map.XmlType, map.XmlTypeNamespace);
151
152                         switch (map.TypeData.SchemaType)
153                         {
154                                 case SchemaTypes.Class: WriteObjectElement (map, ob, element, namesp); break;
155                                 case SchemaTypes.Array: WriteListElement (map, ob, element, namesp); break;
156                                 case SchemaTypes.Primitive: WritePrimitiveElement (map, ob, element, namesp); break;
157                                 case SchemaTypes.Enum: WriteEnumElement (map, ob, element, namesp); break;
158                         }
159
160                         if (writeWrappingElem)
161                                 WriteEndElement (ob);
162                 }
163
164                 protected virtual void WriteMessage (XmlMembersMapping membersMap, object[] parameters)
165                 {
166                         if (membersMap.HasWrapperElement) {
167                                 TopLevelElement ();
168                                 WriteStartElement(membersMap.ElementName, membersMap.Namespace, (_format == SerializationFormat.Encoded));
169
170                                 if (Writer.LookupPrefix (XmlSchema.Namespace) == null)
171                                         WriteAttribute ("xmlns","xsd",XmlSchema.Namespace,XmlSchema.Namespace);
172         
173                                 if (Writer.LookupPrefix (XmlSchema.InstanceNamespace) == null)
174                                         WriteAttribute ("xmlns","xsi",XmlSchema.InstanceNamespace,XmlSchema.InstanceNamespace);
175                         }
176                         
177                         WriteMembers ((ClassMap)membersMap.ObjectMap, parameters, true);
178
179                         if (membersMap.HasWrapperElement)
180                                 WriteEndElement();
181                 }
182
183                 protected virtual void WriteObjectElement (XmlTypeMapping typeMap, object ob, string element, string namesp)
184                 {
185                         ClassMap map = (ClassMap)typeMap.ObjectMap;
186                         if (map.NamespaceDeclarations != null)
187                                 WriteNamespaceDeclarations ((XmlSerializerNamespaces) map.NamespaceDeclarations.GetValue (ob));
188                         
189                         WriteObjectElementAttributes (typeMap, ob);
190                         WriteObjectElementElements (typeMap, ob);
191                 }
192                 
193                 protected virtual void WriteObjectElementAttributes (XmlTypeMapping typeMap, object ob)
194                 {
195                         ClassMap map = (ClassMap)typeMap.ObjectMap;
196                         WriteAttributeMembers (map, ob, false);
197                 }
198
199                 protected virtual void WriteObjectElementElements (XmlTypeMapping typeMap, object ob)
200                 {
201                         ClassMap map = (ClassMap)typeMap.ObjectMap;
202                         WriteElementMembers (map, ob, false);
203                 }
204
205                 void WriteMembers (ClassMap map, object ob, bool isValueList)
206                 {
207                         WriteAttributeMembers (map, ob, isValueList);
208                         WriteElementMembers (map, ob, isValueList);
209                 }
210                 
211                 void WriteAttributeMembers (ClassMap map, object ob, bool isValueList)
212                 {
213                         // Write attributes
214
215                         XmlTypeMapMember anyAttrMember = map.DefaultAnyAttributeMember;
216 #if !MOONLIGHT
217                         if (anyAttrMember != null && MemberHasValue (anyAttrMember, ob, isValueList))
218                         {
219                                 ICollection extraAtts = (ICollection) GetMemberValue (anyAttrMember, ob, isValueList);
220                                 if (extraAtts != null) 
221                                 {
222                                         foreach (XmlAttribute attr in extraAtts)
223                                                 if (attr.NamespaceURI != xmlNamespace)
224                                                         WriteXmlAttribute (attr, ob);
225                                 }
226                         }
227 #endif
228
229                         ICollection attributes = map.AttributeMembers;
230                         if (attributes != null)
231                         {
232                                 foreach (XmlTypeMapMemberAttribute attr in attributes) {
233                                         if (MemberHasValue (attr, ob, isValueList))
234                                                 WriteAttribute (attr.AttributeName, attr.Namespace, GetStringValue (attr.MappedType, attr.TypeData, GetMemberValue (attr, ob, isValueList)));
235                                 }
236                         }
237                 }
238
239                 void WriteElementMembers (ClassMap map, object ob, bool isValueList)
240                 {
241                         ICollection members = map.ElementMembers;
242                         if (members != null)
243                         {
244                                 foreach (XmlTypeMapMemberElement member in members)
245                                 {
246                                         if (!MemberHasValue (member, ob, isValueList)) continue;
247                                         object memberValue = GetMemberValue (member, ob, isValueList);
248                                         Type memType = member.GetType();
249
250                                         if (memType == typeof(XmlTypeMapMemberList))
251                                         {
252                                                 WriteMemberElement ((XmlTypeMapElementInfo) member.ElementInfo[0], memberValue);
253                                         }
254                                         else if (memType == typeof(XmlTypeMapMemberFlatList))
255                                         {
256                                                 if (memberValue != null)
257                                                         WriteListContent (ob, member.TypeData, ((XmlTypeMapMemberFlatList)member).ListMap, memberValue, null);
258                                         }
259                                         else if (memType == typeof(XmlTypeMapMemberAnyElement))
260                                         {
261                                                 if (memberValue != null)
262                                                         WriteAnyElementContent ((XmlTypeMapMemberAnyElement)member, memberValue);
263                                         }
264                                         else if (memType == typeof(XmlTypeMapMemberAnyAttribute))
265                                         {
266                                                 // Ignore
267                                         }
268                                         else if (memType == typeof(XmlTypeMapMemberElement))
269                                         {
270                                                 XmlTypeMapElementInfo elem = member.FindElement (ob, memberValue);
271                                                 WriteMemberElement (elem, memberValue);
272                                         }
273                                         else
274                                                 throw new InvalidOperationException ("Unknown member type");
275                                 }
276                         }
277                 }
278
279                 object GetMemberValue (XmlTypeMapMember member, object ob, bool isValueList)
280                 {
281                         if (isValueList) return ((object[])ob)[member.GlobalIndex];
282                         else return member.GetValue (ob);
283                 }
284
285                 bool MemberHasValue (XmlTypeMapMember member, object ob, bool isValueList)
286                 {
287                         if (isValueList) {
288                                 if (member.IsOptionalValueType && !member.GetValueSpecified (ob))
289                                         return false;
290                                 return member.GlobalIndex < ((object[])ob).Length;
291                         }
292                         else if (member.DefaultValue != System.DBNull.Value) {
293                                 object val = GetMemberValue (member, ob, isValueList);
294                                 if (val == null && member.DefaultValue == null) return false;
295                                 if (val != null && val.GetType().IsEnum)
296                                 {
297                                         if (val.Equals (member.DefaultValue)) return false;
298                                         Type t = Enum.GetUnderlyingType(val.GetType());
299                                         val = Convert.ChangeType (val, t, null);
300                                 }
301                                 if (val != null && val.Equals (member.DefaultValue)) return false;
302                         }
303                         else if (member.IsOptionalValueType)
304                                 return member.GetValueSpecified (ob);
305
306                         return true;
307                 }
308
309                 void WriteMemberElement (XmlTypeMapElementInfo elem, object memberValue)
310                 {
311                         switch (elem.TypeData.SchemaType)
312                         {
313                                 case SchemaTypes.XmlNode:
314 #if MOONLIGHT
315                                         throw new NotSupportedException ();
316 #else
317                                         string elemName = elem.WrappedElement ? elem.ElementName : "";
318                                         if (_format == SerializationFormat.Literal) WriteElementLiteral(((XmlNode)memberValue), elemName, elem.Namespace, elem.IsNullable, false);
319                                         else WriteElementEncoded(((XmlNode)memberValue), elemName, elem.Namespace, elem.IsNullable, false);
320                                         break;
321 #endif
322
323                                 case SchemaTypes.Enum:
324                                 case SchemaTypes.Primitive:
325                                         if (_format == SerializationFormat.Literal) 
326                                                 WritePrimitiveValueLiteral (memberValue, elem.ElementName, elem.Namespace, elem.MappedType, elem.TypeData, elem.WrappedElement, elem.IsNullable);
327                                         else 
328                                                 WritePrimitiveValueEncoded (memberValue, elem.ElementName, elem.Namespace, new XmlQualifiedName (elem.DataTypeName, elem.DataTypeNamespace), elem.MappedType, elem.TypeData, elem.WrappedElement, elem.IsNullable);
329                                         break;
330
331                                 case SchemaTypes.Array:
332                                         if (memberValue == null) {
333                                                 if (!elem.IsNullable) return;
334                                                 if (_format == SerializationFormat.Literal) WriteNullTagLiteral (elem.ElementName, elem.Namespace);
335                                                 else WriteNullTagEncoded (elem.ElementName, elem.Namespace);
336                                         }
337                                         else if (elem.MappedType.MultiReferenceType) 
338                                                 WriteReferencingElement (elem.ElementName, elem.Namespace, memberValue, elem.IsNullable);
339                                         else {
340                                                 WriteStartElement(elem.ElementName, elem.Namespace, memberValue);
341                                                 WriteListContent (null, elem.TypeData, (ListMap) elem.MappedType.ObjectMap, memberValue, null);
342                                                 WriteEndElement (memberValue);
343                                         }
344                                         break;
345
346                                 case SchemaTypes.Class:
347                                         if (elem.MappedType.MultiReferenceType) {
348                                                 if (elem.MappedType.TypeData.Type == typeof(object))
349                                                         WritePotentiallyReferencingElement (elem.ElementName, elem.Namespace, memberValue, null, false, elem.IsNullable);
350                                                 else
351                                                         WriteReferencingElement (elem.ElementName, elem.Namespace, memberValue, elem.IsNullable);
352                                         }
353                                         else WriteObject (elem.MappedType, memberValue, elem.ElementName, elem.Namespace, elem.IsNullable, false, true);
354                                         break;
355
356                                 case SchemaTypes.XmlSerializable:
357                                         // bug #419973
358                                         if (!elem.MappedType.TypeData.Type.IsInstanceOfType (memberValue))
359                                                 memberValue = ImplicitConvert (memberValue, elem.MappedType.TypeData.Type);
360                                         WriteSerializable ((IXmlSerializable) memberValue, elem.ElementName, elem.Namespace, elem.IsNullable);
361                                         break;
362
363                                 default:
364                                         throw new NotSupportedException ("Invalid value type");
365                         }
366                 }
367
368                 object ImplicitConvert (object obj, Type type)
369                 {
370                         if (obj == null)
371                                 return null;
372                         for (Type t = type; t != typeof (object); t = t.BaseType) {
373                                 MethodInfo mi = t.GetMethod ("op_Implicit", new Type [] {t});
374                                 if (mi != null && mi.ReturnType.IsAssignableFrom (obj.GetType ()))
375                                         return mi.Invoke (null, new object [] {obj});
376                         }
377
378                         for (Type t = obj.GetType (); t != typeof (object); t = t.BaseType) {
379                                 MethodInfo mi = t.GetMethod ("op_Implicit", new Type [] {t});
380                                 if (mi != null && mi.ReturnType == type)
381                                         return mi.Invoke (null, new object [] {obj});
382                         }
383                         return obj;
384                 }
385
386                 void WritePrimitiveValueLiteral (object memberValue, string name, string ns, XmlTypeMapping mappedType, TypeData typeData, bool wrapped, bool isNullable)
387                 {
388                         if (!wrapped) {
389                                 WriteValue (GetStringValue (mappedType, typeData, memberValue));
390                         }
391                         else if (isNullable) {
392                                 if (typeData.Type == typeof(XmlQualifiedName)) WriteNullableQualifiedNameLiteral (name, ns, (XmlQualifiedName)memberValue);
393                                 else WriteNullableStringLiteral (name, ns, GetStringValue (mappedType, typeData, memberValue));
394                         }
395                         else {
396                                 if (typeData.Type == typeof(XmlQualifiedName)) WriteElementQualifiedName (name, ns, (XmlQualifiedName)memberValue);
397                                 else WriteElementString (name, ns, GetStringValue (mappedType, typeData, memberValue));
398                         }
399                 }
400
401                 void WritePrimitiveValueEncoded (object memberValue, string name, string ns, XmlQualifiedName xsiType, XmlTypeMapping mappedType, TypeData typeData, bool wrapped, bool isNullable)
402                 {
403                         if (!wrapped) {
404                                 WriteValue (GetStringValue (mappedType, typeData, memberValue));
405                         }
406                         else if (isNullable) {
407                                 if (typeData.Type == typeof(XmlQualifiedName)) WriteNullableQualifiedNameEncoded (name, ns, (XmlQualifiedName)memberValue, xsiType);
408                                 else WriteNullableStringEncoded (name, ns, GetStringValue (mappedType, typeData, memberValue), xsiType);
409                         }
410                         else {
411                                 if (typeData.Type == typeof(XmlQualifiedName)) WriteElementQualifiedName (name, ns, (XmlQualifiedName)memberValue, xsiType);
412                                 else WriteElementString (name, ns, GetStringValue (mappedType, typeData, memberValue), xsiType);
413                         }
414                 }
415
416                 protected virtual void WriteListElement (XmlTypeMapping typeMap, object ob, string element, string namesp)
417                 {
418                         if (_format == SerializationFormat.Encoded)
419                         {
420                                 string n, ns;
421                                 int itemCount = GetListCount (typeMap.TypeData, ob);
422                                 ((ListMap) typeMap.ObjectMap).GetArrayType (itemCount, out n, out ns);
423                                 string arrayType = (ns != string.Empty) ? FromXmlQualifiedName (new XmlQualifiedName(n,ns)) : n;
424                                 WriteAttribute ("arrayType", XmlSerializer.EncodingNamespace, arrayType);
425                         }
426                         WriteListContent (null, typeMap.TypeData, (ListMap) typeMap.ObjectMap, ob, null);
427                 }
428
429                 void WriteListContent (object container, TypeData listType, ListMap map, object ob, StringBuilder targetString)
430                 {
431                         if (listType.Type.IsArray)
432                         {
433                                 Array array = (Array)ob;
434                                 for (int n=0; n<array.Length; n++)
435                                 {
436                                         object item = array.GetValue (n);
437                                         XmlTypeMapElementInfo info = map.FindElement (container, n, item);
438                                         if (info != null && targetString == null) WriteMemberElement (info, item);
439                                         else if (info != null && targetString != null) targetString.Append (GetStringValue (info.MappedType, info.TypeData, item)).Append (" ");
440                                         else if (item != null) throw CreateUnknownTypeException (item);
441                                 }
442                         }
443                         else if (ob is ICollection)
444                         {
445                                 int count = (int) ob.GetType().GetProperty ("Count").GetValue(ob,null);
446                                 PropertyInfo itemProp = TypeData.GetIndexerProperty (listType.Type);
447                                 object[] index = new object[1];
448                                 for (int n=0; n<count; n++)
449                                 {
450                                         index[0] = n;
451                                         object item = itemProp.GetValue (ob, index);
452                                         XmlTypeMapElementInfo info = map.FindElement (container, n, item);
453                                         if (info != null && targetString == null) WriteMemberElement (info, item);
454                                         else if (info != null && targetString != null) targetString.Append (GetStringValue (info.MappedType, info.TypeData, item)).Append (" ");
455                                         else if (item != null) throw CreateUnknownTypeException (item);
456                                 }
457                         }
458                         else if (ob is IEnumerable)
459                         {
460                                 IEnumerable e = (IEnumerable)ob;
461                                 foreach (object item in e)
462                                 {
463                                         XmlTypeMapElementInfo info = map.FindElement (container, -1, item);
464                                         if (info != null && targetString == null) WriteMemberElement (info, item);
465                                         else if (info != null && targetString != null) targetString.Append (GetStringValue (info.MappedType, info.TypeData, item)).Append (" ");
466                                         else if (item != null) throw CreateUnknownTypeException (item);
467                                 }
468                         }
469                         else
470                                 throw new Exception ("Unsupported collection type");
471                 }
472
473                 int GetListCount (TypeData listType, object ob)
474                 {
475                         if (listType.Type.IsArray)
476                                 return ((Array)ob).Length;
477                         else
478                                 return (int) listType.Type.GetProperty ("Count").GetValue(ob,null);
479                 }
480
481                 void WriteAnyElementContent (XmlTypeMapMemberAnyElement member, object memberValue)
482                 {
483 #if MOONLIGHT
484                         throw new NotSupportedException ();
485 #else
486                         if (member.TypeData.Type == typeof (XmlElement)) {
487                                 memberValue = new object[] { memberValue };
488                         }
489
490                         Array elems = (Array) memberValue;
491                         foreach (var elem_ in elems)
492                         {
493                                 XmlNode elem = elem_ as XmlNode;
494                                 if (elem == null)
495                                         throw new InvalidOperationException (String.Format ("XmlAnyElementAttribute can only be applied to members of type XmlElement, XmlElement[] or XmlNode[]. The target object is {0}", elem_ != null ? elem_.GetType () : null));
496                                 if (elem is XmlElement) 
497                                 {
498                                         if (member.IsElementDefined (elem.Name, elem.NamespaceURI))
499                                         {
500                                                 if (_format == SerializationFormat.Literal) WriteElementLiteral (elem, "", "", false, true);
501                                                 else WriteElementEncoded (elem, "", "", false, true);
502                                         }
503                                         else
504                                                 throw CreateUnknownAnyElementException (elem.Name, elem.NamespaceURI);
505                                 }
506                                 else
507                                         elem.WriteTo (Writer);
508                         }
509 #endif
510                 }
511
512                 protected virtual void WritePrimitiveElement (XmlTypeMapping typeMap, object ob, string element, string namesp)
513                 {
514                         Writer.WriteString (GetStringValue (typeMap, typeMap.TypeData, ob));
515                 }
516
517                 protected virtual void WriteEnumElement (XmlTypeMapping typeMap, object ob, string element, string namesp)
518                 {
519                         Writer.WriteString (GetEnumXmlValue (typeMap, ob));
520                 }
521
522                 string GetStringValue (XmlTypeMapping typeMap, TypeData type, object value)
523                 {
524                         if (type.SchemaType == SchemaTypes.Array) {
525                                 if (value == null) return null;
526                                 StringBuilder sb = new StringBuilder ();
527                                 WriteListContent (null, typeMap.TypeData, (ListMap)typeMap.ObjectMap, value, sb);
528                                 return sb.ToString ().Trim ();
529                         }
530                         else if (type.SchemaType == SchemaTypes.Enum)
531                                 return GetEnumXmlValue (typeMap, value);
532                         else if (type.Type == typeof (XmlQualifiedName))
533                                 return FromXmlQualifiedName ((XmlQualifiedName)value);
534                         else if (value == null)
535                                 return null;
536                         else
537                                 return XmlCustomFormatter.ToXmlString (type, value);
538                 }
539
540                 string GetEnumXmlValue (XmlTypeMapping typeMap, object ob)
541                 {
542                         if (ob == null)
543                                 return null;
544                         EnumMap map = (EnumMap)typeMap.ObjectMap;
545                         return map.GetXmlName (typeMap.TypeFullName, ob);
546                 }
547
548                 class CallbackInfo
549                 {
550                         XmlSerializationWriterInterpreter _swi;
551                         XmlTypeMapping _typeMap;
552
553                         public CallbackInfo (XmlSerializationWriterInterpreter swi, XmlTypeMapping typeMap)
554                         {
555                                 _swi = swi;
556                                 _typeMap = typeMap;
557                         }
558
559                         internal void WriteObject (object ob)
560                         {
561                                 _swi.WriteObject (_typeMap, ob, _typeMap.ElementName, _typeMap.Namespace, false, false, false);
562                         }
563
564                         internal void WriteEnum (object ob)
565                         {
566                                 _swi.WriteObject (_typeMap, ob, _typeMap.ElementName, _typeMap.Namespace, false, true, false);
567                         }
568                 }
569
570         }
571 }