2002-08-25 Tim Coleman <tim@timcoleman.com>
[mono.git] / mcs / class / System.XML / System.Xml / XmlTextWriter.cs
index 4df230e6b4d4bdd2b23c7033d8663a019ddcbfe6..c0958b8348d3bbf4a55833303ff0e30725173c60 100644 (file)
@@ -18,28 +18,28 @@ namespace System.Xml
        {
                #region Fields
 
-               protected TextWriter w;
-               protected bool nullEncoding = false;
-               protected bool openWriter = true;
-               protected bool openStartElement = false;
-               protected bool openStartAttribute = false;
-               protected bool documentStarted = false;
-               protected bool namespaces = true;
-               protected bool openAttribute = false;
-               protected bool attributeWrittenForElement = false;
-               protected Stack openElements = new Stack ();
-               protected Formatting formatting = Formatting.None;
-               protected int indentation = 2;
-               protected char indentChar = ' ';
-               protected string indentChars = "  ";
-               protected char quoteChar = '\"';
-               protected int indentLevel = 0;
-               protected string indentFormatting;
-               protected Stream baseStream = null;
-               protected string xmlLang = null;
-               protected XmlSpace xmlSpace = XmlSpace.None;
-               protected bool openXmlLang = false;
-               protected bool openXmlSpace = false;
+               TextWriter w;
+               bool nullEncoding = false;
+               bool openWriter = true;
+               bool openStartElement = false;
+               bool openStartAttribute = false;
+               bool documentStarted = false;
+               bool namespaces = true;
+               bool openAttribute = false;
+               bool attributeWrittenForElement = false;
+               Stack openElements = new Stack ();
+               Formatting formatting = Formatting.None;
+               int indentation = 2;
+               char indentChar = ' ';
+               string indentChars = "  ";
+               char quoteChar = '\"';
+               int indentLevel = 0;
+               string indentFormatting;
+               Stream baseStream = null;
+               string xmlLang = null;
+               XmlSpace xmlSpace = XmlSpace.None;
+               bool openXmlLang = false;
+               bool openXmlSpace = false;
 
                #endregion
 
@@ -48,6 +48,7 @@ namespace System.Xml
                public XmlTextWriter (TextWriter w) : base ()
                {
                        this.w = w;
+                       nullEncoding = (w.Encoding == null);
                        
                        try {
                                baseStream = ((StreamWriter)w).BaseStream;
@@ -86,7 +87,7 @@ namespace System.Xml
                        set { formatting = value; }
                }
 
-               public bool IndentingOverriden 
+               private bool IndentingOverriden 
                {
                        get {
                                if (openElements.Count == 0)
@@ -181,7 +182,6 @@ namespace System.Xml
                        if (!openWriter) {
                                throw new InvalidOperationException ("The Writer is closed.");
                        }
-
                        if ((documentStarted == true) && (formatting == Formatting.Indented) && (!IndentingOverriden)) {
                                indentFormatting = "\r\n";
                                if (indentLevel > 0) {
@@ -197,19 +197,26 @@ namespace System.Xml
 
                public override void Close ()
                {
-                       while (openElements.Count > 0) {
-                               WriteEndElement();
-                       }
+                       CloseOpenAttributeAndElements ();
 
                        w.Close();
                        ws = WriteState.Closed;
                        openWriter = false;
                }
 
+               private void CloseOpenAttributeAndElements ()
+               {
+                       if (openAttribute)
+                               WriteEndAttribute ();
+
+                       while (openElements.Count > 0) {
+                               WriteEndElement();
+                       }
+               }
+
                private void CloseStartElement ()
                {
-                       if (openStartElement) 
-                       {
+                       if (openStartElement) {
                                w.Write(">");
                                ws = WriteState.Content;
                                openStartElement = false;
@@ -322,27 +329,40 @@ namespace System.Xml
                        openAttribute = false;
                }
 
-               [MonoTODO]
                public override void WriteEndDocument ()
                {
-                       throw new NotImplementedException ();
+                       if ((ws == WriteState.Start) || (ws == WriteState.Prolog))
+                               throw new ArgumentException ("This document does not have a root element.");
+
+                       CloseOpenAttributeAndElements ();
+
+                       ws = WriteState.Start;
                }
 
                public override void WriteEndElement ()
+               {
+                       WriteEndElementInternal (false);
+               }
+
+               private void WriteEndElementInternal (bool fullEndElement)
                {
                        if (openElements.Count == 0)
                                throw new InvalidOperationException("There was no XML start tag open.");
 
                        indentLevel--;
-
                        CheckState ();
 
                        if (openStartElement) {
-                               w.Write (" />");
+                               if (openAttribute)
+                                       WriteEndAttribute ();
+                               if (fullEndElement)
+                                       w.Write ("></{0}>", ((XmlTextWriterOpenElement)openElements.Peek ()).Name);
+                               else
+                                       w.Write (" />");
+
                                openElements.Pop ();
                                openStartElement = false;
-                       }
-                       else {
+                       } else {
                                w.Write ("{0}</{1}>", indentFormatting, openElements.Pop ());
                        }
 
@@ -355,10 +375,9 @@ namespace System.Xml
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO]
                public override void WriteFullEndElement ()
                {
-                       throw new NotImplementedException ();
+                       WriteEndElementInternal (true);
                }
 
                [MonoTODO]
@@ -388,13 +407,16 @@ namespace System.Xml
                [MonoTODO]
                public override void WriteQualifiedName (string localName, string ns)
                {
-                       throw new NotImplementedException ();
+                       if (localName == null || localName == String.Empty)
+                               throw new ArgumentException ();
+
+                       CheckState ();
+                       w.Write ("{0}:{1}", ns, localName);
                }
 
-               [MonoTODO]
                public override void WriteRaw (string data)
                {
-                       throw new NotImplementedException ();
+                       WriteStringInternal (data, false);
                }
 
                [MonoTODO]
@@ -477,7 +499,7 @@ namespace System.Xml
 
                        string encodingFormatting = "";
 
-                       if (!nullEncoding)
+                       if (!nullEncoding) 
                                encodingFormatting = String.Format (" encoding={0}{1}{0}", quoteChar, w.Encoding.HeaderName);
 
                        w.Write("<?xml version={0}1.0{0}{1}{2}?>", quoteChar, encodingFormatting, standaloneFormatting);
@@ -493,52 +515,55 @@ namespace System.Xml
                        WriteStartElementInternal (prefix, localName, ns);
                }
 
-               protected override void WriteStartElementInternal (string prefix, string localName, string ns)
+               private void WriteStartElementInternal (string prefix, string localName, string ns)
                {
                        if (prefix == null)
                                prefix = String.Empty;
 
-                       if (ns == null)
-                               ns = String.Empty;
-
                        if ((prefix != String.Empty) && ((ns == null) || (ns == String.Empty)))
                                throw new ArgumentException ("Cannot use a prefix with an empty namespace.");
 
                        CheckState ();
                        CloseStartElement ();
-
+                       
                        string formatXmlns = "";
                        string formatPrefix = "";
 
-                       if (ns != String.Empty) 
+                       if(ns != null)
                        {
-                               string existingPrefix = namespaceManager.LookupPrefix (ns);
+                               if (ns != String.Empty) 
+                               {
+                                       string existingPrefix = namespaceManager.LookupPrefix (ns);
 
-                               if (prefix == String.Empty)
-                                       prefix = existingPrefix;
+                                       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 != 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) {
-                               formatPrefix = prefix + ":";
+                               if (prefix != String.Empty) {
+                                       formatPrefix = prefix + ":";
+                               }
                        }
 
                        w.Write ("{0}<{1}{2}{3}", indentFormatting, formatPrefix, localName, formatXmlns);
+       
 
                        openElements.Push (new XmlTextWriterOpenElement (formatPrefix + localName));
                        ws = WriteState.Element;
                        openStartElement = true;
 
                        namespaceManager.PushScope ();
-                       namespaceManager.AddNamespace (prefix, ns);
-
+                       if(ns != null)
+                       {
+                               namespaceManager.AddNamespace (prefix, ns);
+                       }
                        indentLevel++;
                }
 
@@ -547,33 +572,48 @@ namespace System.Xml
                        if (ws == WriteState.Prolog)
                                throw new InvalidOperationException ("Token content in state Prolog would result in an invalid XML document.");
 
+                       WriteStringInternal (text, true);
+               }
+
+               private void WriteStringInternal (string text, bool entitize)
+               {
                        if (text == null)
                                text = String.Empty;
 
-                       if (text != String.Empty) {
+                       if (text != String.Empty) 
+                       {
                                CheckState ();
 
-                               text = text.Replace ("&", "&amp;");
-                               text = text.Replace ("<", "&lt;");
-                               text = text.Replace (">", "&gt;");
-                               
-                               if (openAttribute) {
-                                       if (quoteChar == '"')
-                                               text = text.Replace ("\"", "&quot;");
-                                       else
-                                               text = text.Replace ("'", "&apos;");
+                               if (entitize)
+                               {
+                                       text = text.Replace ("&", "&amp;");
+                                       text = text.Replace ("<", "&lt;");
+                                       text = text.Replace (">", "&gt;");
+                                       
+                                       if (openAttribute) 
+                                       {
+                                               if (quoteChar == '"')
+                                                       text = text.Replace ("\"", "&quot;");
+                                               else
+                                                       text = text.Replace ("'", "&apos;");
+                                       }
                                }
 
                                if (!openAttribute)
+                               {
+                                       IndentingOverriden = true;
                                        CloseStartElement ();
-
+                               }
                                if (!openXmlLang && !openXmlSpace)
                                        w.Write (text);
-                               else {
+                               else 
+                               {
                                        if (openXmlLang)
                                                xmlLang = text;
-                                       else {
-                                               switch (text) {
+                                       else 
+                                       {
+                                               switch (text) 
+                                               {
                                                        case "default":
                                                                xmlSpace = XmlSpace.Default;
                                                                break;
@@ -586,8 +626,6 @@ namespace System.Xml
                                        }
                                }
                        }
-
-                       IndentingOverriden = true;
                }
 
                [MonoTODO]