2 // System.Xml.XmlNodeTests
5 // Kral Ferch <kral_ferch@hotmail.com>
6 // Martin Willemoes Hansen
9 // (C) 2003 Martin Willemoes Hansen
17 using NUnit.Framework;
19 namespace MonoTests.System.Xml
22 public class XmlNodeTests : Assertion
35 public void GetReady ()
37 document = new XmlDocument ();
38 document.NodeInserted += new XmlNodeChangedEventHandler (this.EventNodeInserted);
39 document.NodeInserting += new XmlNodeChangedEventHandler (this.EventNodeInserting);
40 document.NodeRemoved += new XmlNodeChangedEventHandler (this.EventNodeRemoved);
41 document.NodeRemoving += new XmlNodeChangedEventHandler (this.EventNodeRemoving);
42 element = document.CreateElement ("foo");
43 element2 = document.CreateElement ("bar");
46 private void EventNodeInserted(Object sender, XmlNodeChangedEventArgs e)
51 private void EventNodeInserting (Object sender, XmlNodeChangedEventArgs e)
56 private void EventNodeChanged(Object sender, XmlNodeChangedEventArgs e)
61 private void EventNodeChanging (Object sender, XmlNodeChangedEventArgs e)
66 private void EventNodeRemoved(Object sender, XmlNodeChangedEventArgs e)
71 private void EventNodeRemoving (Object sender, XmlNodeChangedEventArgs e)
77 public void AppendChild ()
83 element.AppendChild (element2);
87 // Can only append to elements, documents, and attributes
90 comment = document.CreateComment ("baz");
91 comment.AppendChild (element2);
92 Fail ("Expected an InvalidOperationException to be thrown.");
94 catch (InvalidOperationException) {}
96 // Can't append a node from one document into another document.
97 XmlDocument document2 = new XmlDocument();
98 AssertEquals (1, element.ChildNodes.Count);
101 element2 = document2.CreateElement ("qux");
102 element.AppendChild (element2);
103 Fail ("Expected an ArgumentException to be thrown.");
105 catch (ArgumentException) {}
106 AssertEquals (1, element.ChildNodes.Count);
108 // Can't append to a readonly node.
109 /* TODO put this in when I figure out how to create a read-only node.
112 XmlElement element3 = (XmlElement)element.CloneNode (false);
113 Assert (!element.IsReadOnly);
114 Assert (element3.IsReadOnly);
115 element2 = document.CreateElement ("quux");
116 element3.AppendChild (element2);
117 Fail ("Expected an ArgumentException to be thrown.");
119 catch (ArgumentException) {}
124 public void GetNamespaceOfPrefix ()
126 document.LoadXml ("<root xmlns='urn:default' attr='value' "
127 + "xml:lang='en' xmlns:foo='urn:foo' foo:att='fooatt'>text node</root>");
128 XmlNode n = document.DocumentElement;
129 AssertEquals ("#1", "urn:default", n.GetNamespaceOfPrefix (String.Empty));
130 AssertEquals ("#2", "urn:foo", n.GetNamespaceOfPrefix ("foo"));
131 AssertEquals ("#3", String.Empty, n.GetNamespaceOfPrefix ("bar"));
133 AssertEquals ("#4", "http://www.w3.org/XML/1998/namespace", n.GetNamespaceOfPrefix ("xml"));
134 AssertEquals ("#5", "http://www.w3.org/2000/xmlns/", n.GetNamespaceOfPrefix ("xmlns"));
136 AssertEquals ("#4", String.Empty, n.GetNamespaceOfPrefix ("xml"));
137 AssertEquals ("#5", String.Empty, n.GetNamespaceOfPrefix ("xmlns"));
140 n = document.DocumentElement.FirstChild;
141 AssertEquals ("#6", "urn:default", n.GetNamespaceOfPrefix (String.Empty));
142 AssertEquals ("#7", "urn:foo", n.GetNamespaceOfPrefix ("foo"));
143 AssertEquals ("#8", String.Empty, n.GetNamespaceOfPrefix ("bar"));
145 AssertEquals ("#9", "http://www.w3.org/XML/1998/namespace", n.GetNamespaceOfPrefix ("xml"));
146 AssertEquals ("#10", "http://www.w3.org/2000/xmlns/", n.GetNamespaceOfPrefix ("xmlns"));
148 AssertEquals ("#9", String.Empty, n.GetNamespaceOfPrefix ("xml"));
149 AssertEquals ("#10", String.Empty, n.GetNamespaceOfPrefix ("xmlns"));
154 [ExpectedException (typeof (ArgumentNullException))]
155 public void GetNamespaceOfPrefixNullArg ()
157 new XmlDocument ().GetNamespaceOfPrefix (null);
161 public void InsertBefore()
163 document = new XmlDocument();
164 document.LoadXml("<root><sub /></root>");
165 XmlElement docelem = document.DocumentElement;
166 docelem.InsertBefore(document.CreateElement("good_child"), docelem.FirstChild);
167 AssertEquals("InsertBefore.Normal", "good_child", docelem.FirstChild.Name);
168 // These are required for .NET 1.0 but not for .NET 1.1.
170 document.InsertBefore (document.CreateElement ("BAD_MAN"), docelem);
171 Fail ("#InsertBefore.BadPositionButNoError.1");
177 public void InsertAfter()
179 document = new XmlDocument();
180 document.LoadXml("<root><sub1 /><sub2 /></root>");
181 XmlElement docelem = document.DocumentElement;
182 XmlElement newelem = document.CreateElement("good_child");
183 docelem.InsertAfter(newelem, docelem.FirstChild);
184 AssertEquals("InsertAfter.Normal", 3, docelem.ChildNodes.Count);
185 AssertEquals("InsertAfter.First", "sub1", docelem.FirstChild.Name);
186 AssertEquals("InsertAfter.Last", "sub2", docelem.LastChild.Name);
187 AssertEquals("InsertAfter.Prev", "good_child", docelem.FirstChild.NextSibling.Name);
188 AssertEquals("InsertAfter.Next", "good_child", docelem.LastChild.PreviousSibling.Name);
189 // this doesn't throw any exception *only on .NET 1.1*
190 // .NET 1.0 throws an exception.
192 document.InsertAfter(document.CreateElement("BAD_MAN"), docelem);
194 AssertEquals("InsertAfter with bad location",
195 "<root><sub1 /><good_child /><sub2 /></root><BAD_MAN />",
197 } catch (XmlException ex) {
201 } catch (Exception) {}
206 public void Normalize ()
208 XmlDocument doc = new XmlDocument ();
209 doc.LoadXml ("<root>This is the <b>hardest</b> one.</root>");
210 doc.NodeInserted += new XmlNodeChangedEventHandler (EventNodeInserted);
211 doc.NodeChanged += new XmlNodeChangedEventHandler (EventNodeChanged);
212 doc.NodeRemoved += new XmlNodeChangedEventHandler (EventNodeRemoved);
214 AssertEquals (3, doc.DocumentElement.ChildNodes.Count);
216 doc.DocumentElement.Normalize ();
217 AssertEquals (3, doc.DocumentElement.ChildNodes.Count);
219 inserted = changed = removed = false;
221 doc.DocumentElement.AppendChild (doc.CreateTextNode ("Addendum."));
222 AssertEquals (4, doc.DocumentElement.ChildNodes.Count);
223 inserted = changed = removed = false;
225 doc.DocumentElement.Normalize ();
226 AssertEquals (3, doc.DocumentElement.ChildNodes.Count);
229 inserted = changed = removed = false;
231 doc.DocumentElement.SetAttribute ("attr", "");
232 XmlAttribute attr = doc.DocumentElement.Attributes [0] as XmlAttribute;
233 AssertEquals (1, attr.ChildNodes.Count);
234 inserted = changed = removed = false;
236 // Such behavior violates DOM Level 2 Node#normalize(),
237 // but MS DOM is designed as such.
238 AssertEquals (1, attr.ChildNodes.Count);
242 public void Normalize2 ()
244 XmlDocument doc = new XmlDocument ();
245 doc.PreserveWhitespace = true;
246 doc.LoadXml ("<root> </root>");
247 XmlElement root = doc.DocumentElement;
248 root.AppendChild (doc.CreateTextNode ("foo"));
249 root.AppendChild (doc.CreateTextNode ("bar"));
250 root.AppendChild (doc.CreateWhitespace (" "));
251 root.AppendChild (doc.CreateTextNode ("baz"));
252 doc.NodeInserted += new XmlNodeChangedEventHandler (OnChange);
253 doc.NodeChanged += new XmlNodeChangedEventHandler (OnChange);
254 doc.NodeRemoved += new XmlNodeChangedEventHandler (OnChange);
255 AssertEquals ("Before Normalize()", 5, root.ChildNodes.Count);
257 AssertEquals ("<root> foobar baz</root>", root.OuterXml);
258 AssertEquals ("After Normalize()", 1, root.ChildNodes.Count);
263 private void OnChange (object o, XmlNodeChangedEventArgs e)
265 switch (normalize2Count) {
267 AssertEquals ("Action0", XmlNodeChangedAction.Remove, e.Action);
268 AssertEquals ("Value0", " ", e.Node.Value);
271 AssertEquals ("Action1", XmlNodeChangedAction.Remove, e.Action);
272 AssertEquals ("Value1", "bar", e.Node.Value);
275 AssertEquals ("Action2", XmlNodeChangedAction.Remove, e.Action);
276 AssertEquals ("Value2", " ", e.Node.Value);
279 AssertEquals ("Action3", XmlNodeChangedAction.Remove, e.Action);
280 AssertEquals ("Value3", "baz", e.Node.Value);
283 AssertEquals ("Action4", XmlNodeChangedAction.Change, e.Action);
284 AssertEquals ("Value4", " foobar baz", e.Node.Value);
287 Fail (String.Format ("Unexpected event. Action = {0}, node type = {1}, node name = {2}, node value = {3}", e.Action, e.Node.NodeType, e.Node.Name, e.Node.Value));
294 public void PrependChild()
296 document = new XmlDocument();
297 document.LoadXml("<root><sub1 /><sub2 /></root>");
298 XmlElement docelem = document.DocumentElement;
299 docelem.PrependChild(document.CreateElement("prepender"));
300 AssertEquals("PrependChild", "prepender", docelem.FirstChild.Name);
303 public void saveTestRemoveAll ()
305 // TODO: put this test back in when AttributeCollection.RemoveAll() is implemented.
306 element.AppendChild(element2);
309 element.RemoveAll ();
315 public void RemoveChild ()
317 element.AppendChild(element2);
320 element.RemoveChild (element2);
326 public void RemoveLastChild ()
328 element.InnerXml = "<foo/><bar/><baz/>";
329 element.RemoveChild (element.LastChild);
330 AssertNotNull (element.FirstChild);
334 public void GetPrefixOfNamespace ()
336 document.LoadXml ("<root><c1 xmlns='urn:foo'><c2 xmlns:foo='urn:foo' xmlns='urn:bar'><c3 xmlns=''/></c2></c1></root>");
337 AssertEquals ("root", String.Empty, document.DocumentElement.GetPrefixOfNamespace ("urn:foo"));
338 AssertEquals ("c1", String.Empty, document.DocumentElement.GetPrefixOfNamespace ("urn:foo"));
339 AssertEquals ("c2", String.Empty, document.DocumentElement.FirstChild.GetPrefixOfNamespace ("urn:foo"));
340 AssertEquals ("c3", "foo", document.DocumentElement.FirstChild.FirstChild.GetPrefixOfNamespace ("urn:foo"));
342 // disconnected nodes.
343 XmlNode n = document.CreateElement ("foo");
344 AssertEquals (String.Empty, n.GetPrefixOfNamespace ("foo"));
345 n = document.CreateTextNode ("text"); // does not have Attributes
346 AssertEquals (String.Empty, n.GetPrefixOfNamespace ("foo"));
347 n = document.CreateXmlDeclaration ("1.0", null, null); // does not have Attributes
348 AssertEquals (String.Empty, n.GetPrefixOfNamespace ("foo"));
352 public void GetPrefixOfNamespace2 ()
354 XmlDocument doc = new XmlDocument ();
355 doc.AppendChild (doc.CreateElement ("foo"));
356 doc.DocumentElement.SetAttributeNode (
357 doc.CreateAttribute ("xmlns", "u", "http://www.w3.org/2000/xmlns/"));
358 doc.DocumentElement.Attributes [0].Value = "urn:foo";
359 XmlElement el = doc.CreateElement ("bar");
360 doc.DocumentElement.AppendChild (el);
361 AssertEquals ("u", el.GetPrefixOfNamespace ("urn:foo"));
365 public void ReplaceChild ()
367 document.LoadXml ("<root/>");
368 document.NodeInserted += new XmlNodeChangedEventHandler (this.EventNodeInserted);
369 document.NodeChanged += new XmlNodeChangedEventHandler (this.EventNodeChanged);
370 document.NodeRemoved += new XmlNodeChangedEventHandler (this.EventNodeRemoved);
371 inserted = changed = removed = false;
372 XmlElement el = document.CreateElement("root2");
373 document.ReplaceChild (el, document.DocumentElement);
374 AssertEquals ("root2", document.DocumentElement.Name);
375 AssertEquals (1, document.ChildNodes.Count);
376 Assert (inserted && removed && !changed);
380 public void InnerText ()
382 document.LoadXml ("<root>This is <b>mixed</b> content. Also includes <![CDATA[CDATA section]]>.<!-- Should be ignored --></root>");
383 string total = "This is mixed content. Also includes CDATA section.";
384 XmlNode elemB = document.DocumentElement.ChildNodes [1];
385 AssertEquals ("mixed", elemB.FirstChild.InnerText); // text node
386 AssertEquals ("mixed", elemB.InnerText); // element b
387 AssertEquals (total, document.DocumentElement.InnerText); // element root
388 AssertEquals (total, document.InnerText); // whole document
392 public void InnerXmlWithXmlns ()
394 XmlDocument document = new XmlDocument ();
395 XmlElement xel = document.CreateElement ("KeyValue", "http://www.w3.org/2000/09/xmldsig#");
396 xel.SetAttribute ("xmlns", "http://www.w3.org/2000/09/xmldsig#");
397 xel.InnerXml = "<DSAKeyValue>blablabla</DSAKeyValue>";
398 string expected = "<KeyValue xmlns=\"http://www.w3.org/2000/09/xmldsig#\"><DSAKeyValue>blablabla</DSAKeyValue></KeyValue>";
399 AssertEquals (expected, xel.OuterXml);
403 public void SelectNodes ()
405 // This test is done in this class since it tests only XmlDocumentNavigator.
406 string xpath = "//@*|//namespace::*";
407 XmlDocument doc = new XmlDocument ();
408 doc.LoadXml ("<element xmlns='urn:foo'><foo><bar>test</bar></foo></element>");
409 XmlNodeList nl = doc.SelectNodes (xpath);
410 AssertEquals (6, nl.Count);
411 // BTW, as for namespace nodes, Node does not exist
412 // in the tree, so the return value should be
413 // implementation dependent.
414 AssertEquals ("#1", XmlNodeType.Attribute, nl [0].NodeType);
415 AssertEquals ("#2", XmlNodeType.Attribute, nl [1].NodeType);
416 AssertEquals ("#3", XmlNodeType.Attribute, nl [2].NodeType);
417 AssertEquals ("#4", XmlNodeType.Attribute, nl [3].NodeType);
418 AssertEquals ("#5", XmlNodeType.Attribute, nl [4].NodeType);
419 AssertEquals ("#6", XmlNodeType.Attribute, nl [5].NodeType);
420 AssertEquals ("xmlns", nl [0].LocalName);
421 AssertEquals ("xml", nl [1].LocalName);
422 AssertEquals ("xmlns", nl [2].LocalName);
423 AssertEquals ("xml", nl [3].LocalName);
424 AssertEquals ("xmlns", nl [4].LocalName);
425 AssertEquals ("xml", nl [5].LocalName);
429 [Ignore ("MS.NET has a bug; it does not return nodes in document order.")]
430 public void SelectNodes2 ()
432 // This test is done in this class since it tests only XmlDocumentNavigator.
433 string xpath = "//*|//@*|//namespace::*";
434 XmlDocument doc = new XmlDocument ();
435 doc.LoadXml ("<element xmlns='urn:foo'><foo><bar>test</bar></foo></element>");
436 XmlNodeList nl = doc.SelectNodes (xpath);
437 AssertEquals (9, nl.Count);
438 AssertEquals (XmlNodeType.Element, nl [0].NodeType);
439 AssertEquals (XmlNodeType.Attribute, nl [1].NodeType);
440 AssertEquals (XmlNodeType.Attribute, nl [2].NodeType);
441 AssertEquals (XmlNodeType.Element, nl [3].NodeType);
442 AssertEquals (XmlNodeType.Attribute, nl [4].NodeType);
443 AssertEquals (XmlNodeType.Attribute, nl [5].NodeType);
444 AssertEquals (XmlNodeType.Element, nl [6].NodeType);
445 AssertEquals (XmlNodeType.Attribute, nl [7].NodeType);
446 AssertEquals (XmlNodeType.Attribute, nl [8].NodeType);
447 AssertEquals ("element", nl [0].LocalName);
448 AssertEquals ("xmlns", nl [1].LocalName);
449 AssertEquals ("xml", nl [2].LocalName);
450 AssertEquals ("foo", nl [3].LocalName);
451 AssertEquals ("xmlns", nl [4].LocalName);
452 AssertEquals ("xml", nl [5].LocalName);
453 AssertEquals ("bar", nl [6].LocalName);
454 AssertEquals ("xmlns", nl [7].LocalName);
455 AssertEquals ("xml", nl [8].LocalName);
459 public void BaseURI ()
462 XmlDocument doc = new XmlDocument ();
463 doc.Load ("Test/XmlFiles/simple.xml");
464 XmlElement el = doc.CreateElement ("foo");
465 AssertEquals (String.Empty, el.BaseURI);
466 doc.DocumentElement.AppendChild (el);
467 Assert (String.Empty != el.BaseURI);
468 XmlAttribute attr = doc.CreateAttribute ("attr");
469 AssertEquals (String.Empty, attr.BaseURI);
473 public void CloneReadonlyNode ()
475 // Clone() should return such node that is not readonly
476 string dtd = "<!DOCTYPE root ["
477 + "<!ELEMENT root (#PCDATA|foo)*>"
478 + "<!ELEMENT foo EMPTY>"
479 + "<!ENTITY ent1 '<foo /><![CDATA[cdata]]>'>]>";
480 string xml = dtd + "<root>&ent1;</root>";
482 XmlDocument doc = new XmlDocument ();
484 XmlNode n = doc.DocumentElement.FirstChild.FirstChild;
485 Assert ("#1", n.IsReadOnly);
486 Assert ("#2", !n.CloneNode (true).IsReadOnly);
490 public void InnerTextComment ()
492 XmlDocument doc = new XmlDocument ();
493 doc.LoadXml ("<a><!--xx--></a>");
494 AssertEquals (String.Empty, doc.InnerText);
497 [Test] // part of bug #80331
498 public void AppendReferenceChildAsNewChild ()
500 XmlDocument d = new XmlDocument ();
501 XmlElement r = d.CreateElement ("Docs");
504 XmlElement s = Create (d, "param", "pattern");
505 s.AppendChild (Create (d, "para", "insert text here"));
509 r.AppendChild (Create (d, "param", "pattern"));
510 r.AppendChild (Create (d, "param", "pattern"));
512 r.InsertBefore (s, r.FirstChild);
515 XmlElement Create (XmlDocument d, string name, string param)
517 XmlElement e = d.CreateElement (name);
518 e.SetAttribute ("name", param);
523 public void PrependChild2 ()
525 XmlDocument d = new XmlDocument ();
526 XmlElement r = d.CreateElement ("Docs");
529 XmlElement s = Create (d, "param", "pattern");
530 s.AppendChild (Create (d, "para", "insert text here"));
534 r.AppendChild (Create (d, "param", "pattern"));
535 r.AppendChild (Create (d, "param", "pattern"));