Fixed bug #4668 - C# compiler doesn't like decimal in custom attribute values, so...
[mono.git] / mcs / class / System.XML / System.Xml.Serialization / XmlSerializationWriter.cs
index 522314608f386cb8181de34cd72a412172a63c13..3cd8036884c1abf92306420c1a22e9de61f3f313 100644 (file)
@@ -31,6 +31,7 @@
 
 using System;
 using System.Collections;
+using System.Collections.Generic;
 using System.Globalization;
 using System.Text;
 using System.Xml;
@@ -297,6 +298,14 @@ namespace System.Xml.Serialization
                        Writer.WriteAttributeString (prefix, localName, ns, value);
                }
 
+               void WriteXmlNode (XmlNode node)
+               {
+                       if (node is XmlDocument)
+                               node = ((XmlDocument) node).DocumentElement;
+
+                       node.WriteTo (Writer);
+               }
+
                protected void WriteElementEncoded (XmlNode node, string name, string ns, bool isNullable, bool any)
                {
                        if (name != string.Empty)
@@ -309,12 +318,12 @@ namespace System.Xml.Serialization
                                else
                                {
                                        Writer.WriteStartElement (name, ns);
-                                       node.WriteTo (Writer);
+                                       WriteXmlNode (node);
                                        Writer.WriteEndElement ();
                                }
                        }
                        else
-                               node.WriteTo (Writer);
+                               WriteXmlNode(node);
                }
 
                protected void WriteElementLiteral (XmlNode node, string name, string ns, bool isNullable, bool any)
@@ -329,12 +338,12 @@ namespace System.Xml.Serialization
                                else
                                {
                                        Writer.WriteStartElement (name, ns);
-                                       node.WriteTo (Writer);
+                                       WriteXmlNode (node);
                                        Writer.WriteEndElement ();
                                }
                        }
                        else
-                               node.WriteTo (Writer);
+                               WriteXmlNode (node);
                }
 
                protected void WriteElementQualifiedName (string localName, XmlQualifiedName value)
@@ -478,12 +487,11 @@ namespace System.Xml.Serialization
                        WriteAttribute ("id", GetId (o, true));
                }
 
-               protected void WriteNamespaceDeclarations (XmlSerializerNamespaces ns)
+               protected void WriteNamespaceDeclarations (XmlSerializerNamespaces xmlns)
                {
-                       if (ns == null)
+                       if (xmlns == null)
                                return;
-
-                       ICollection namespaces = ns.Namespaces.Values;
+                       ICollection namespaces = xmlns.Namespaces.Values;
                        foreach (XmlQualifiedName qn in namespaces) {
                                if (qn.Namespace != String.Empty && Writer.LookupPrefix (qn.Namespace) != qn.Name)
                                        WriteAttribute ("xmlns", qn.Name, xmlNamespace, qn.Namespace);
@@ -562,11 +570,7 @@ namespace System.Xml.Serialization
                protected void WriteNullTagEncoded (string name, string ns)
                {
                        Writer.WriteStartElement (name, ns);
-#if NET_1_1
                        Writer.WriteAttributeString ("nil", XmlSchema.InstanceNamespace, "true");
-#else
-                       Writer.WriteAttributeString ("null", XmlSchema.InstanceNamespace, "1");
-#endif
                        Writer.WriteEndElement ();
                }
 
@@ -605,19 +609,21 @@ namespace System.Xml.Serialization
                                return;
                        }
 
+                       var t = o.GetType ();
+
                        WriteStartElement (n, ns, true);
 
                        CheckReferenceQueue ();
 
-                       if (callbacks.ContainsKey (o.GetType ()))
+                       if (callbacks != null && callbacks.ContainsKey (o.GetType ()))
                        {
-                               WriteCallbackInfo info = (WriteCallbackInfo) callbacks[o.GetType()];
-                               if (o.GetType ().IsEnum) {
+                               WriteCallbackInfo info = (WriteCallbackInfo) callbacks[t];
+                               if (t.IsEnum) {
                                        info.Callback (o);
                                }
                                else if (suppressReference) {
                                        Writer.WriteAttributeString ("id", GetId (o, false));
-                                       if (ambientType != o.GetType ()) WriteXsiType(info.TypeName, info.TypeNs);
+                                       if (ambientType != t) WriteXsiType(info.TypeName, info.TypeNs);
                                        info.Callback (o);
                                }
                                else {
@@ -628,15 +634,17 @@ namespace System.Xml.Serialization
                        else
                        {
                                // Must be a primitive type or array of primitives
-                               TypeData td = TypeTranslator.GetTypeData (o.GetType ());
+                               TypeData td = TypeTranslator.GetTypeData (t, null, true);
                                if (td.SchemaType == SchemaTypes.Primitive) {
-                                       WriteXsiType (td.XmlType, XmlSchema.Namespace);
+                                       if (t != ambientType)
+                                               WriteXsiType (td.XmlType, XmlSchema.Namespace);
                                        Writer.WriteString (XmlCustomFormatter.ToXmlString (td, o));
                                } else if (IsPrimitiveArray (td)) {
                                        if (!AlreadyQueued (o)) referencedElements.Enqueue (o);
                                        Writer.WriteAttributeString ("href", "#" + GetId (o, true));
-                               } else
-                                       throw new InvalidOperationException ("Invalid type: " + o.GetType().FullName);
+                               } else {
+                                       throw new InvalidOperationException ("Invalid type: " + t.FullName);
+                               }
                        }
 
                        WriteEndElement ();
@@ -747,17 +755,27 @@ namespace System.Xml.Serialization
                }
 
                protected void WriteSerializable (IXmlSerializable serializable, string name, string ns, bool isNullable)
+               {
+                       WriteSerializable (serializable, name, ns, isNullable, true);
+               }
+
+#if NET_2_0
+               protected
+#endif
+               void WriteSerializable (IXmlSerializable serializable, string name, string ns, bool isNullable, bool wrapped)
                {
                        if (serializable == null)
                        {
-                               if (isNullable) WriteNullTagLiteral (name, ns);
+                               if (isNullable && wrapped) WriteNullTagLiteral (name, ns);
                                return;
                        }
                        else
                        {
-                               Writer.WriteStartElement (name, ns);
+                               if (wrapped)
+                                       Writer.WriteStartElement (name, ns);
                                serializable.WriteXml (Writer);
-                               Writer.WriteEndElement ();
+                               if (wrapped)
+                                       Writer.WriteEndElement ();
                        }
                }
 
@@ -788,6 +806,18 @@ namespace System.Xml.Serialization
                }
 
                protected void WriteStartElement (string name, string ns, object o, bool writePrefixed)
+               {
+                       WriteStartElement (name, ns, o, writePrefixed, namespaces);
+               }
+
+#if NET_2_0
+               protected void WriteStartElement (string name, string ns, Object o, bool writePrefixed, XmlSerializerNamespaces xmlns)
+               {
+                       WriteStartElement (name, ns, o, writePrefixed, xmlns != null ? xmlns.ToArray () : null);
+               }
+#endif
+
+               void WriteStartElement (string name, string ns, object o, bool writePrefixed, ICollection namespaces)
                {
                        if (o != null)
                        {
@@ -801,12 +831,13 @@ namespace System.Xml.Serialization
                        
                        if (topLevelElement && ns != null && ns.Length != 0)
                        {
-                               foreach (XmlQualifiedName qn in namespaces)
-                                       if (qn.Namespace == ns) {
-                                               prefix = qn.Name;
-                                               writePrefixed = true;
-                                               break;
-                                       }
+                               if (namespaces != null)
+                                       foreach (XmlQualifiedName qn in namespaces)
+                                               if (qn.Namespace == ns) {
+                                                       prefix = qn.Name;
+                                                       writePrefixed = true;
+                                                       break;
+                                               }
                        }
 
                        if (writePrefixed && ns != string.Empty)
@@ -839,30 +870,32 @@ namespace System.Xml.Serialization
                protected void WriteTypedPrimitive (string name, string ns, object o, bool xsiType)
                {
                        string value;
-                       TypeData td = TypeTranslator.GetTypeData (o.GetType ());
+                       TypeData td = TypeTranslator.GetTypeData (o.GetType (), null, true);
+                       if (td.SchemaType != SchemaTypes.Primitive)
+                               throw new InvalidOperationException (String.Format ("The type of the argument object '{0}' is not primitive.", td.FullTypeName));
 
-                       name = XmlCustomFormatter.FromXmlName (name);
+                       if (name == null) {
+                               ns = td.IsXsdType ? XmlSchema.Namespace : XmlSerializer.WsdlTypesNamespace;
+                               name = td.XmlType;
+                       }
+                       else
+                               name = XmlCustomFormatter.FromXmlName (name);
                        Writer.WriteStartElement (name, ns);
 
-                       if (o is XmlNode[]) {
-                               foreach (XmlNode node in (XmlNode[])o)
-                                       node.WriteTo (Writer);
+                       if (o is XmlQualifiedName)
+                               value = FromXmlQualifiedName ((XmlQualifiedName) o);
+                       else
+                               value = XmlCustomFormatter.ToXmlString (td, o);
+
+                       if (xsiType)
+                       {
+                               if (td.SchemaType != SchemaTypes.Primitive)
+                                       throw new InvalidOperationException (string.Format (unexpectedTypeError, o.GetType().FullName));
+                               WriteXsiType (td.XmlType, td.IsXsdType ? XmlSchema.Namespace : XmlSerializer.WsdlTypesNamespace);
                        }
-                       else {
-                               if (o is XmlQualifiedName)
-                                       value = FromXmlQualifiedName ((XmlQualifiedName) o);
-                               else
-                                       value = XmlCustomFormatter.ToXmlString (td, o);
 
-                               if (xsiType)
-                               {
-                                       if (td.SchemaType != SchemaTypes.Primitive)
-                                               throw new InvalidOperationException (string.Format (unexpectedTypeError, o.GetType().FullName));
-                                       WriteXsiType (td.XmlType, XmlSchema.Namespace);
-                               }
+                       WriteValue (value);
 
-                               WriteValue (value);
-                       }
                        Writer.WriteEndElement ();
                }
 
@@ -913,16 +946,17 @@ namespace System.Xml.Serialization
                
 #if NET_2_0
 
-               [MonoTODO]
                protected Exception CreateInvalidAnyTypeException (object o)
                {
-                       throw new NotImplementedException ();
+                       if (o == null)
+                               return new InvalidOperationException ("null is invalid as anyType in XmlSerializer");
+                       else
+                               return CreateInvalidAnyTypeException (o.GetType ());
                }
                
-               [MonoTODO]
-               protected Exception CreateInvalidAnyTypeException (Type t)
+               protected Exception CreateInvalidAnyTypeException (Type type)
                {
-                       throw new NotImplementedException ();
+                       return new InvalidOperationException (String.Format ("An object of type '{0}' is invalid as anyType in XmlSerializer", type));
                }
 
                protected Exception CreateInvalidEnumValueException (object value, string typeName)
@@ -948,12 +982,6 @@ namespace System.Xml.Serialization
                        throw new NotImplementedException ();
                }
                
-               [MonoTODO]
-               protected void WriteSerializable (IXmlSerializable serializable, string name, string ns, bool isNullable, bool any)
-               {
-                       throw new NotImplementedException ();
-               }
-               
                [MonoTODO]
                protected bool EscapeName
                {