XmlTextWriter formatting, indenting, xml declaration stuff.
authorKral Ferch <kral@mono-cvs.ximian.com>
Sat, 23 Mar 2002 04:38:35 +0000 (04:38 -0000)
committerKral Ferch <kral@mono-cvs.ximian.com>
Sat, 23 Mar 2002 04:38:35 +0000 (04:38 -0000)
svn path=/trunk/mcs/; revision=3277

mcs/class/System.XML/Mono.System.XML.csproj
mcs/class/System.XML/System.Xml/ChangeLog
mcs/class/System.XML/System.Xml/XmlNodeListChildren.cs
mcs/class/System.XML/System.Xml/XmlTextWriter.cs
mcs/class/System.XML/Test/ChangeLog
mcs/class/System.XML/Test/XmlTextWriterTests.cs

index 1d730000fe7cb4d5c838011de0393738ee0791a1..3bcb502777d7f785054c6017b7c9ed60f6469a57 100644 (file)
                     SubType = "Code"
                     BuildAction = "Compile"
                 />
+                <File
+                    RelPath = "System.Xml\XmlTextWriterOpenElement.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
                 <File
                     RelPath = "System.Xml\XmlTokenizedType.cs"
                     SubType = "Code"
index db6058fb9746732a643b1cd17e65ef9a399cce9c..74aef79615f4de393f55342381a95dd9412fcd95 100644 (file)
@@ -1,3 +1,19 @@
+2002-03-23  Kral Ferch <kral_ferch@hotmail.com>
+
+       * XmlNodeListChildren.cs: made class internal
+       instead of public.  Shouldn't be visible outside
+       of System.Xml.
+       
+       * XmlTextWriter.cs: Implementations for Formatting,
+       IndentChar, Indenting, QuoteChar, WriteStartDocument(standalone).
+       Suppresses encoding on xml declaration if null stream passed in.
+       Formats output including suppressing indentation for elements in
+       mixed content mode.
+       
+       * XmlTextWriterOpenElement.cs: Initial checkin.
+       XmlTextWriter uses stack of these objects to track
+       state.
+       
 2002-03-22  Mike Kestner  <mkestner@speakeasy.net>
 
        * XmlElement.cs: impl HasAttribute(string name).
index ad46257780436de5dff45e0d1f5da7ff2c76d5c9..c5d6282350371a6237cc5d109809bdc1592f9768 100644 (file)
@@ -12,7 +12,7 @@ using System.Collections;
 
 namespace System.Xml
 {
-       public class XmlNodeListChildren : XmlNodeList
+       internal class XmlNodeListChildren : XmlNodeList
        {
                #region Enumerator
 
index 38eaee5d5521b6163324f04ab240457a850a5ccf..f88e20f6a72270bb4ea3b031d59de6f065a2afeb 100644 (file)
@@ -19,11 +19,19 @@ namespace System.Xml
                #region Fields
 
                protected TextWriter w;
+               protected bool nullEncoding = false;
                protected bool openWriter = true;
                protected bool openStartElement;
                protected bool documentStarted = false;
                protected Stack openElements = new Stack ();
                protected XmlNamespaceManager namespaceManager = new XmlNamespaceManager (new NameTable ());
+               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;
 
                #endregion
 
@@ -36,6 +44,11 @@ namespace System.Xml
 
                public XmlTextWriter (Stream w, Encoding encoding) : base ()
                {
+                       if (encoding == null) {
+                               nullEncoding = true;
+                               encoding = new UTF8Encoding ();
+                       }
+
                        this.w = new StreamWriter(w, encoding);
                }
 
@@ -54,22 +67,39 @@ namespace System.Xml
                }
 
 
-               [MonoTODO]
                public Formatting Formatting {
-                       get { throw new NotImplementedException(); }
-                       set { throw new NotImplementedException(); }
+                       get { return formatting; }
+                       set { formatting = value; }
+               }
+
+               public bool IndentingOverriden 
+               {
+                       get {
+                               if (openElements.Count == 0)
+                                       return false;
+                               else
+                                       return (((XmlTextWriterOpenElement)openElements.Peek()).IndentingOverriden);
+                       }
+                       set {
+                               if (openElements.Count > 0)
+                                       ((XmlTextWriterOpenElement)openElements.Peek()).IndentingOverriden = value;
+                       }
                }
 
-               [MonoTODO]
                public int Indentation {
-                       get { throw new NotImplementedException(); }
-                       set { throw new NotImplementedException(); }
+                       get { return indentation; }
+                       set {
+                               indentation = value;
+                               UpdateIndentChars ();
+                       }
                }
 
-               [MonoTODO]
                public char IndentChar {
-                       get { throw new NotImplementedException(); }
-                       set { throw new NotImplementedException(); }
+                       get { return indentChar; }
+                       set {
+                               indentChar = value;
+                               UpdateIndentChars ();
+                       }
                }
 
                [MonoTODO]
@@ -80,8 +110,13 @@ namespace System.Xml
 
                [MonoTODO]
                public char QuoteChar {
-                       get { throw new NotImplementedException(); }
-                       set { throw new NotImplementedException(); }
+                       get { return quoteChar; }
+                       set {
+                               if ((value != '\'') && (value != '\"'))
+                                       throw new ArgumentException ("This is an invalid XML attribute quote character. Valid attribute quote characters are ' and \".");
+                               
+                               quoteChar = value;
+                       }
                }
 
                [MonoTODO]
@@ -109,6 +144,16 @@ namespace System.Xml
                                throw new InvalidOperationException ("The Writer is closed.");
                        }
 
+                       if ((documentStarted == true) && (formatting == Formatting.Indented) && (!IndentingOverriden)) {
+                               indentFormatting = "\r\n";
+                               if (indentLevel > 0) {
+                                       for (int i = 0; i < indentLevel; i++)
+                                               indentFormatting += indentChars;
+                               }
+                       }
+                       else
+                               indentFormatting = "";
+
                        documentStarted = true;
                }
 
@@ -132,10 +177,9 @@ namespace System.Xml
                        }
                }
 
-               [MonoTODO]
                public override void Flush ()
                {
-                       throw new NotImplementedException ();
+                       w.Flush ();
                }
 
                [MonoTODO]
@@ -144,6 +188,13 @@ namespace System.Xml
                        throw new NotImplementedException ();
                }
 
+               private void UpdateIndentChars ()
+               {
+                       indentChars = "";
+                       for (int i = 0; i < indentation; i++)
+                               indentChars += indentChar;
+               }
+
                [MonoTODO]
                public override void WriteBase64 (byte[] buffer, int index, int count)
                {
@@ -216,6 +267,8 @@ namespace System.Xml
                        if (openElements.Count == 0)
                                throw new InvalidOperationException("There was no XML start tag open.");
 
+                       indentLevel--;
+
                        CheckState ();
 
                        if (openStartElement) {
@@ -224,7 +277,7 @@ namespace System.Xml
                                openStartElement = false;
                        }
                        else {
-                               w.Write ("</{0}>", openElements.Pop ());
+                               w.Write ("{0}</{1}>", indentFormatting, openElements.Pop ());
                                namespaceManager.PopScope();
                        }
                }
@@ -262,7 +315,7 @@ namespace System.Xml
                        CheckState ();
                        CloseStartElement ();
 
-                       w.Write ("<?{0} {1}?>", name, text);
+                       w.Write ("{0}<?{1} {2}?>", indentFormatting, name, text);
                }
 
                [MonoTODO]
@@ -291,19 +344,34 @@ namespace System.Xml
 
                public override void WriteStartDocument ()
                {
-                       if (documentStarted == true) {
-                               throw new InvalidOperationException("WriteStartDocument should be the first call.");
-                       }
+                       WriteStartDocument ("");
+               }
 
-                       CheckState ();
+               public override void WriteStartDocument (bool standalone)
+               {
+                       string standaloneFormatting;
+
+                       if (standalone == true)
+                               standaloneFormatting = " standalone=\"yes\"";
+                       else
+                               standaloneFormatting = " standalone=\"no\"";
 
-                       w.Write("<?xml version=\"1.0\" encoding=\"" + w.Encoding.HeaderName + "\"?>");
+                       WriteStartDocument (standaloneFormatting);
                }
 
-               [MonoTODO]
-               public override void WriteStartDocument (bool standalone)
+               private void WriteStartDocument (string standaloneFormatting)
                {
-                       throw new NotImplementedException ();
+                       if (documentStarted == true)
+                               throw new InvalidOperationException("WriteStartDocument should be the first call.");
+
+                       CheckState ();
+
+                       string encodingFormatting = "";
+
+                       if (!nullEncoding)
+                               encodingFormatting = " encoding=\"" + w.Encoding.HeaderName + "\"";
+
+                       w.Write("<?xml version=\"1.0\"{0}{1}?>", encodingFormatting, standaloneFormatting);
                }
 
                public override void WriteStartElement (string prefix, string localName, string ns)
@@ -337,13 +405,15 @@ namespace System.Xml
                                formatPrefix = prefix + ":";
                        }
 
-                       w.Write ("<{0}{1}{2}", formatPrefix, localName, formatXmlns);
+                       w.Write ("{0}<{1}{2}{3}", indentFormatting, formatPrefix, localName, formatXmlns);
 
-                       openElements.Push (formatPrefix + localName);
+                       openElements.Push (new XmlTextWriterOpenElement (formatPrefix + localName));
                        openStartElement = true;
 
                        namespaceManager.PushScope ();
                        namespaceManager.AddNamespace (prefix, ns);
+
+                       indentLevel++;
                }
 
                [MonoTODO("Haven't done any entity replacements yet.")]
@@ -354,6 +424,8 @@ namespace System.Xml
                                CloseStartElement ();
                                w.Write (text);
                        }
+
+                       IndentingOverriden = true;
                }
 
                [MonoTODO]
index bf710249c654d88ef2a3bd075f761efef0288fa5..2bd719d4050f13a3c18c48f992e698690a1c119e 100644 (file)
@@ -1,3 +1,11 @@
+2002-03-23  Kral Ferch <kral_ferch@hotmail.com>
+
+       * XmlTextWriterTests.cs: constructor tests with
+       different encodings to test that encoding gets suppressed
+       on xml declaration when null stream passed to constructor.
+       WriteStartDocument(standalone) tests.  Tests for formatting
+       and indentation.  Test for invalid value set on QuoteChar.
+
 2002-03-22  Duncan Mak  <duncan@ximian.com>
 
        * AllTests.cs: 
index 1cd2aa83bfb20e2f4cd241baa6276cfb8a12eb51..805ae83a899befb9ea62068608d6979abc717a2c 100644 (file)
@@ -9,6 +9,7 @@
 
 using System;
 using System.IO;
+using System.Text;
 using System.Xml;
 
 using NUnit.Framework;
@@ -125,6 +126,53 @@ namespace Ximian.Mono.Tests
                        catch (ArgumentException) { }
                }
 
+               public void TestConstructors ()
+               {
+                       MemoryStream ms;
+                       StreamReader sr;
+                       XmlTextWriter xtw;
+
+                       ms = new MemoryStream ();
+                       xtw = new XmlTextWriter (ms, new UnicodeEncoding ());
+                       xtw.WriteStartDocument ();
+                       xtw.Flush ();
+                       ms.Seek (0, SeekOrigin.Begin);
+                       sr = new StreamReader (ms);
+                       AssertEquals ("<?xml version=\"1.0\" encoding=\"utf-16\"?>", sr.ReadToEnd ());
+
+                       ms = new MemoryStream ();
+                       xtw = new XmlTextWriter (ms, new UnicodeEncoding ());
+                       xtw.WriteStartDocument (true);
+                       xtw.Flush ();
+                       ms.Seek (0, SeekOrigin.Begin);
+                       sr = new StreamReader (ms);
+                       AssertEquals ("<?xml version=\"1.0\" encoding=\"utf-16\" standalone=\"yes\"?>", sr.ReadToEnd ());
+
+                       ms = new MemoryStream ();
+                       xtw = new XmlTextWriter (ms, new UTF8Encoding ());
+                       xtw.WriteStartDocument ();
+                       xtw.Flush ();
+                       ms.Seek (0, SeekOrigin.Begin);
+                       sr = new StreamReader (ms);
+                       AssertEquals ("<?xml version=\"1.0\" encoding=\"utf-8\"?>", sr.ReadToEnd ());
+
+                       ms = new MemoryStream ();
+                       xtw = new XmlTextWriter (ms, null);
+                       xtw.WriteStartDocument ();
+                       xtw.Flush ();
+                       ms.Seek (0, SeekOrigin.Begin);
+                       sr = new StreamReader (ms);
+                       AssertEquals ("<?xml version=\"1.0\"?>", sr.ReadToEnd ());
+
+                       ms = new MemoryStream ();
+                       xtw = new XmlTextWriter (ms, null);
+                       xtw.WriteStartDocument (true);
+                       xtw.Flush ();
+                       ms.Seek (0, SeekOrigin.Begin);
+                       sr = new StreamReader (ms);
+                       AssertEquals ("<?xml version=\"1.0\" standalone=\"yes\"?>", sr.ReadToEnd ());
+               }
+
                public void TestDocumentStart ()
                {
                        xtw.WriteStartDocument ();
@@ -140,6 +188,16 @@ namespace Ximian.Mono.Tests
                                AssertEquals ("Exception message is incorrect.",
                                        "WriteStartDocument should be the first call.", e.Message);
                        }
+
+                       xtw = new XmlTextWriter (sw = new StringWriter ());
+                       xtw.WriteStartDocument (true);
+                       AssertEquals ("<?xml version=\"1.0\" encoding=\"utf-16\" standalone=\"yes\"?>",
+                               sw.GetStringBuilder ().ToString ());
+
+                       xtw = new XmlTextWriter (sw = new StringWriter ());
+                       xtw.WriteStartDocument (false);
+                       AssertEquals ("<?xml version=\"1.0\" encoding=\"utf-16\" standalone=\"no\"?>",
+                               sw.GetStringBuilder ().ToString ());
                }
 
                public void TestElementEmpty ()
@@ -155,6 +213,46 @@ namespace Ximian.Mono.Tests
                        AssertEquals ("WriteElementString has incorrect output.", "<foo>bar</foo>", sw.GetStringBuilder().ToString());
                }
 
+               public void TestFormatting ()
+               {
+                       xtw.Formatting = Formatting.Indented;
+                       xtw.WriteStartDocument ();
+                       xtw.WriteStartElement ("foo");
+                       xtw.WriteElementString ("bar", "");
+                       xtw.Close ();
+                       AssertEquals ("<?xml version=\"1.0\" encoding=\"utf-16\"?>\r\n<foo>\r\n  <bar />\r\n</foo>",
+                               sw.GetStringBuilder ().ToString ());
+               }
+
+               public void TestFormattingInvalidXmlForFun ()
+               {
+                       xtw.Formatting = Formatting.Indented;
+                       xtw.IndentChar = 'x';
+                       xtw.WriteStartDocument ();
+                       xtw.WriteStartElement ("foo");
+                       xtw.WriteStartElement ("bar");
+                       xtw.WriteElementString ("baz", "");
+                       xtw.Close ();
+                       AssertEquals ("<?xml version=\"1.0\" encoding=\"utf-16\"?>\r\n<foo>\r\nxx<bar>\r\nxxxx<baz />\r\nxx</bar>\r\n</foo>",
+                               sw.GetStringBuilder ().ToString ());
+               }
+
+               public void TestFormattingFromRemarks ()
+               {
+                       // Remarks section of on-line help for XmlTextWriter.Formatting suggests this test.
+                       xtw.Formatting = Formatting.Indented; 
+                       xtw.WriteStartElement ("ol"); 
+                       xtw.WriteStartElement ("li"); 
+                       xtw.WriteString ("The big "); // This means "li" now has a mixed content model. 
+                       xtw.WriteElementString ("b", "E"); 
+                       xtw.WriteElementString ("i", "lephant"); 
+                       xtw.WriteString (" walks slowly."); 
+                       xtw.WriteEndElement (); 
+                       xtw.WriteEndElement ();
+                       AssertEquals ("<ol>\r\n  <li>The big <b>E</b><i>lephant</i> walks slowly.</li>\r\n</ol>",
+                               sw.GetStringBuilder ().ToString ());
+               }
+
                public void TestProcessingInstructionValid ()
                {
                        xtw.WriteProcessingInstruction("foo", "bar");
@@ -220,6 +318,14 @@ namespace Ximian.Mono.Tests
                        }
                }
 
+               public void TestQuoteCharInvalid ()
+               {
+                       try {
+                               xtw.QuoteChar = 'x';
+                               Fail ("Should have thrown an ArgumentException.");
+                       } catch (ArgumentException) {}
+               }
+
                public void TestWriteEndElement ()
                {
                        try