2010-06-30 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / class / System.XML / System.Xml / XmlWriter.cs
index 00e3c0df0d27c10162538822e5d6da0b1bbd2f58..b54681130505db35dc0553563bff0f5d53da6bb0 100644 (file)
@@ -7,6 +7,7 @@
 //
 // (C) 2002 Kral Ferch
 // (C) 2002-2003 Atsushi Enomoto
+// (C) 2004-2007 Novell, Inc.
 //
 
 //
 //
 
 using System;
+using System.Collections;
 using System.IO;
 using System.Text;
-#if NET_2_0
+#if !MOONLIGHT
 using System.Xml.XPath;
 #endif
 
 namespace System.Xml
 {
-#if NET_2_0
        public abstract class XmlWriter : IDisposable
-#else
-       public abstract class XmlWriter
-#endif
        {
 #if NET_2_0
                XmlWriterSettings settings;
@@ -59,11 +57,7 @@ namespace System.Xml
 
 #if NET_2_0
                public virtual XmlWriterSettings Settings {
-                       get {
-                               if (settings == null)
-                                       settings = new XmlWriterSettings ();
-                               return settings;
-                       }
+                       get { return settings; }
                }
 #endif
 
@@ -125,7 +119,7 @@ namespace System.Xml
                public static XmlWriter Create (string file, XmlWriterSettings settings)
                {
                        Encoding enc = settings != null ? settings.Encoding : Encoding.UTF8;
-                       return Create (new StreamWriter (file, false, enc), settings);
+                       return CreateTextWriter (new StreamWriter (file, false, enc), settings, true);
                }
 
                public static XmlWriter Create (StringBuilder builder, XmlWriterSettings settings)
@@ -135,38 +129,53 @@ namespace System.Xml
 
                public static XmlWriter Create (TextWriter writer, XmlWriterSettings settings)
                {
-                       return CreateTextWriter (writer, settings);
+                       if (settings == null)
+                               settings = new XmlWriterSettings ();
+                       return CreateTextWriter (writer, settings, settings.CloseOutput);
                }
 
                public static XmlWriter Create (XmlWriter writer, XmlWriterSettings settings)
                {
                        if (settings == null)
                                settings = new XmlWriterSettings ();
-                       writer.settings = settings;
+                       else
+                               settings = settings.Clone ();
+
+                       var src = writer.Settings;
+                       if (src == null) {
+                               settings.ConformanceLevel = ConformanceLevel.Document; // Huh? Why??
+                               writer = new DefaultXmlWriter (writer);
+                               writer.settings = settings;
+                       } else {
+                               ConformanceLevel dst = src.ConformanceLevel;
+                               switch (src.ConformanceLevel) {
+                               case ConformanceLevel.Auto:
+                                       dst = settings.ConformanceLevel;
+                                       break;
+                               case ConformanceLevel.Document:
+                               case ConformanceLevel.Fragment:
+                                       if (settings.ConformanceLevel != ConformanceLevel.Auto)
+                                               dst = settings.ConformanceLevel;
+                                       break;
+                               }
+
+                               settings.MergeFrom (src);
+
+                               // It returns a new XmlWriter instance if 1) Settings is null, or 2) Settings ConformanceLevel (or might be other members as well) give significant difference.
+                               if (src.ConformanceLevel != dst) {
+                                       writer = new DefaultXmlWriter (writer, false);
+                                       writer.settings = settings;
+                               }
+                       }
+
                        return writer;
                }
 
-               private static XmlWriter CreateTextWriter (TextWriter writer, XmlWriterSettings settings)
+               private static XmlWriter CreateTextWriter (TextWriter writer, XmlWriterSettings settings, bool closeOutput)
                {
                        if (settings == null)
                                settings = new XmlWriterSettings ();
-                       XmlTextWriter xtw = new XmlTextWriter (writer);
-                       // Indent, IndentChars
-                       if (settings.Indent) {
-                               xtw.Formatting = Formatting.Indented;
-                               xtw.IndentChars = settings.IndentChars;
-                               xtw.NewLineOnAttributes = settings.NewLineOnAttributes;
-                       }
-                       // NewLineChars
-                       xtw.NewLineChars = settings.NewLineChars;
-                       // CloseOutput
-                       xtw.CloseOutput = settings.CloseOutput;
-                       // ConformanceLevel
-                       xtw.ConformanceLevel = settings.ConformanceLevel;
-                       // OmitXmlDeclaration
-                       xtw.OmitXmlDeclaration = settings.OmitXmlDeclaration;
-                       // CheckCharacters
-                       xtw.CheckCharacters = settings.CheckCharacters;
+                       XmlTextWriter xtw = new XmlTextWriter (writer, settings, closeOutput);
                        return Create (xtw, settings);
                }
 
@@ -191,6 +200,10 @@ namespace System.Xml
                                return;
 
                        WriteStartAttribute (reader.Prefix, reader.LocalName, reader.NamespaceURI);
+#if MOONLIGHT
+                       // no ReadAttributeValue() in 2.1 profile.
+                       WriteString (reader.Value);
+#else
                        while (reader.ReadAttributeValue ()) {
                                switch (reader.NodeType) {
                                case XmlNodeType.Text:
@@ -201,6 +214,7 @@ namespace System.Xml
                                        break;
                                }
                        }
+#endif
                        WriteEndAttribute ();
                }
 
@@ -399,21 +413,17 @@ namespace System.Xml
                                WriteString (localName);
                }
 
-#if NET_2_0
-               [MonoTODO ("test defattr handling")]
+#if !MOONLIGHT
                public virtual void WriteNode (XPathNavigator navigator, bool defattr)
                {
                        if (navigator == null)
                                throw new ArgumentNullException ("navigator");
                        switch (navigator.NodeType) {
                        case XPathNodeType.Attribute:
+                               // no operation
+                               break;
                        case XPathNodeType.Namespace:
-                               if (defattr || navigator.SchemaInfo == null ||
-                                   !navigator.SchemaInfo.IsDefault)
-                                       WriteAttributeString (navigator.Prefix, 
-                                               navigator.LocalName,
-                                               navigator.NamespaceURI,
-                                               navigator.Value);
+                               // no operation
                                break;
                        case XPathNodeType.Text:
                                WriteString (navigator.Value);
@@ -442,13 +452,19 @@ namespace System.Xml
                                WriteStartElement (navigator.Prefix, navigator.LocalName, navigator.NamespaceURI);
                                if (navigator.MoveToFirstNamespace (XPathNamespaceScope.Local)) {
                                        do {
-                                               WriteNode (navigator, defattr);
+                                               if (defattr || navigator.SchemaInfo == null || navigator.SchemaInfo.IsDefault)
+                                                       WriteAttributeString (navigator.Prefix,
+                                                               navigator.LocalName == String.Empty ? "xmlns" : navigator.LocalName,
+                                                               "http://www.w3.org/2000/xmlns/",
+                                                               navigator.Value);
                                        } while (navigator.MoveToNextNamespace (XPathNamespaceScope.Local));
                                        navigator.MoveToParent ();
                                }
                                if (navigator.MoveToFirstAttribute ()) {
                                        do {
-                                               WriteNode (navigator, defattr);
+                                               if (defattr || navigator.SchemaInfo == null || navigator.SchemaInfo.IsDefault)
+                                                       WriteAttributeString (navigator.Prefix, navigator.LocalName, navigator.NamespaceURI, navigator.Value);
+
                                        } while (navigator.MoveToNextAttribute ());
                                        navigator.MoveToParent ();
                                }
@@ -599,74 +615,96 @@ namespace System.Xml
                public abstract void WriteWhitespace (string ws);
 
 #if NET_2_0
-               [MonoTODO]
                public virtual void WriteValue (bool value)
                {
                        WriteString (XQueryConvert.BooleanToString (value));
                }
 
-               [MonoTODO]
                public virtual void WriteValue (DateTime value)
                {
                        WriteString (XmlConvert.ToString (value));
                }
 
-               [MonoTODO]
                public virtual void WriteValue (decimal value)
                {
                        WriteString (XQueryConvert.DecimalToString (value));
                }
 
-               [MonoTODO]
                public virtual void WriteValue (double value)
                {
                        WriteString (XQueryConvert.DoubleToString (value));
                }
 
-               [MonoTODO]
                public virtual void WriteValue (int value)
                {
                        WriteString (XQueryConvert.IntToString (value));
                }
 
-               [MonoTODO]
                public virtual void WriteValue (long value)
                {
                        WriteString (XQueryConvert.IntegerToString (value));
                }
 
-               [MonoTODO]
                public virtual void WriteValue (object value)
                {
+                       if (value == null)
+                               throw new ArgumentNullException ("value");
+
                        if (value is string)
                                WriteString ((string) value);
                        else if (value is bool)
                                WriteValue ((bool) value);
+                       else if (value is byte)
+                               WriteValue ((int) value);
+                       else if (value is byte [])
+                               WriteBase64 ((byte []) value, 0, ((byte []) value).Length);
+                       else if (value is char [])
+                               WriteChars ((char []) value, 0, ((char []) value).Length);
                        else if (value is DateTime)
                                WriteValue ((DateTime) value);
                        else if (value is decimal)
                                WriteValue ((decimal) value);
                        else if (value is double)
                                WriteValue ((double) value);
+                       else if (value is short)
+                               WriteValue ((int) value);
                        else if (value is int)
                                WriteValue ((int) value);
                        else if (value is long)
                                WriteValue ((long) value);
+                       else if (value is float)
+                               WriteValue ((float) value);
+                       else if (value is TimeSpan) // undocumented
+                               WriteString (XmlConvert.ToString ((TimeSpan) value));
                        else if (value is XmlQualifiedName) {
                                XmlQualifiedName qname = (XmlQualifiedName) value;
-                               WriteQualifiedName (qname.Name, qname.Namespace);
+                               if (!qname.Equals (XmlQualifiedName.Empty)) {
+                                       if (qname.Namespace.Length > 0 && LookupPrefix (qname.Namespace) == null)
+                                               throw new InvalidCastException (String.Format ("The QName '{0}' cannot be written. No corresponding prefix is declared", qname));
+                                       WriteQualifiedName (qname.Name, qname.Namespace);
+                               }
+                               else
+                                       WriteString (String.Empty);
+                       }
+                       else if (value is IEnumerable) {
+                               bool follow = false;
+                               foreach (object obj in (IEnumerable) value) {
+                                       if (follow)
+                                               WriteString (" ");
+                                       else
+                                               follow = true;
+                                       WriteValue (obj);
+                               }
                        }
                        else
-                               throw new NotImplementedException ("Argument value is " + value);
+                               throw new InvalidCastException (String.Format ("Type '{0}' cannot be cast to string", value.GetType ()));
                }
 
-               [MonoTODO]
                public virtual void WriteValue (float value)
                {
                        WriteString (XQueryConvert.FloatToString (value));
                }
 
-               [MonoTODO]
                public virtual void WriteValue (string value)
                {
                        WriteString (value);