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
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);
84 Assert.IsTrue (inserted);
85 Assert.IsTrue (inserting);
87 // Can only append to elements, documents, and attributes
90 comment = document.CreateComment ("baz");
91 comment.AppendChild (element2);
92 Assert.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 Assert.AreEqual (1, element.ChildNodes.Count);
101 element2 = document2.CreateElement ("qux");
102 element.AppendChild (element2);
103 Assert.Fail ("Expected an ArgumentException to be thrown.");
105 catch (ArgumentException) {}
106 Assert.AreEqual (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.IsTrue (!element.IsReadOnly);
114 Assert.IsTrue (element3.IsReadOnly);
115 element2 = document.CreateElement ("quux");
116 element3.AppendChild (element2);
117 Assert.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 Assert.AreEqual ("urn:default", n.GetNamespaceOfPrefix (String.Empty), "#1");
130 Assert.AreEqual ("urn:foo", n.GetNamespaceOfPrefix ("foo"), "#2");
131 Assert.AreEqual (String.Empty, n.GetNamespaceOfPrefix ("bar"), "#3");
132 Assert.AreEqual ("http://www.w3.org/XML/1998/namespace", n.GetNamespaceOfPrefix ("xml"), "#4");
133 Assert.AreEqual ("http://www.w3.org/2000/xmlns/", n.GetNamespaceOfPrefix ("xmlns"), "#5");
135 n = document.DocumentElement.FirstChild;
136 Assert.AreEqual ("urn:default", n.GetNamespaceOfPrefix (String.Empty), "#6");
137 Assert.AreEqual ("urn:foo", n.GetNamespaceOfPrefix ("foo"), "#7");
138 Assert.AreEqual (String.Empty, n.GetNamespaceOfPrefix ("bar"), "#8");
139 Assert.AreEqual ("http://www.w3.org/XML/1998/namespace", n.GetNamespaceOfPrefix ("xml"), "#9");
140 Assert.AreEqual ("http://www.w3.org/2000/xmlns/", n.GetNamespaceOfPrefix ("xmlns"), "#10");
144 [ExpectedException (typeof (ArgumentNullException))]
145 public void GetNamespaceOfPrefixNullArg ()
147 new XmlDocument ().GetNamespaceOfPrefix (null);
151 public void InsertBefore()
153 document = new XmlDocument();
154 document.LoadXml("<root><sub /></root>");
155 XmlElement docelem = document.DocumentElement;
156 docelem.InsertBefore(document.CreateElement("good_child"), docelem.FirstChild);
157 Assert.AreEqual ("good_child", docelem.FirstChild.Name, "InsertBefore.Normal");
158 // These are required for .NET 1.0 but not for .NET 1.1.
160 document.InsertBefore (document.CreateElement ("BAD_MAN"), docelem);
161 Assert.Fail ("#InsertBefore.BadPositionButNoError.1");
167 public void InsertAfter()
169 document = new XmlDocument();
170 document.LoadXml("<root><sub1 /><sub2 /></root>");
171 XmlElement docelem = document.DocumentElement;
172 XmlElement newelem = document.CreateElement("good_child");
173 docelem.InsertAfter(newelem, docelem.FirstChild);
174 Assert.AreEqual (3, docelem.ChildNodes.Count, "InsertAfter.Normal");
175 Assert.AreEqual ("sub1", docelem.FirstChild.Name, "InsertAfter.First");
176 Assert.AreEqual ("sub2", docelem.LastChild.Name, "InsertAfter.Last");
177 Assert.AreEqual ("good_child", docelem.FirstChild.NextSibling.Name, "InsertAfter.Prev");
178 Assert.AreEqual ("good_child", docelem.LastChild.PreviousSibling.Name, "InsertAfter.Next");
179 // this doesn't throw any exception *only on .NET 1.1*
180 // .NET 1.0 throws an exception.
182 document.InsertAfter(document.CreateElement("BAD_MAN"), docelem);
184 Assert.AreEqual ("<root><sub1 /><good_child /><sub2 /></root><BAD_MAN />", document.InnerXml, "InsertAfter with bad location");
185 } catch (XmlException ex) {
189 } catch (Exception) {}
194 public void Normalize ()
196 XmlDocument doc = new XmlDocument ();
197 doc.LoadXml ("<root>This is the <b>hardest</b> one.</root>");
198 doc.NodeInserted += new XmlNodeChangedEventHandler (EventNodeInserted);
199 doc.NodeChanged += new XmlNodeChangedEventHandler (EventNodeChanged);
200 doc.NodeRemoved += new XmlNodeChangedEventHandler (EventNodeRemoved);
202 Assert.AreEqual (3, doc.DocumentElement.ChildNodes.Count);
204 doc.DocumentElement.Normalize ();
205 Assert.AreEqual (3, doc.DocumentElement.ChildNodes.Count);
206 Assert.IsTrue (changed);
207 inserted = changed = removed = false;
209 doc.DocumentElement.AppendChild (doc.CreateTextNode ("Addendum."));
210 Assert.AreEqual (4, doc.DocumentElement.ChildNodes.Count);
211 inserted = changed = removed = false;
213 doc.DocumentElement.Normalize ();
214 Assert.AreEqual (3, doc.DocumentElement.ChildNodes.Count);
215 Assert.IsTrue (changed);
216 Assert.IsTrue (removed);
217 inserted = changed = removed = false;
219 doc.DocumentElement.SetAttribute ("attr", "");
220 XmlAttribute attr = doc.DocumentElement.Attributes [0] as XmlAttribute;
221 Assert.AreEqual (1, attr.ChildNodes.Count);
222 inserted = changed = removed = false;
224 // Such behavior violates DOM Level 2 Node#normalize(),
225 // but MS DOM is designed as such.
226 Assert.AreEqual (1, attr.ChildNodes.Count);
230 public void Normalize2 ()
232 XmlDocument doc = new XmlDocument ();
233 doc.PreserveWhitespace = true;
234 doc.LoadXml ("<root> </root>");
235 XmlElement root = doc.DocumentElement;
236 root.AppendChild (doc.CreateTextNode ("foo"));
237 root.AppendChild (doc.CreateTextNode ("bar"));
238 root.AppendChild (doc.CreateWhitespace (" "));
239 root.AppendChild (doc.CreateTextNode ("baz"));
240 doc.NodeInserted += new XmlNodeChangedEventHandler (OnChange);
241 doc.NodeChanged += new XmlNodeChangedEventHandler (OnChange);
242 doc.NodeRemoved += new XmlNodeChangedEventHandler (OnChange);
243 Assert.AreEqual (5, root.ChildNodes.Count, "Before Normalize()");
245 Assert.AreEqual ("<root> foobar baz</root>", root.OuterXml);
246 Assert.AreEqual (1, root.ChildNodes.Count, "After Normalize()");
251 private void OnChange (object o, XmlNodeChangedEventArgs e)
253 switch (normalize2Count) {
255 Assert.AreEqual (XmlNodeChangedAction.Remove, e.Action, "Action0");
256 Assert.AreEqual (" ", e.Node.Value, "Value0");
259 Assert.AreEqual (XmlNodeChangedAction.Remove, e.Action, "Action1");
260 Assert.AreEqual ("bar", e.Node.Value, "Value1");
263 Assert.AreEqual (XmlNodeChangedAction.Remove, e.Action, "Action2");
264 Assert.AreEqual (" ", e.Node.Value, "Value2");
267 Assert.AreEqual (XmlNodeChangedAction.Remove, e.Action, "Action3");
268 Assert.AreEqual ("baz", e.Node.Value, "Value3");
271 Assert.AreEqual (XmlNodeChangedAction.Change, e.Action, "Action4");
272 Assert.AreEqual (" foobar baz", e.Node.Value, "Value4");
275 Assert.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));
282 public void PrependChild()
284 document = new XmlDocument();
285 document.LoadXml("<root><sub1 /><sub2 /></root>");
286 XmlElement docelem = document.DocumentElement;
287 docelem.PrependChild(document.CreateElement("prepender"));
288 Assert.AreEqual ("prepender", docelem.FirstChild.Name, "PrependChild");
291 public void saveTestRemoveAll ()
293 // TODO: put this test back in when AttributeCollection.RemoveAll() is implemented.
294 element.AppendChild(element2);
297 element.RemoveAll ();
298 Assert.IsTrue (removed);
299 Assert.IsTrue (removing);
303 public void RemoveChild ()
305 element.AppendChild(element2);
308 element.RemoveChild (element2);
309 Assert.IsTrue (removed);
310 Assert.IsTrue (removing);
314 public void RemoveLastChild ()
316 element.InnerXml = "<foo/><bar/><baz/>";
317 element.RemoveChild (element.LastChild);
318 Assert.IsNotNull (element.FirstChild);
322 public void GetPrefixOfNamespace ()
324 document.LoadXml ("<root><c1 xmlns='urn:foo'><c2 xmlns:foo='urn:foo' xmlns='urn:bar'><c3 xmlns=''/></c2></c1></root>");
325 Assert.AreEqual (String.Empty, document.DocumentElement.GetPrefixOfNamespace ("urn:foo"), "root");
326 Assert.AreEqual (String.Empty, document.DocumentElement.GetPrefixOfNamespace ("urn:foo"), "c1");
327 Assert.AreEqual (String.Empty, document.DocumentElement.FirstChild.GetPrefixOfNamespace ("urn:foo"), "c2");
328 Assert.AreEqual ("foo", document.DocumentElement.FirstChild.FirstChild.GetPrefixOfNamespace ("urn:foo"), "c3");
330 // disconnected nodes.
331 XmlNode n = document.CreateElement ("foo");
332 Assert.AreEqual (String.Empty, n.GetPrefixOfNamespace ("foo"));
333 n = document.CreateTextNode ("text"); // does not have Attributes
334 Assert.AreEqual (String.Empty, n.GetPrefixOfNamespace ("foo"));
335 n = document.CreateXmlDeclaration ("1.0", null, null); // does not have Attributes
336 Assert.AreEqual (String.Empty, n.GetPrefixOfNamespace ("foo"));
340 public void GetPrefixOfNamespace2 ()
342 XmlDocument doc = new XmlDocument ();
343 doc.AppendChild (doc.CreateElement ("foo"));
344 doc.DocumentElement.SetAttributeNode (
345 doc.CreateAttribute ("xmlns", "u", "http://www.w3.org/2000/xmlns/"));
346 doc.DocumentElement.Attributes [0].Value = "urn:foo";
347 XmlElement el = doc.CreateElement ("bar");
348 doc.DocumentElement.AppendChild (el);
349 Assert.AreEqual ("u", el.GetPrefixOfNamespace ("urn:foo"));
353 public void ReplaceChild ()
355 document.LoadXml ("<root/>");
356 document.NodeInserted += new XmlNodeChangedEventHandler (this.EventNodeInserted);
357 document.NodeChanged += new XmlNodeChangedEventHandler (this.EventNodeChanged);
358 document.NodeRemoved += new XmlNodeChangedEventHandler (this.EventNodeRemoved);
359 inserted = changed = removed = false;
360 XmlElement el = document.CreateElement("root2");
361 document.ReplaceChild (el, document.DocumentElement);
362 Assert.AreEqual ("root2", document.DocumentElement.Name);
363 Assert.AreEqual (1, document.ChildNodes.Count);
364 Assert.IsTrue (inserted && removed && !changed);
368 public void InnerText ()
370 document.LoadXml ("<root>This is <b>mixed</b> content. Also includes <![CDATA[CDATA section]]>.<!-- Should be ignored --></root>");
371 string total = "This is mixed content. Also includes CDATA section.";
372 XmlNode elemB = document.DocumentElement.ChildNodes [1];
373 Assert.AreEqual ("mixed", elemB.FirstChild.InnerText); // text node
374 Assert.AreEqual ("mixed", elemB.InnerText); // element b
375 Assert.AreEqual (total, document.DocumentElement.InnerText); // element root
376 Assert.AreEqual (total, document.InnerText); // whole document
380 public void InnerXmlWithXmlns ()
382 XmlDocument document = new XmlDocument ();
383 XmlElement xel = document.CreateElement ("KeyValue", "http://www.w3.org/2000/09/xmldsig#");
384 xel.SetAttribute ("xmlns", "http://www.w3.org/2000/09/xmldsig#");
385 xel.InnerXml = "<DSAKeyValue>blablabla</DSAKeyValue>";
386 string expected = "<KeyValue xmlns=\"http://www.w3.org/2000/09/xmldsig#\"><DSAKeyValue>blablabla</DSAKeyValue></KeyValue>";
387 Assert.AreEqual (expected, xel.OuterXml);
391 public void SelectNodes ()
393 // This test is done in this class since it tests only XmlDocumentNavigator.
394 string xpath = "//@*|//namespace::*";
395 XmlDocument doc = new XmlDocument ();
396 doc.LoadXml ("<element xmlns='urn:foo'><foo><bar>test</bar></foo></element>");
397 XmlNodeList nl = doc.SelectNodes (xpath);
398 Assert.AreEqual (6, nl.Count);
399 // BTW, as for namespace nodes, Node does not exist
400 // in the tree, so the return value should be
401 // implementation dependent.
402 Assert.AreEqual (XmlNodeType.Attribute, nl [0].NodeType, "#1");
403 Assert.AreEqual (XmlNodeType.Attribute, nl [1].NodeType, "#2");
404 Assert.AreEqual (XmlNodeType.Attribute, nl [2].NodeType, "#3");
405 Assert.AreEqual (XmlNodeType.Attribute, nl [3].NodeType, "#4");
406 Assert.AreEqual (XmlNodeType.Attribute, nl [4].NodeType, "#5");
407 Assert.AreEqual (XmlNodeType.Attribute, nl [5].NodeType, "#6");
408 Assert.AreEqual ("xmlns", nl [0].LocalName);
409 Assert.AreEqual ("xml", nl [1].LocalName);
410 Assert.AreEqual ("xmlns", nl [2].LocalName);
411 Assert.AreEqual ("xml", nl [3].LocalName);
412 Assert.AreEqual ("xmlns", nl [4].LocalName);
413 Assert.AreEqual ("xml", nl [5].LocalName);
417 [Ignore ("MS.NET has a bug; it does not return nodes in document order.")]
418 public void SelectNodes2 ()
420 // This test is done in this class since it tests only XmlDocumentNavigator.
421 string xpath = "//*|//@*|//namespace::*";
422 XmlDocument doc = new XmlDocument ();
423 doc.LoadXml ("<element xmlns='urn:foo'><foo><bar>test</bar></foo></element>");
424 XmlNodeList nl = doc.SelectNodes (xpath);
425 Assert.AreEqual (9, nl.Count);
426 Assert.AreEqual (XmlNodeType.Element, nl [0].NodeType);
427 Assert.AreEqual (XmlNodeType.Attribute, nl [1].NodeType);
428 Assert.AreEqual (XmlNodeType.Attribute, nl [2].NodeType);
429 Assert.AreEqual (XmlNodeType.Element, nl [3].NodeType);
430 Assert.AreEqual (XmlNodeType.Attribute, nl [4].NodeType);
431 Assert.AreEqual (XmlNodeType.Attribute, nl [5].NodeType);
432 Assert.AreEqual (XmlNodeType.Element, nl [6].NodeType);
433 Assert.AreEqual (XmlNodeType.Attribute, nl [7].NodeType);
434 Assert.AreEqual (XmlNodeType.Attribute, nl [8].NodeType);
435 Assert.AreEqual ("element", nl [0].LocalName);
436 Assert.AreEqual ("xmlns", nl [1].LocalName);
437 Assert.AreEqual ("xml", nl [2].LocalName);
438 Assert.AreEqual ("foo", nl [3].LocalName);
439 Assert.AreEqual ("xmlns", nl [4].LocalName);
440 Assert.AreEqual ("xml", nl [5].LocalName);
441 Assert.AreEqual ("bar", nl [6].LocalName);
442 Assert.AreEqual ("xmlns", nl [7].LocalName);
443 Assert.AreEqual ("xml", nl [8].LocalName);
447 public void BaseURI ()
450 XmlDocument doc = new XmlDocument ();
451 doc.Load ("Test/XmlFiles/simple.xml");
452 XmlElement el = doc.CreateElement ("foo");
453 Assert.AreEqual (String.Empty, el.BaseURI);
454 doc.DocumentElement.AppendChild (el);
455 Assert.IsTrue (String.Empty != el.BaseURI);
456 XmlAttribute attr = doc.CreateAttribute ("attr");
457 Assert.AreEqual (String.Empty, attr.BaseURI);
461 public void CloneReadonlyNode ()
463 // Clone() should return such node that is not readonly
464 string dtd = "<!DOCTYPE root ["
465 + "<!ELEMENT root (#PCDATA|foo)*>"
466 + "<!ELEMENT foo EMPTY>"
467 + "<!ENTITY ent1 '<foo /><![CDATA[cdata]]>'>]>";
468 string xml = dtd + "<root>&ent1;</root>";
470 XmlDocument doc = new XmlDocument ();
472 XmlNode n = doc.DocumentElement.FirstChild.FirstChild;
473 Assert.IsTrue (n.IsReadOnly, "#1");
474 Assert.IsTrue (!n.CloneNode (true).IsReadOnly, "#2");
478 public void InnerTextComment ()
480 XmlDocument doc = new XmlDocument ();
481 doc.LoadXml ("<a><!--xx--></a>");
482 Assert.AreEqual (String.Empty, doc.InnerText);
485 [Test] // part of bug #80331
486 public void AppendReferenceChildAsNewChild ()
488 XmlDocument d = new XmlDocument ();
489 XmlElement r = d.CreateElement ("Docs");
492 XmlElement s = Create (d, "param", "pattern");
493 s.AppendChild (Create (d, "para", "insert text here"));
497 r.AppendChild (Create (d, "param", "pattern"));
498 r.AppendChild (Create (d, "param", "pattern"));
500 r.InsertBefore (s, r.FirstChild);
503 XmlElement Create (XmlDocument d, string name, string param)
505 XmlElement e = d.CreateElement (name);
506 e.SetAttribute ("name", param);
511 public void PrependChild2 ()
513 XmlDocument d = new XmlDocument ();
514 XmlElement r = d.CreateElement ("Docs");
517 XmlElement s = Create (d, "param", "pattern");
518 s.AppendChild (Create (d, "para", "insert text here"));
522 r.AppendChild (Create (d, "param", "pattern"));
523 r.AppendChild (Create (d, "param", "pattern"));