2008-05-12 Atsushi Enomoto <atsushi@ximian.com>
authorAtsushi Eno <atsushieno@gmail.com>
Mon, 12 May 2008 10:16:06 +0000 (10:16 -0000)
committerAtsushi Eno <atsushieno@gmail.com>
Mon, 12 May 2008 10:16:06 +0000 (10:16 -0000)
* XContainer.cs, XElement.cs, XNode.cs, XUtil.cs :
  made several refactoring on handling "content" items in couple of
  Add*() methods. Attributes should be allowed in XElement.Add(),
  while they should be rejected in XNode.Add*Self().
  Similarly, Add() and SetValue() should reject any invalid content
  items.
  Add() should also append string content to the last node when the
  last node is text.

* XDocumentTest.cs, XElementTest.cs :
  Added couple of tests for Add() and AddBeforeSelf().

svn path=/trunk/mcs/; revision=102990

mcs/class/System.Xml.Linq/System.Xml.Linq/ChangeLog
mcs/class/System.Xml.Linq/System.Xml.Linq/XContainer.cs
mcs/class/System.Xml.Linq/System.Xml.Linq/XElement.cs
mcs/class/System.Xml.Linq/System.Xml.Linq/XNode.cs
mcs/class/System.Xml.Linq/System.Xml.Linq/XUtil.cs
mcs/class/System.Xml.Linq/Test/System.Xml.Linq/ChangeLog
mcs/class/System.Xml.Linq/Test/System.Xml.Linq/XDocumentTest.cs
mcs/class/System.Xml.Linq/Test/System.Xml.Linq/XElementTest.cs

index 9bee1e7d86a4a5ea8281828142a1b3eb67de8d70..a4246b656b71ba11674a122bada18ccfcbd073a9 100644 (file)
@@ -1,3 +1,14 @@
+2008-05-12  Atsushi Enomoto  <atsushi@ximian.com>
+
+       * XContainer.cs, XElement.cs, XNode.cs, XUtil.cs :
+         made several refactoring on handling "content" items in couple of
+         Add*() methods. Attributes should be allowed in XElement.Add(),
+         while they should be rejected in XNode.Add*Self().
+         Similarly, Add() and SetValue() should reject any invalid content
+         items.
+         Add() should also append string content to the last node when the
+         last node is text.
+
 2008-05-12  Atsushi Enomoto  <atsushi@ximian.com>
 
        * XUtil.cs : added ExpandArray() and marked some members as wrong.
index 6e6586f4761ce48e42953a6f7c8874b3019d9d54..ff55569abf7da41fa1874f219c0ed68df03ea082 100644 (file)
@@ -80,8 +80,10 @@ namespace System.Xml.Linq
                        if (content == null)
                                return;
 
-                       foreach (XNode n in XUtil.ToNodes (content))
-                               AddNode (n);
+                       foreach (object o in XUtil.ExpandArray (content))
+                               if (!OnAddingObject (o))
+                                       foreach (XNode n in XUtil.ToNodes (o))
+                                               AddNode (n);
                }
 
                void AddNode (XNode n)
@@ -100,7 +102,9 @@ namespace System.Xml.Linq
 
                public void Add (params object [] content)
                {
-                       foreach (object o in XUtil.ShrinkArray (content))
+                       if (content == null)
+                               return;
+                       foreach (object o in XUtil.ExpandArray (content))
                                Add (o);
                }
 
@@ -109,7 +113,7 @@ namespace System.Xml.Linq
                        if (first == null)
                                Add (content);
                        else
-                               first.AddBeforeSelf (content);
+                               AddFirst (XUtil.ExpandArray (content));
                }
 
                public void AddFirst (params object [] content)
@@ -119,7 +123,14 @@ namespace System.Xml.Linq
                        if (first == null)
                                Add (content);
                        else
-                               first.AddBeforeSelf (content);
+                               foreach (object o in XUtil.ExpandArray (content))
+                                       if (!OnAddingObject (o))
+                                               first.AddBeforeSelf (o);
+               }
+
+               internal virtual bool OnAddingObject (object o)
+               {
+                       return false;
                }
 
                public XmlWriter CreateWriter ()
@@ -228,9 +239,5 @@ namespace System.Xml.Linq
                        }
                }
                */
-
-               internal virtual void OnAdded (XNode item, bool addFirst)
-               {
-               }
        }
 }
index 4726b650d671e87377192206e49950a744efc6e9..afdb5bd286cb873c3bb08b3926c107838388e869 100644 (file)
@@ -525,22 +525,26 @@ namespace System.Xml.Linq
                                        a.Remove ();
                        } else {
                                if (a == null) {
-                                       a = new XAttribute (name, value);
-                                       a.SetOwner (this);
-                                       if (attr_first == null) {
-                                               attr_first = a;
-                                               attr_last = a;
-                                       } else {
-                                               attr_last.NextAttribute = a;
-                                               a.PreviousAttribute = attr_last;
-                                               attr_last = a;
-                                       }
+                                       SetAttributeObject (new XAttribute (name, value));
                                }
                                else
                                        a.Value = XUtil.ToString (value);
                        }
                }
 
+               void SetAttributeObject (XAttribute a)
+               {
+                       a.SetOwner (this);
+                       if (attr_first == null) {
+                               attr_first = a;
+                               attr_last = a;
+                       } else {
+                               attr_last.NextAttribute = a;
+                               a.PreviousAttribute = attr_last;
+                               attr_last = a;
+                       }
+               }
+
                public override void WriteTo (XmlWriter w)
                {
                        w.WriteStartElement (name.LocalName, name.Namespace.NamespaceName);
@@ -632,14 +636,36 @@ namespace System.Xml.Linq
 
                public void SetValue (object value)
                {
+                       if (value == null)
+                               throw new ArgumentNullException ("value");
+                       if (value is XAttribute || value is XDocument || value is XDeclaration || value is XDocumentType)
+                               throw new ArgumentException (String.Format ("Node type {0} is not allowed as element value", value.GetType ()));
                        RemoveNodes ();
                        foreach (XNode n in XUtil.ToNodes (value))
                                Add (n);
                }
 
+               internal override bool OnAddingObject (object o)
+               {
+                       XAttribute a = o as XAttribute;
+                       if (a != null) {
+                               foreach (XAttribute ia in Attributes ())
+                                       if (a.Name == ia.Name)
+                                               throw new InvalidOperationException (String.Format ("Duplicate attribute: {0}", a.Name));
+                               SetAttributeObject (a);
+                               return true;
+                       }
+                       else if (o is string && LastNode is XText) {
+                               ((XText) LastNode).Value += o as string;
+                               return true;
+                       }
+                       else
+                               return false;
+               }
+
                internal override void OnAdded (XNode node, bool addFirst)
                {
-                       if (node is XDocument || node is XDocumentType)
+                       if (node is XDocument || node is XDocumentType || node is XDeclaration)
                                throw new ArgumentException (String.Format ("A node of type {0} cannot be added as a content", node.GetType ()));
                }
 
index 5191bb1c5b7706b94385044d4db78c13f1fce4ac..cd58225030370abf1d5eea61f863874e99338c5f 100644 (file)
@@ -94,6 +94,7 @@ namespace System.Xml.Linq
                        if (Parent == null)
                                throw new InvalidOperationException ();
                        foreach (XNode n in XUtil.ToNodes (content)) {
+                               OnAdded (n, false);
                                n.SetOwner (Parent);
                                n.previous = this;
                                n.next = next;
@@ -121,6 +122,7 @@ namespace System.Xml.Linq
                        if (Parent == null)
                                throw new InvalidOperationException ();
                        foreach (XNode n in XUtil.ToNodes (content)) {
+                               OnAdded (n, true);
                                n.SetOwner (Parent);
                                n.previous = previous;
                                n.next = this;
@@ -291,5 +293,9 @@ namespace System.Xml.Linq
                        AddAfterSelf (items);
                        Remove ();
                }
+
+               internal virtual void OnAdded (XNode item, bool addFirst)
+               {
+               }
        }
 }
index b48efc4e54c775f38e2ed374d26aeea997e26cf8..f9cfbc1865c2dd5afedfe96184fc95e1fec10d23 100644 (file)
@@ -78,6 +78,8 @@ namespace System.Xml.Linq
                // FIXME: it will be removed. It makes attribute processing incorrect.
                public static IEnumerable<XNode> ToNodes (object o)
                {
+                       if (o is XAttribute)
+                               throw new ArgumentException ("Attribute node is not allowed as argument");
                        XNode n = o as XNode;
                        if (n != null)
                                yield return n;
index 5d9f0464bcf6206f0bd2c2c51e7d16fec2062b33..213c4cbc22570f1a4f9e887b36e66ab2dbf8c97e 100644 (file)
@@ -1,3 +1,8 @@
+2008-05-12  Atsushi Enomoto  <atsushi@ximian.com>
+
+       * XDocumentTest.cs, XElementTest.cs :
+         Added couple of tests for Add() and AddBeforeSelf().
+
 2008-05-12  Atsushi Enomoto  <atsushi@ximian.com>
 
        * XStreamingElementTest.cs : new test.
index fe3a400ca439efd8f041e50566bb10ccdc010c17..2e6ec5e5c890b2503b129b3ef8a6cba98923fc95 100644 (file)
@@ -93,5 +93,13 @@ namespace MonoTests.System.Xml.Linq
                        // hence converted to a string -> error
                        doc.Add (new XDeclaration ("1.0", null, null));
                }
+
+               [Test]
+               [ExpectedException (typeof (ArgumentException))]
+               public void AddXAttributeToDocument ()
+               {
+                       var doc = new XDocument ();
+                       doc.Add (new XAttribute ("foo", " "));
+               }
        }
 }
index 83f8fddf50eab4e2fc2ff3cac3afd6cce011434f..00ad22d9d384ca022b65ffb1e6a7e94773ad3776 100644 (file)
@@ -206,6 +206,36 @@ namespace MonoTests.System.Xml.Linq
                        Assert.AreEqual ("bar", bar.Name.LocalName, "#6");
                }
 
+               [Test]
+               [ExpectedException (typeof (ArgumentException))]
+               public void AddAfterSelfAttribute ()
+               {
+                       var el = new XElement ("root", new XElement ("child"));
+                       var el2 = el.FirstNode as XElement;
+                       el2.AddAfterSelf (new XAttribute ("foo", "bar"));
+               }
+
+               [Test]
+               [ExpectedException (typeof (ArgumentException))]
+               public void AddAfterSelfXDocument ()
+               {
+                       var el = new XElement ("root", new XElement ("child"));
+                       var el2 = el.FirstNode as XElement;
+                       el2.AddAfterSelf (new XDocument ());
+               }
+
+               [Test]
+               [ExpectedException (typeof (ArgumentException))]
+               [Category ("NotDotNet")]
+               [Category ("NotWorking")]
+               // LAMESPEC: there is no reason to not reject XDeclaration while it rejects XDocument.
+               public void AddAfterSelfXDeclaration ()
+               {
+                       var el = new XElement ("root", new XElement ("child"));
+                       var el2 = el.FirstNode as XElement;
+                       el2.AddAfterSelf (new XDeclaration ("1.0", null, null));
+               }
+
                [Test]
                public void AddBeforeSelf ()
                {
@@ -250,6 +280,29 @@ namespace MonoTests.System.Xml.Linq
                        Assert.AreEqual ("foo", foo.Name.LocalName, "#4");
                }
 
+               [Test]
+               public void AddJoinsStringAfterText ()
+               {
+                       var el = XElement.Parse ("<foo>text1</foo>");
+                       el.Add ("text2");
+                       el.Add (new XText ("text3"));
+                       IEnumerator<XNode> e = el.Nodes ().GetEnumerator ();
+                       Assert.IsTrue (e.MoveNext (), "#1");
+                       Assert.AreEqual ("text1text2", e.Current.ToString (), "#2");
+                       Assert.IsTrue (e.MoveNext (), "#3");
+                       Assert.AreEqual ("text3", e.Current.ToString (), "#4");
+                       Assert.IsFalse (e.MoveNext (), "#5");
+               }
+
+               [Test]
+               [ExpectedException (typeof (InvalidOperationException))]
+               public void AddDuplicateAttribute ()
+               {
+                       var el = new XElement ("foo",
+                               new XAttribute ("bar", "baz"));
+                       el.Add (new XAttribute ("bar", "baz"));
+               }
+
                [Test]
                public void ReplaceWith ()
                {
@@ -369,5 +422,37 @@ namespace MonoTests.System.Xml.Linq
                                new XElement ("bar"));
                        Assert.AreEqual ("Linux&Windows", a.Value);
                }
+
+               [Test]
+               [ExpectedException (typeof (ArgumentException))]
+               public void SetValueXAttribute ()
+               {
+                       new XElement ("foo").SetValue (new XAttribute ("foo", "bar"));
+               }
+
+               [Test]
+               [ExpectedException (typeof (ArgumentException))]
+               public void SetValueXDocumnent ()
+               {
+                       new XElement ("foo").SetValue (new XDocument ());
+               }
+
+               [Test]
+               // LAMESPEC: there is no reason to not reject XDeclaration while it rejects XDocument.
+               [ExpectedException (typeof (ArgumentException))]
+               [Category ("NotDotNet")]
+               public void SetValueXDeclaration ()
+               {
+                       var el = new XElement ("foo");
+                       el.SetValue (new XDeclaration ("1.0", null, null));
+                       Assert.AreEqual ("<?xml version=\"1.0\"?>", el.Value);
+               }
+
+               [Test]
+               [ExpectedException (typeof (ArgumentNullException))]
+               public void SetValueNull ()
+               {
+                       new XElement ("foo", "text").SetValue (null);
+               }
        }
 }