2 // Mono Class Libraries
3 // System.Xml.Serialization.XmlSerializer
6 // John Donagher (john@webmeta.com)
7 // Ajay kumar Dwivedi (adwiv@yahoo.com)
8 // Tim Coleman (tim@timcoleman.com)
10 // (C) 2002 John Donagher, Ajay kumar Dwivedi
11 // Copyright (C) Tim Coleman, 2002
15 using System.Collections;
17 using System.Reflection;
19 using System.Xml.Schema;
21 namespace System.Xml.Serialization {
23 /// Summary description for XmlSerializer.
25 public class XmlSerializer {
30 XmlAttributeOverrides overrides;
32 XmlRootAttribute rootAttribute;
33 string defaultNamespace;
34 static Hashtable typeTable;
42 protected XmlSerializer ()
46 public XmlSerializer (Type type)
47 : this (type, null, null, null, null)
52 public XmlSerializer (XmlTypeMapping xmltypemapping)
56 public XmlSerializer (Type type, string defaultNamespace)
57 : this (type, null, null, null, defaultNamespace)
61 public XmlSerializer (Type type, Type[] extraTypes)
62 : this (type, null, extraTypes, null, null)
66 public XmlSerializer (Type type, XmlAttributeOverrides overrides)
67 : this (type, overrides, null, null, null)
71 public XmlSerializer (Type type, XmlRootAttribute root)
72 : this (type, null, null, root, null)
76 internal XmlSerializer (Hashtable typeTable)
78 typeTable = typeTable;
81 public XmlSerializer (Type type, XmlAttributeOverrides overrides, Type[] extraTypes, XmlRootAttribute root, string defaultNamespace)
84 throw new ArgumentNullException ("type", "XmlSerializer can't be constructed with a null type");
87 this.overrides = overrides;
88 this.extraTypes = (extraTypes == null ? new Type[0] : extraTypes);
91 this.rootAttribute = root;
93 object[] attributes = type.GetCustomAttributes (typeof (XmlRootAttribute), false);
94 if (attributes.Length > 0)
95 this.rootAttribute = (XmlRootAttribute) attributes[0];
98 this.defaultNamespace = defaultNamespace;
100 if (typeTable == null)
101 typeTable = new Hashtable ();
103 FillTypeTable (type);
106 #endregion // Constructors
111 public event XmlAttributeEventHandler UnknownAttribute;
113 public event XmlElementEventHandler UnknownElement;
115 public event XmlNodeEventHandler UnknownNode;
117 public event UnreferencedObjectEventHandler UnreferencedObject;
123 public bool UseOrder {
124 get { return useOrder; }
125 set { useOrder = value; }
128 #endregion // Properties
133 public virtual bool CanDeserialize (XmlReader xmlReader)
135 throw new NotImplementedException ();
139 protected virtual XmlSerializationReader CreateReader ()
141 throw new NotImplementedException ();
145 protected virtual XmlSerializationReader CreateWriter ()
147 throw new NotImplementedException ();
151 public object Deserialize (Stream stream)
153 throw new NotImplementedException ();
156 public object Deserialize (TextReader textReader)
158 throw new NotImplementedException ();
161 public object Deserialize (XmlReader xmlReader)
163 throw new NotImplementedException ();
167 public virtual object Deserialize (XmlSerializationReader reader)
169 throw new NotImplementedException ();
173 protected virtual void Serialize (object o, XmlSerializationWriter writer)
175 throw new NotImplementedException ();
178 public void Serialize (Stream stream, object o)
180 XmlTextWriter xmlWriter = new XmlTextWriter (stream, System.Text.Encoding.Default);
181 xmlWriter.Formatting = Formatting.Indented;
182 Serialize (xmlWriter, o, null);
185 public void Serialize (TextWriter textWriter, object o)
187 XmlTextWriter xmlWriter = new XmlTextWriter (textWriter);
188 xmlWriter.Formatting = Formatting.Indented;
189 Serialize (xmlWriter, o, null);
192 public void Serialize (XmlWriter xmlWriter, object o)
194 Serialize (xmlWriter, o);
197 public void Serialize (Stream stream, object o, XmlSerializerNamespaces namespaces)
199 XmlTextWriter xmlWriter = new XmlTextWriter (stream, System.Text.Encoding.Default);
200 xmlWriter.Formatting = Formatting.Indented;
201 Serialize (xmlWriter, o, namespaces);
204 public void Serialize (TextWriter textWriter, object o, XmlSerializerNamespaces namespaces)
206 XmlTextWriter xmlWriter = new XmlTextWriter (textWriter);
207 xmlWriter.Formatting = Formatting.Indented;
208 Serialize (xmlWriter, o, namespaces);
211 public void Serialize (XmlWriter writer, object o, XmlSerializerNamespaces namespaces)
213 Type objType = o.GetType ();
214 string rootName = objType.Name;
215 string rootNs = String.Empty;
216 string rootPrefix = String.Empty;
218 if (namespaces == null)
219 namespaces = new XmlSerializerNamespaces ();
221 if (namespaces.Count == 0) {
222 namespaces.Add ("xsd", XmlSchema.Namespace);
223 namespaces.Add ("xsi", XmlSchema.InstanceNamespace);
226 XmlSerializerNamespaces nss = new XmlSerializerNamespaces ();
227 XmlQualifiedName[] qnames;
229 writer.WriteStartDocument ();
231 object[] memberObj = (object[]) typeTable[objType];
232 if (memberObj == null)
233 throw new Exception ("Unknown Type " + objType + " encountered during Serialization");
235 Hashtable memberTable = (Hashtable) memberObj[0];
236 XmlAttributes xmlAttributes = (XmlAttributes) memberTable[""];
238 //If we have been passed an XmlRoot, set it on the base class
239 if (rootAttribute != null)
240 xmlAttributes.XmlRoot = rootAttribute;
242 if (xmlAttributes.XmlRoot != null) {
243 isNullable = xmlAttributes.XmlRoot.IsNullable;
244 if (xmlAttributes.XmlRoot.ElementName != null)
245 rootName = xmlAttributes.XmlRoot.ElementName;
246 rootNs = xmlAttributes.XmlRoot.Namespace;
249 if (namespaces.GetPrefix (rootNs) != null)
250 rootPrefix = namespaces.GetPrefix (rootNs);
252 //XMLNS attributes in the Root
253 XmlAttributes XnsAttrs = (XmlAttributes) ((object[]) typeTable[objType])[1];
254 if (XnsAttrs != null) {
255 MemberInfo member = XnsAttrs.MemberInfo;
256 FieldInfo fieldInfo = member as FieldInfo;
257 PropertyInfo propertyInfo = member as PropertyInfo;
258 XmlSerializerNamespaces xns;
260 if (fieldInfo != null)
261 xns = (XmlSerializerNamespaces) fieldInfo.GetValue (o);
263 xns = (XmlSerializerNamespaces) propertyInfo.GetValue (o, null);
265 qnames = xns.ToArray ();
267 foreach (XmlQualifiedName qname in qnames)
268 nss.Add (qname.Name, qname.Namespace);
271 //XmlNs from the namespaces passed
272 qnames = namespaces.ToArray ();
273 foreach (XmlQualifiedName qname in qnames)
274 if (writer.LookupPrefix (qname.Namespace) != qname.Name)
275 nss.Add (qname.Name, qname.Namespace);
277 writer.WriteStartElement (rootPrefix, rootName, rootNs);
279 qnames = nss.ToArray();
280 foreach (XmlQualifiedName qname in qnames)
281 if (writer.LookupPrefix (qname.Namespace) != qname.Name)
282 writer.WriteAttributeString ("xmlns", qname.Name, null, qname.Namespace);
284 if (rootPrefix == String.Empty && rootNs != String.Empty && rootNs != null)
285 writer.WriteAttributeString (String.Empty, "xmlns", null, rootNs);
287 SerializeMembers (writer, o, true);//, namespaces);
288 writer.WriteEndDocument ();
291 private void SerializeMembers (XmlWriter writer, object o, bool isRoot)
293 Type objType = o.GetType ();
294 XmlAttributes nsAttributes = (XmlAttributes) ((object[]) typeTable [objType])[1];
295 ArrayList attributes = (ArrayList) ((object[]) typeTable [objType])[2];
296 ArrayList elements = (ArrayList) ((object[]) typeTable [objType])[3];
299 if (!isRoot && nsAttributes != null) {
300 MemberInfo member = nsAttributes.MemberInfo;
301 FieldInfo fieldInfo = member as FieldInfo;
302 PropertyInfo propertyInfo = member as PropertyInfo;
304 XmlSerializerNamespaces xns;
306 if (fieldInfo != null)
307 xns = (XmlSerializerNamespaces) fieldInfo.GetValue (o);
309 xns = (XmlSerializerNamespaces) propertyInfo.GetValue (o, null);
311 XmlQualifiedName[] qnames = xns.ToArray ();
312 foreach (XmlQualifiedName qname in qnames)
313 if (writer.LookupPrefix (qname.Namespace) != qname.Name)
314 writer.WriteAttributeString ("xmlns", qname.Name, null, qname.Namespace);
317 //Serialize the Attributes.
318 foreach (XmlAttributes xmlAttributes in attributes) {
319 MemberInfo member = xmlAttributes.MemberInfo;
320 FieldInfo fieldInfo = member as FieldInfo;
321 PropertyInfo propertyInfo = member as PropertyInfo;
324 object attributeValue;
325 string attributeValueString;
326 string attributeName;
329 if (fieldInfo != null) {
330 attributeType = fieldInfo.FieldType;
331 attributeValue = fieldInfo.GetValue (o);
334 attributeType = propertyInfo.PropertyType;
335 attributeValue = propertyInfo.GetValue (o, null);
338 attributeName = xmlAttributes.GetAttributeName (attributeType, member.Name);
339 attributeNs = xmlAttributes.GetAttributeNamespace (attributeType);
341 if (attributeValue is XmlQualifiedName) {
342 XmlQualifiedName qname = (XmlQualifiedName) attributeValue;
347 writer.WriteStartAttribute (attributeName, attributeNs);
348 writer.WriteQualifiedName (qname.Name, qname.Namespace);
349 writer.WriteEndAttribute ();
352 else if (attributeValue is XmlQualifiedName[]) {
353 XmlQualifiedName[] qnames = (XmlQualifiedName[]) attributeValue;
354 writer.WriteStartAttribute (attributeName, attributeNs);
356 foreach (XmlQualifiedName qname in qnames) {
360 writer.WriteWhitespace (" ");
361 writer.WriteQualifiedName (qname.Name, qname.Namespace);
363 writer.WriteEndAttribute ();
366 else if (attributeValue is XmlAttribute[]) {
367 XmlAttribute[] xmlattrs = (XmlAttribute[]) attributeValue;
368 foreach (XmlAttribute xmlattr in xmlattrs)
369 xmlattr.WriteTo(writer);
373 attributeValueString = GetXmlValue (attributeValue);
374 if (attributeValueString != GetXmlValue (xmlAttributes.XmlDefaultValue))
375 writer.WriteAttributeString (attributeName, attributeNs, attributeValueString);
378 // Serialize Elements
379 foreach (XmlAttributes xmlElements in elements) {
380 MemberInfo member = xmlElements.MemberInfo;
381 FieldInfo fieldInfo = member as FieldInfo;
382 PropertyInfo propertyInfo = member as PropertyInfo;
389 if (fieldInfo != null) {
390 elementType = fieldInfo.FieldType;
391 elementValue = fieldInfo.GetValue (o);
394 elementType = propertyInfo.PropertyType;
395 elementValue = propertyInfo.GetValue (o, null);
398 elementName = xmlElements.GetElementName (elementType, member.Name);
399 elementNs = xmlElements.GetElementNamespace (elementType);
400 WriteElement (writer, xmlElements, elementName, elementNs, elementType, elementValue);
404 [MonoTODO ("Remove FIXMEs")]
405 private void WriteElement (XmlWriter writer, XmlAttributes attrs, string name, string ns, Type type, Object value)
407 if (IsInbuiltType (type)) {
408 string xmlValue = GetXmlValue (value);
409 if (xmlValue != String.Empty && xmlValue != null)
410 writer.WriteElementString (name, ns, xmlValue);
412 else if (attrs.XmlText != null && value != null) {
413 if (type == typeof (object[])) {
416 else if (type == typeof (string[])) {
419 else if (type == typeof (XmlNode)) {
420 ((XmlNode) value).WriteTo (writer);
422 else if (type == typeof (XmlNode[])) {
423 XmlNode[] nodes = (XmlNode[]) value;
424 foreach (XmlNode node in nodes)
425 node.WriteTo (writer);
428 else if (type.IsArray && value != null) {
429 writer.WriteStartElement (name, ns);
430 SerializeArray (writer, value);
431 writer.WriteEndElement ();
433 else if (value is ICollection) {
434 BindingFlags flags = BindingFlags.Public | BindingFlags.Instance;
436 //Find a non indexer Count Property with return type of int
437 PropertyInfo countInfo = type.GetProperty ("Count", flags, null, typeof (int), new Type[0], null);
438 PropertyInfo itemInfo = type.GetProperty ("Item", flags, null, null, new Type[1] {typeof (int)}, null);
439 int count = (int) countInfo.GetValue (value, null);
442 for (int i = 0; i < count; i++) {
443 object itemValue = itemInfo.GetValue (value, new object[1] {i});
445 if (itemValue != null) {
446 string itemName = attrs.GetElementName (itemValue.GetType (), name);
447 string itemNs = attrs.GetElementNamespace (itemValue.GetType ());
449 writer.WriteStartElement (itemName, itemNs);
450 SerializeMembers (writer, itemValue, false);
451 writer.WriteEndElement ();
455 else if (value is IEnumerable) {
458 else if (type.IsEnum) {
461 else if (value != null) { //Complex Type?
462 string itemName = attrs.GetElementName (value.GetType (), name);
463 string itemNs = attrs.GetElementNamespace (value.GetType ());
464 writer.WriteStartElement (itemName, itemNs);
465 SerializeMembers (writer, value, false);
466 writer.WriteEndElement ();
474 private void SerializeArray (XmlWriter writer, object o)
476 throw new NotImplementedException ();
480 /// If the type is a string, valuetype or primitive type we do not populate the TypeTable.
481 /// If the type is an array, we populate the TypeTable with Element type of the array.
482 /// If the type implements ICollection, it is handled differently. We do not care for its members.
483 /// If the type implements IEnumberable, we check that it implements Add(). Don't care for members.
485 [MonoTODO ("Remove FIXMEs")]
486 private void FillTypeTable (Type type)
488 if (typeTable.Contains (type))
491 //For value types and strings we don't need the members.
492 //FIXME: We will need the enum types probably.
493 if (IsInbuiltType (type))
496 //Array, ICollection and IEnumberable are treated differenty
498 FillArrayType (type);
501 else if (type.IsEnum) {
506 //There must be a public constructor
507 if (!HasDefaultConstructor (type))
508 throw new Exception ("Can't Serialize Type " + type.Name + " since it does not have default Constructor");
510 if (type.GetInterface ("ICollection") == typeof (System.Collections.ICollection)) {
511 FillICollectionType (type);
514 if (type.GetInterface ("IEnumerable") == typeof (System.Collections.IEnumerable)) {
515 //FillIEnumerableType(type);
521 //Add the Class to the hashtable.
522 //Each value of the hashtable has two objects, one is the hashtable with key of membername (for deserialization)
523 //Other is an Array of XmlSerializernames, Array of XmlAttributes & Array of XmlElements.
524 Object[] memberObj = new Object[4];
525 typeTable.Add (type,memberObj);
527 Hashtable memberTable = new Hashtable ();
528 memberObj[0] = memberTable;
529 memberTable.Add ("", XmlAttributes.FromClass (type));
533 ArrayList attributes = new ArrayList ();
534 memberObj[2] = attributes;
536 ArrayList elements = new ArrayList ();
537 memberObj[3] = elements;
539 //Get the graph of the members. Graph is nothing but the order
540 //in which MS implementation serializes the members.
541 MemberInfo[] minfo = GetGraph (type);
543 foreach (MemberInfo member in minfo) {
544 FieldInfo fieldInfo = (member as FieldInfo);
545 PropertyInfo propertyInfo = (member as PropertyInfo);
547 if (fieldInfo != null) {
548 //If field is readOnly or const, do not serialize it.
549 if (fieldInfo.IsLiteral || fieldInfo.IsInitOnly)
552 XmlAttributes xmlAttributes = XmlAttributes.FromField (member, fieldInfo);
554 //If XmlAttributes have XmlIgnore, ignore this member
556 if (xmlAttributes.XmlIgnore)
559 //If this member is a XmlNs type, set the XmlNs object.
560 if (xmlAttributes.Xmlns) {
561 memberObj[1] = xmlAttributes;
565 //If the member is a attribute Type, Add to attribute list
566 if (xmlAttributes.isAttribute)
567 attributes.Add (xmlAttributes);
568 else //Add to elements
569 elements.Add (xmlAttributes);
571 //Add in the Hashtable.
572 memberTable.Add (member.Name, xmlAttributes);
574 if (xmlAttributes.XmlAnyAttribute != null || xmlAttributes.XmlText != null)
577 if (xmlAttributes.XmlElements.Count > 0) {
578 foreach (XmlElementAttribute elem in xmlAttributes.XmlElements) {
579 if (elem.Type != null)
580 FillTypeTable (elem.Type);
582 FillTypeTable (fieldInfo.FieldType);
587 if (!IsInbuiltType (fieldInfo.FieldType))
588 FillTypeTable (fieldInfo.FieldType);
590 else if (propertyInfo != null) {
591 //If property is readonly or writeonly, do not serialize it.
592 //Exceptions are properties whose return type is array, ICollection or IEnumerable
593 //Indexers are not serialized unless the class Implements ICollection.
594 if (!(propertyInfo.PropertyType.IsArray || Implements (propertyInfo.PropertyType, typeof (ICollection)) ||
595 (propertyInfo.PropertyType != typeof (string) && Implements (propertyInfo.PropertyType, typeof (IEnumerable))))) {
596 if(!(propertyInfo.CanRead && propertyInfo.CanWrite) || propertyInfo.GetIndexParameters ().Length != 0)
600 XmlAttributes xmlAttributes = XmlAttributes.FromProperty (member, propertyInfo);
602 // If XmlAttributes have XmlIgnore, ignore this member
603 if (xmlAttributes.XmlIgnore)
606 // If this member is a XmlNs type, set the XmlNs object.
607 if (xmlAttributes.Xmlns) {
608 memberObj[1] = xmlAttributes;
611 // If the member is a attribute Type, Add to attribute list
612 if (xmlAttributes.isAttribute)
613 attributes.Add (xmlAttributes);
614 else //Add to elements
615 elements.Add (xmlAttributes);
617 // OtherWise add in the Hashtable.
618 memberTable.Add (member.Name, xmlAttributes);
620 if (xmlAttributes.XmlAnyAttribute != null || xmlAttributes.XmlText != null)
623 if (xmlAttributes.XmlElements.Count > 0) {
624 foreach (XmlElementAttribute elem in xmlAttributes.XmlElements) {
625 if (elem.Type != null)
626 FillTypeTable (elem.Type);
628 FillTypeTable (propertyInfo.PropertyType);
633 if (!IsInbuiltType (propertyInfo.PropertyType))
634 FillTypeTable (propertyInfo.PropertyType);
638 // Sort the attributes for the members according to their Order
639 // This is an extension to MS's Implementation and will be useful
640 // if our reflection does not return the same order of elements
643 BubbleSort (elements, XmlAttributes.attrComparer);
646 private void FillArrayType (Type type)
648 if (type.GetArrayRank () != 1)
649 throw new Exception ("MultiDimensional Arrays are not Supported");
651 Type arrayType = type.GetElementType ();
653 if (arrayType.IsArray)
654 FillArrayType (arrayType);
655 else if (!IsInbuiltType (arrayType))
656 FillTypeTable (arrayType);
659 private void FillICollectionType (Type type)
661 //Must have an public Indexer that takes an integer and
662 //a public Count Property which returns an int.
664 BindingFlags flags = BindingFlags.Public | BindingFlags.Instance;
666 //Find a non indexer Count Property with return type of int
667 PropertyInfo countProp = type.GetProperty ("Count", flags, null, typeof (int), new Type[0], null);
668 if (countProp == null || !countProp.CanRead)
669 throw new Exception ("Cannot Serialize " + type + " because it implements ICollectoion, but does not implement public Count property");
670 //Find a indexer Item Property which takes an int
671 PropertyInfo itemProp = type.GetProperty ("Item", flags, null, null, new Type[1] {typeof (int)}, null);
672 if (itemProp == null || !itemProp.CanRead || !itemProp.CanWrite)
673 throw new Exception ("Cannot Serialize " + type + " because it does not have a read/write indexer property that takes an int as argument");
674 FillTypeTable (itemProp.PropertyType);
678 private void FillIEnumerableType (Type type)
680 //Must implement a public Add method that takes a single parameter.
681 //The Add method's parameter must be of the same type as is returned from
682 //the Current property on the value returned from GetEnumerator, or one of that type's bases.
684 // We currently ignore enumerable types anyway, so this method was junked.
685 // The code did not do what the documentation above says (if that is even possible!)
689 private void FillEnum (Type type)
691 Hashtable memberTable = new Hashtable ();
692 BindingFlags flags = BindingFlags.Public | BindingFlags.Instance;
693 typeTable.Add (type, memberTable);
694 string[] names = Enum.GetNames (type);
696 foreach (string name in names) {
697 MemberInfo[] members = type.GetMember (name);
698 if (members.Length != 1)
699 throw new Exception("Should never happen. Enum member not present or more than one. " + name);
700 XmlAttributes xmlAttributes = new XmlAttributes (members[0]);
702 if (xmlAttributes.XmlIgnore)
705 if (xmlAttributes.XmlEnum != null)
706 memberTable.Add (members[0].Name, xmlAttributes.XmlEnum.Name);
708 memberTable.Add (members[0].Name, members[0].Name);
712 private bool HasDefaultConstructor (Type type)
714 ConstructorInfo defaultConstructor = type.GetConstructor (new Type[0]);
715 if (defaultConstructor == null || defaultConstructor.IsAbstract || defaultConstructor.IsStatic || !defaultConstructor.IsPublic)
721 private bool IsInbuiltType (Type type)
725 if (type.IsValueType || type == typeof (string) || type.IsPrimitive)
730 private static MemberInfo[] GetGraph(Type type)
732 ArrayList typeGraph = new ArrayList ();
733 GetGraph (type, typeGraph);
734 return (MemberInfo[]) typeGraph.ToArray (typeof (MemberInfo));
737 private static void GetGraph (Type type, ArrayList typeGraph)
739 BindingFlags flags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly;
740 if (type.BaseType == null)
742 GetGraph (type.BaseType, typeGraph);
744 typeGraph.AddRange (type.GetFields (flags));
745 typeGraph.AddRange (type.GetProperties (flags));
748 private string GetXmlValue (object value)
754 Type type = value.GetType ();
756 if (typeTable.ContainsKey (type)) {
757 Hashtable memberTable = (Hashtable) (typeTable[type]);
758 if (type.IsDefined (typeof (FlagsAttribute), false)) {
759 //If value is exactly a single enum member
760 if (memberTable.Contains (value.ToString ()))
761 return (string) memberTable[value.ToString ()];
764 int enumval = (int) value;
765 string[] names = Enum.GetNames (type);
767 foreach (string key in names) {
768 if (!memberTable.ContainsKey (key))
771 //Otherwise multiple values.
772 int val = (int) Enum.Parse (type, key);
773 if (val != 0 && (enumval & val) == val)
774 retval += " " + (string) memberTable[Enum.GetName (type, val)];
777 retval = retval.Trim ();
779 if (retval.Length == 0)
784 else if (memberTable.ContainsKey (value.ToString ()))
785 return (string) memberTable[value.ToString()];
790 throw new Exception ("Unknown Enumeration");
793 return (bool) value ? "true" : "false";
794 if (value is XmlQualifiedName) {
795 if (((XmlQualifiedName) value).IsEmpty)
798 return (value == null) ? null : value.ToString ();
801 [MonoTODO ("Remove FIXMEs")]
802 private static void ProcessAttributes (XmlAttributes attrs, Hashtable memberTable)
804 if (attrs.XmlAnyAttribute != null) {
807 foreach (XmlAnyElementAttribute anyelem in attrs.XmlAnyElements)
808 memberTable.Add (new XmlQualifiedName (anyelem.Name, anyelem.Namespace), attrs);
810 if (attrs.XmlArray != null) {
814 foreach (XmlArrayItemAttribute item in attrs.XmlArrayItems)
815 memberTable.Add (new XmlQualifiedName (item.ElementName, item.Namespace), attrs);
817 if (attrs.XmlAttribute != null)
818 memberTable.Add (new XmlQualifiedName (attrs.XmlAttribute.AttributeName,attrs.XmlAttribute.Namespace), attrs);
820 if (attrs.XmlChoiceIdentifier != null) {
824 foreach (XmlElementAttribute elem in attrs.XmlElements)
825 memberTable.Add (new XmlQualifiedName (elem.ElementName, elem.Namespace), attrs);
827 if (attrs.XmlEnum != null) {
831 if (attrs.XmlType != null)
832 memberTable.Add (new XmlQualifiedName (attrs.XmlType.TypeName, attrs.XmlType.Namespace), attrs);
835 private bool Implements (Type type, Type interfaceType)
837 return (type.GetInterface (interfaceType.Name) == interfaceType);
840 private static void BubbleSort (ArrayList array, IComparer comparer)
842 int len = array.Count;
844 for (int i=0; i < len; i++) {
845 for (int j=0; j < len -i -1; j++) {
848 if (comparer.Compare (obj2 , obj1 ) < 0) {
855 #endregion // Methods