+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.
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)
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);
}
if (first == null)
Add (content);
else
- first.AddBeforeSelf (content);
+ AddFirst (XUtil.ExpandArray (content));
}
public void AddFirst (params object [] content)
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 ()
}
}
*/
-
- internal virtual void OnAdded (XNode item, bool addFirst)
- {
- }
}
}
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);
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 ()));
}
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;
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;
AddAfterSelf (items);
Remove ();
}
+
+ internal virtual void OnAdded (XNode item, bool addFirst)
+ {
+ }
}
}
// 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;
+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.
// 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", " "));
+ }
}
}
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 ()
{
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 ()
{
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);
+ }
}
}