2003-02-28 Alan Tam <Tam@SiuLung.com>
[mono.git] / mcs / class / System.XML / System.Xml / XmlTextWriter.cs
index b1f3c4df9ce5e38ae112b533574edaee18653766..3f6c19e29841cd6cd77cfe291943e82d5c6c3f45 100644 (file)
@@ -40,6 +40,9 @@ namespace System.Xml
                XmlSpace xmlSpace = XmlSpace.None;
                bool openXmlLang = false;
                bool openXmlSpace = false;
+               string openElementPrefix;
+               string openElementNS;
+               bool hasRoot = false;
 
                #endregion
 
@@ -175,6 +178,44 @@ namespace System.Xml
                #endregion
 
                #region Methods
+               private void AddMissingElementXmlns ()
+               {
+                       // output namespace declaration if not exist.
+                       string prefix = openElementPrefix;
+                       string ns = openElementNS;
+                       if (ns != null/* && LookupPrefix (ns) != prefix*/) 
+                       {
+                               string formatXmlns = String.Empty;
+                               if (ns != String.Empty)
+                               {
+                                       string existingPrefix = namespaceManager.LookupPrefix (ns);
+                                       bool addDefaultNamespace = false;
+
+                                       if (existingPrefix == null) 
+                                       {
+                                               namespaceManager.AddNamespace (prefix, ns);
+                                               addDefaultNamespace = true;
+                                       }
+
+                                       if (prefix == String.Empty)
+                                               prefix = existingPrefix;
+
+                                       if (prefix != existingPrefix)
+                                               formatXmlns = String.Format (" xmlns:{0}={1}{2}{1}", prefix, quoteChar, ns);
+                                       else if (addDefaultNamespace)
+                                               formatXmlns = String.Format (" xmlns={0}{1}{0}", quoteChar, ns);
+                               } 
+                               else if ((prefix == String.Empty) && (namespaceManager.LookupNamespace (prefix) != String.Empty)) 
+                               {
+                                       namespaceManager.AddNamespace (prefix, ns);
+                                       formatXmlns = String.Format (" xmlns={0}{0}", quoteChar);
+                               }
+                               if(formatXmlns != String.Empty)
+                                       w.Write(formatXmlns);
+                               openElementPrefix = null;
+                               openElementNS = null;
+                       }
+               }
 
                private void CheckState ()
                {
@@ -182,7 +223,7 @@ namespace System.Xml
                                throw new InvalidOperationException ("The Writer is closed.");
                        }
                        if ((documentStarted == true) && (formatting == Formatting.Indented) && (!IndentingOverriden)) {
-                               indentFormatting = "\r\n";
+                               indentFormatting = w.NewLine;
                                if (indentLevel > 0) {
                                        for (int i = 0; i < indentLevel; i++)
                                                indentFormatting += indentChars;
@@ -215,12 +256,15 @@ namespace System.Xml
 
                private void CloseStartElement ()
                {
-                       if (openStartElement) {
-                               w.Write(">");
-                               ws = WriteState.Content;
-                               openStartElement = false;
-                               attributeWrittenForElement = false;
-                       }
+                       if (!openStartElement)
+                               return;
+
+                       AddMissingElementXmlns ();
+
+                       w.Write (">");
+                       ws = WriteState.Content;
+                       openStartElement = false;
+                       attributeWrittenForElement = false;
                }
 
                public override void Flush ()
@@ -232,9 +276,10 @@ namespace System.Xml
                {
                        string prefix = namespaceManager.LookupPrefix (ns);
 
-                       if (prefix == String.Empty)
-                               prefix = null;
-
+                       // XmlNamespaceManager has changed to return null when NSURI not found.
+                       // (Contradiction to the documentation.)
+                       //if (prefix == String.Empty)
+                       //      prefix = null;
                        return prefix;
                }
 
@@ -345,10 +390,11 @@ namespace System.Xml
                {
                        CloseOpenAttributeAndElements ();
 
-                       if ((ws == WriteState.Start) || (ws == WriteState.Prolog))
+                       if (!hasRoot)
                                throw new ArgumentException ("This document does not have a root element.");
 
                        ws = WriteState.Start;
+                       hasRoot = false;
                }
 
                public override void WriteEndElement ()
@@ -363,6 +409,7 @@ namespace System.Xml
 
                        indentLevel--;
                        CheckState ();
+                       AddMissingElementXmlns ();
 
                        if (openStartElement) {
                                if (openAttribute)
@@ -440,10 +487,9 @@ namespace System.Xml
                        WriteStringInternal (data, false);
                }
 
-               [MonoTODO]
                public override void WriteRaw (char[] buffer, int index, int count)
                {
-                       throw new NotImplementedException ();
+                       WriteStringInternal (new string (buffer, index, count), false);
                }
 
                public override void WriteStartAttribute (string prefix, string localName, string ns)
@@ -476,7 +522,8 @@ namespace System.Xml
                                string existingPrefix = namespaceManager.LookupPrefix (ns);
 
                                if (prefix == String.Empty)
-                                       prefix = existingPrefix;
+                                       prefix = (existingPrefix == null) ?
+                                               String.Empty : existingPrefix;
                        }
 
                        if (prefix != String.Empty) 
@@ -516,6 +563,11 @@ namespace System.Xml
                        if (documentStarted == true)
                                throw new InvalidOperationException("WriteStartDocument should be the first call.");
 
+                       if (hasRoot)
+                               throw new XmlException ("WriteStartDocument called twice.");
+
+                       hasRoot = true;
+
                        CheckState ();
 
                        string encodingFormatting = "";
@@ -538,39 +590,23 @@ namespace System.Xml
 
                private void WriteStartElementInternal (string prefix, string localName, string ns)
                {
-                       if (prefix == null)
-                               prefix = String.Empty;
-
-                       if ((prefix != String.Empty) && ((ns == null) || (ns == String.Empty)))
+                       if ((prefix != null && prefix != String.Empty) && ((ns == null) || (ns == String.Empty)))
                                throw new ArgumentException ("Cannot use a prefix with an empty namespace.");
 
                        CheckState ();
                        CloseStartElement ();
                        
+                       if (prefix == null)
+                               prefix = namespaceManager.LookupPrefix (ns);
+                       if (prefix == null)
+                               prefix = String.Empty;
+
                        string formatXmlns = "";
                        string formatPrefix = "";
 
-                       if(ns != null)
-                       {
-                               if (ns != String.Empty) 
-                               {
-                                       string existingPrefix = namespaceManager.LookupPrefix (ns);
-
-                                       if (prefix == String.Empty)
-                                               prefix = existingPrefix;
-
-                                       if (prefix != existingPrefix)
-                                               formatXmlns = String.Format (" xmlns:{0}={1}{2}{1}", prefix, quoteChar, ns);
-                                       else if (existingPrefix == String.Empty)
-                                               formatXmlns = String.Format (" xmlns={0}{1}{0}", quoteChar, ns);
-                               }
-                               else if ((prefix == String.Empty) && (namespaceManager.LookupNamespace(prefix) != String.Empty)) {
-                                       formatXmlns = String.Format (" xmlns={0}{0}", quoteChar);
-                               }
-
-                               if (prefix != String.Empty) {
+                       if(ns != null) {
+                               if (prefix != String.Empty)
                                        formatPrefix = prefix + ":";
-                               }
                        }
 
                        w.Write ("{0}<{1}{2}{3}", indentFormatting, formatPrefix, localName, formatXmlns);
@@ -579,12 +615,12 @@ namespace System.Xml
                        openElements.Push (new XmlTextWriterOpenElement (formatPrefix + localName));
                        ws = WriteState.Element;
                        openStartElement = true;
+                       openElementNS = ns;
+                       openElementPrefix = prefix;
 
                        namespaceManager.PushScope ();
-                       if(ns != null)
-                       {
-                               namespaceManager.AddNamespace (prefix, ns);
-                       }
+//                     if(ns != null)
+//                             namespaceManager.AddNamespace (prefix, ns);
                        indentLevel++;
                }