using System;
using System.Collections;
+using System.Collections.Generic;
using System.Globalization;
using System.Text;
using System.Xml;
ArrayList namespaces;
XmlWriter writer;
+#if MOONLIGHT
+ Queue<object> referencedElements;
+#else
Queue referencedElements;
+#endif
Hashtable callbacks;
Hashtable serializedObjects;
const string xmlNamespace = "http://www.w3.org/2000/xmlns/";
#region Properties
+#if MOONLIGHT
+ protected IList XmlNamespaces {
+ get { return namespaces; }
+ set { namespaces = (value as ArrayList); }
+ }
+#else
protected ArrayList Namespaces {
get { return namespaces; }
set { namespaces = value; }
}
+#endif
protected XmlWriter Writer {
get { return writer; }
if (callbacks == null) callbacks = new Hashtable ();
callbacks.Add (type, info);
}
-
+
protected Exception CreateChoiceIdentifierValueException (string value, string identifier, string name, string ns)
{
string message = string.Format ("Value '{0}' of the choice"
Writer.WriteAttributeString (prefix, localName, ns, value);
}
+#if !MOONLIGHT
+ 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)
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)
else
{
Writer.WriteStartElement (name, ns);
- node.WriteTo (Writer);
+ WriteXmlNode (node);
Writer.WriteEndElement ();
}
}
else
- node.WriteTo (Writer);
+ WriteXmlNode (node);
}
+#endif
protected void WriteElementQualifiedName (string localName, XmlQualifiedName value)
{
{
if (ns == null)
return;
-
+#if MOONLIGHT
+ IEnumerable<XmlQualifiedName> namespaces = ns.GetNamespaces ();
+#else
ICollection namespaces = ns.Namespaces.Values;
+#endif
foreach (XmlQualifiedName qn in namespaces) {
if (qn.Namespace != String.Empty && Writer.LookupPrefix (qn.Namespace) != qn.Name)
WriteAttribute ("xmlns", qn.Name, xmlNamespace, qn.Namespace);
CheckReferenceQueue ();
- if (callbacks.ContainsKey (o.GetType ()))
+ if (callbacks != null && callbacks.ContainsKey (o.GetType ()))
{
WriteCallbackInfo info = (WriteCallbackInfo) callbacks[o.GetType()];
if (o.GetType ().IsEnum) {
}
else
{
- // Must be a primitive type
+ // Must be a primitive type or array of primitives
TypeData td = TypeTranslator.GetTypeData (o.GetType ());
- if (td.SchemaType != SchemaTypes.Primitive)
+ if (td.SchemaType == SchemaTypes.Primitive) {
+ 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);
- WriteXsiType(td.XmlType, XmlSchema.Namespace);
- Writer.WriteString (XmlCustomFormatter.ToXmlString (td, o));
}
WriteEndElement ();
object o = referencedElements.Dequeue ();
TypeData td = TypeTranslator.GetTypeData (o.GetType ());
WriteCallbackInfo info = (WriteCallbackInfo) callbacks[o.GetType()];
- WriteStartElement (info.TypeName, info.TypeNs, true);
- Writer.WriteAttributeString ("id", GetId (o, false));
+
+ if (info != null) {
+ WriteStartElement (info.TypeName, info.TypeNs, true);
+ Writer.WriteAttributeString ("id", GetId (o, false));
- if (td.SchemaType != SchemaTypes.Array) // Array use its own "arrayType" attribute
- WriteXsiType(info.TypeName, info.TypeNs);
+ if (td.SchemaType != SchemaTypes.Array) // Array use its own "arrayType" attribute
+ WriteXsiType(info.TypeName, info.TypeNs);
- info.Callback (o);
- WriteEndElement ();
+ info.Callback (o);
+ WriteEndElement ();
+ } else if (IsPrimitiveArray (td)) {
+ WriteArray (o, td);
+ }
+ }
+ }
+
+ bool IsPrimitiveArray (TypeData td)
+ {
+ if (td.SchemaType == SchemaTypes.Array) {
+ if (td.ListItemTypeData.SchemaType == SchemaTypes.Primitive || td.ListItemType == typeof(object))
+ return true;
+ return IsPrimitiveArray (td.ListItemTypeData);
+ } else
+ return false;
+ }
+
+ void WriteArray (object o, TypeData td)
+ {
+ TypeData itemTypeData = td;
+ string xmlType;
+ int nDims = -1;
+
+ do {
+ itemTypeData = itemTypeData.ListItemTypeData;
+ xmlType = itemTypeData.XmlType;
+ nDims++;
}
+ while (itemTypeData.SchemaType == SchemaTypes.Array );
+
+ while (nDims-- > 0)
+ xmlType += "[]";
+
+ WriteStartElement("Array", XmlSerializer.EncodingNamespace, true);
+ Writer.WriteAttributeString("id", GetId(o, false));
+ if (td.SchemaType == SchemaTypes.Array) {
+ Array a = (Array)o;
+ int len = a.Length;
+ Writer.WriteAttributeString("arrayType", XmlSerializer.EncodingNamespace, GetQualifiedName(xmlType, XmlSchema.Namespace) + "[" + len.ToString() + "]");
+ for (int i = 0; i < len; i++) {
+ WritePotentiallyReferencingElement("Item", "", a.GetValue(i), td.ListItemType, false, true);
+ }
+ }
+ WriteEndElement();
}
+
protected void WriteReferencingElement (string n, string ns, object o)
{
WriteReferencingElement (n, ns, o, false);
{
if (referencedElements == null)
{
+#if MOONLIGHT
+ referencedElements = new Queue<object> ();
+#else
referencedElements = new Queue ();
+#endif
InitCallbacks ();
}
}
}
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 ();
}
}
}
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)
{
if (serializedObjects.Contains (o))
- throw new InvalidOperationException ("A cirtular reference was detected while serializing an object of type " + o.GetType().Name);
+ throw new InvalidOperationException ("A circular reference was detected while serializing an object of type " + o.GetType().Name);
else
serializedObjects [o] = o;
}
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)
{
string value;
TypeData td = TypeTranslator.GetTypeData (o.GetType ());
+ 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 ();
}
Writer.WriteString (value);
}
+#if !MOONLIGHT
protected void WriteXmlAttribute (XmlNode node)
{
WriteXmlAttribute (node, null);
WriteAttribute (attr.Prefix, attr.LocalName, attr.NamespaceURI, attr.Value);
}
+#endif
protected void WriteXsiType (string name, string ns)
{
#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)
{
- throw new NotImplementedException ();
+ return new InvalidOperationException (String.Format ("An object of type '{0}' is invalid as anyType in XmlSerializer", t));
}
- [MonoTODO]
protected Exception CreateInvalidEnumValueException (object value, string typeName)
{
- throw new NotImplementedException ();
+ return new InvalidOperationException (string.Format(CultureInfo.CurrentCulture,
+ "'{0}' is not a valid value for {1}.", value, typeName));
}
- [MonoTODO]
protected static string FromEnum (long value, string[] values, long[] ids, string typeName)
{
- throw new NotImplementedException ();
+ return XmlCustomFormatter.FromEnum (value, values, ids, typeName);
}
[MonoTODO]
throw new NotImplementedException ();
}
- [MonoTODO]
- protected void WriteSerializable (IXmlSerializable serializable, string name, string ns, bool isNullable, bool any)
- {
- throw new NotImplementedException ();
- }
-
[MonoTODO]
protected bool EscapeName
{
set { throw new NotImplementedException(); }
}
#endif
-
+
#endregion
class WriteCallbackInfo