2 // System.Xml.XmlDocumentTests
5 // Jason Diamond <jason@injektilo.org>
6 // Kral Ferch <kral_ferch@hotmail.com>
7 // Martin Willemoes Hansen <mwh@sysrq.dk>
9 // (C) 2002 Jason Diamond, Kral Ferch
10 // (C) 2003 Martin Willemoes Hansen
14 using System.Collections;
19 using NUnit.Framework;
22 using InvalidNodeTypeArgException = System.ArgumentException;
23 #else // it makes less sense
24 using InvalidNodeTypeArgException = System.ArgumentOutOfRangeException;
27 namespace MonoTests.System.Xml
30 public class XmlDocumentTests
32 private XmlDocument document;
33 private ArrayList eventStrings = new ArrayList();
35 // These Event* methods support the TestEventNode* Tests in this file.
36 // Most of them are event handlers for the XmlNodeChangedEventHandler
38 private void EventStringAdd(string eventName, XmlNodeChangedEventArgs e)
40 string oldParent = (e.OldParent != null) ? e.OldParent.Name : "<none>";
41 string newParent = (e.NewParent != null) ? e.NewParent.Name : "<none>";
42 eventStrings.Add (String.Format ("{0}, {1}, {2}, {3}, {4}", eventName, e.Action.ToString (), e.Node.OuterXml, oldParent, newParent));
45 private void EventNodeChanged(Object sender, XmlNodeChangedEventArgs e)
47 EventStringAdd ("NodeChanged", e);
50 private void EventNodeChanging (Object sender, XmlNodeChangedEventArgs e)
52 EventStringAdd ("NodeChanging", e);
55 private void EventNodeChangingException (Object sender, XmlNodeChangedEventArgs e)
57 throw new Exception ("don't change the value.");
60 private void EventNodeInserted(Object sender, XmlNodeChangedEventArgs e)
62 EventStringAdd ("NodeInserted", e);
65 private void EventNodeInserting(Object sender, XmlNodeChangedEventArgs e)
67 EventStringAdd ("NodeInserting", e);
70 private void EventNodeInsertingException(Object sender, XmlNodeChangedEventArgs e)
72 throw new Exception ("don't insert the element.");
75 private void EventNodeRemoved(Object sender, XmlNodeChangedEventArgs e)
77 EventStringAdd ("NodeRemoved", e);
80 private void EventNodeRemoving(Object sender, XmlNodeChangedEventArgs e)
82 EventStringAdd ("NodeRemoving", e);
85 private void EventNodeRemovingException(Object sender, XmlNodeChangedEventArgs e)
87 throw new Exception ("don't remove the element.");
91 public void GetReady ()
93 document = new XmlDocument ();
94 document.PreserveWhitespace = true;
98 public void CreateNodeNodeTypeNameEmptyParams ()
101 document.CreateNode (null, null, null);
102 Assert.Fail ("Expected an ArgumentException to be thrown.");
103 } catch (ArgumentException) {}
106 document.CreateNode ("attribute", null, null);
107 Assert.Fail ("Expected a NullReferenceException to be thrown.");
108 } catch (NullReferenceException) {}
111 document.CreateNode ("attribute", "", null);
112 Assert.Fail ("Expected an ArgumentException to be thrown.");
113 } catch (ArgumentException) {}
116 document.CreateNode ("element", null, null);
117 Assert.Fail ("Expected a NullReferenceException to be thrown.");
118 } catch (NullReferenceException) {}
121 document.CreateNode ("element", "", null);
122 Assert.Fail ("Expected an ArgumentException to be thrown.");
123 } catch (ArgumentException) {}
126 document.CreateNode ("entityreference", null, null);
127 Assert.Fail ("Expected a NullReferenceException to be thrown.");
128 } catch (NullReferenceException) {}
132 public void CreateNodeInvalidXmlNodeType ()
137 node = document.CreateNode (XmlNodeType.EndElement, null, null);
138 Assert.Fail ("Expected an ArgumentOutOfRangeException to be thrown.");
139 } catch (InvalidNodeTypeArgException) {}
142 node = document.CreateNode (XmlNodeType.EndEntity, null, null);
143 Assert.Fail ("Expected an ArgumentOutOfRangeException to be thrown.");
144 } catch (InvalidNodeTypeArgException) {}
147 node = document.CreateNode (XmlNodeType.Entity, null, null);
148 Assert.Fail ("Expected an ArgumentOutOfRangeException to be thrown.");
149 } catch (InvalidNodeTypeArgException) {}
152 node = document.CreateNode (XmlNodeType.None, null, null);
153 Assert.Fail ("Expected an ArgumentOutOfRangeException to be thrown.");
154 } catch (InvalidNodeTypeArgException) {}
157 node = document.CreateNode (XmlNodeType.Notation, null, null);
158 Assert.Fail ("Expected an ArgumentOutOfRangeException to be thrown.");
159 } catch (InvalidNodeTypeArgException) {}
161 // TODO: undocumented allowable type.
162 node = document.CreateNode (XmlNodeType.XmlDeclaration, null, null);
163 Assert.AreEqual (XmlNodeType.XmlDeclaration, node.NodeType);
167 public void CreateNodeWhichParamIsUsed ()
171 // No constructor params for Document, DocumentFragment.
173 node = document.CreateNode (XmlNodeType.CDATA, "a", "b", "c");
174 Assert.AreEqual (String.Empty, ((XmlCDataSection)node).Value);
176 node = document.CreateNode (XmlNodeType.Comment, "a", "b", "c");
177 Assert.AreEqual (String.Empty, ((XmlComment)node).Value);
179 node = document.CreateNode (XmlNodeType.DocumentType, "a", "b", "c");
180 Assert.IsNull (((XmlDocumentType)node).Value);
182 // TODO: add this back in to test when it's implemented.
183 // node = document.CreateNode (XmlNodeType.EntityReference, "a", "b", "c");
184 // Assert.IsNull (((XmlEntityReference)node).Value);
186 // TODO: add this back in to test when it's implemented.
187 // node = document.CreateNode (XmlNodeType.ProcessingInstruction, "a", "b", "c");
188 // Assert.AreEqual (String.Empty, ((XmlProcessingInstruction)node).Value);
190 node = document.CreateNode (XmlNodeType.SignificantWhitespace, "a", "b", "c");
191 Assert.AreEqual (String.Empty, ((XmlSignificantWhitespace)node).Value);
193 node = document.CreateNode (XmlNodeType.Text, "a", "b", "c");
194 Assert.AreEqual (String.Empty, ((XmlText)node).Value);
196 node = document.CreateNode (XmlNodeType.Whitespace, "a", "b", "c");
197 Assert.AreEqual (String.Empty, ((XmlWhitespace)node).Value);
199 node = document.CreateNode (XmlNodeType.XmlDeclaration, "a", "b", "c");
200 Assert.AreEqual ("version=\"1.0\"", ((XmlDeclaration)node).Value);
205 [Category ("NotDotNet")] // enbug in 2.0
207 public void CreateNodeNodeTypeName ()
212 node = document.CreateNode ("foo", null, null);
213 Assert.Fail ("Expected an ArgumentException to be thrown.");
214 } catch (ArgumentException) {}
216 // .NET 2.0 fails here.
217 node = document.CreateNode("attribute", "foo", null);
218 Assert.AreEqual (XmlNodeType.Attribute, node.NodeType);
220 node = document.CreateNode("cdatasection", null, null);
221 Assert.AreEqual (XmlNodeType.CDATA, node.NodeType);
223 node = document.CreateNode("comment", null, null);
224 Assert.AreEqual (XmlNodeType.Comment, node.NodeType);
226 node = document.CreateNode("document", null, null);
227 Assert.AreEqual (XmlNodeType.Document, node.NodeType);
228 // TODO: test which constructor this ended up calling,
229 // i.e. reuse underlying NameTable or not?
231 node = document.CreateNode("documentfragment", null, null);
232 Assert.AreEqual (XmlNodeType.DocumentFragment, node.NodeType);
234 node = document.CreateNode("documenttype", null, null);
235 Assert.AreEqual (XmlNodeType.DocumentType, node.NodeType);
237 node = document.CreateNode("element", "foo", null);
238 Assert.AreEqual (XmlNodeType.Element, node.NodeType);
240 // TODO: add this back in to test when it's implemented.
241 // ---> It is implemented, but it is LAMESPEC that allows null entity reference name.
242 // node = document.CreateNode("entityreference", "foo", null);
243 // Assert.AreEqual (XmlNodeType.EntityReference, node.NodeType);
245 // LAMESPEC: null PI name is silly.
246 // node = document.CreateNode("processinginstruction", null, null);
247 // Assert.AreEqual (XmlNodeType.ProcessingInstruction, node.NodeType);
249 node = document.CreateNode("significantwhitespace", null, null);
250 Assert.AreEqual (XmlNodeType.SignificantWhitespace, node.NodeType);
252 node = document.CreateNode("text", null, null);
253 Assert.AreEqual (XmlNodeType.Text, node.NodeType);
255 node = document.CreateNode("whitespace", null, null);
256 Assert.AreEqual (XmlNodeType.Whitespace, node.NodeType);
260 public void DocumentElement ()
262 Assert.IsNull (document.DocumentElement);
263 XmlElement element = document.CreateElement ("foo", "bar", "http://foo/");
264 Assert.IsNotNull (element);
266 Assert.AreEqual ("foo", element.Prefix);
267 Assert.AreEqual ("bar", element.LocalName);
268 Assert.AreEqual ("http://foo/", element.NamespaceURI);
270 Assert.AreEqual ("foo:bar", element.Name);
272 Assert.AreSame (element, document.AppendChild (element));
274 Assert.AreSame (element, document.DocumentElement);
278 public void DocumentEmpty()
280 Assert.AreEqual ("", document.OuterXml, "Incorrect output for empty document.");
284 public void EventNodeChanged()
289 document.NodeChanged += new XmlNodeChangedEventHandler (this.EventNodeChanged);
291 // Node that is part of the document.
292 document.AppendChild (document.CreateElement ("foo"));
293 comment = document.CreateComment ("bar");
294 document.DocumentElement.AppendChild (comment);
295 Assert.AreEqual ("<!--bar-->", document.DocumentElement.InnerXml);
296 comment.Value = "baz";
297 Assert.IsTrue (eventStrings.Contains ("NodeChanged, Change, <!--baz-->, foo, foo"));
298 Assert.AreEqual ("<!--baz-->", document.DocumentElement.InnerXml);
300 // Node that isn't part of the document but created by the document.
301 element = document.CreateElement ("foo");
302 comment = document.CreateComment ("bar");
303 element.AppendChild (comment);
304 Assert.AreEqual ("<!--bar-->", element.InnerXml);
305 comment.Value = "baz";
306 Assert.IsTrue (eventStrings.Contains ("NodeChanged, Change, <!--baz-->, foo, foo"));
307 Assert.AreEqual ("<!--baz-->", element.InnerXml);
310 TODO: Insert this when XmlNode.InnerText() and XmlNode.InnerXml() have been implemented.
312 // Node that is part of the document.
313 element = document.CreateElement ("foo");
314 element.InnerText = "bar";
315 document.AppendChild(element);
316 element.InnerText = "baz";
317 Assert.IsTrue (eventStrings.Contains("NodeChanged, Change, baz, foo, foo"));
319 // Node that isn't part of the document but created by the document.
320 element = document.CreateElement("qux");
321 element.InnerText = "quux";
322 element.InnerText = "quuux";
323 Assert.IsTrue (eventStrings.Contains("NodeChanged, Change, quuux, qux, qux"));
328 public void EventNodeChanging()
333 document.NodeChanging += new XmlNodeChangedEventHandler (this.EventNodeChanging);
335 // Node that is part of the document.
336 document.AppendChild (document.CreateElement ("foo"));
337 comment = document.CreateComment ("bar");
338 document.DocumentElement.AppendChild (comment);
339 Assert.AreEqual ("<!--bar-->", document.DocumentElement.InnerXml);
340 comment.Value = "baz";
341 Assert.IsTrue (eventStrings.Contains ("NodeChanging, Change, <!--bar-->, foo, foo"));
342 Assert.AreEqual ("<!--baz-->", document.DocumentElement.InnerXml);
344 // Node that isn't part of the document but created by the document.
345 element = document.CreateElement ("foo");
346 comment = document.CreateComment ("bar");
347 element.AppendChild (comment);
348 Assert.AreEqual ("<!--bar-->", element.InnerXml);
349 comment.Value = "baz";
350 Assert.IsTrue (eventStrings.Contains ("NodeChanging, Change, <!--bar-->, foo, foo"));
351 Assert.AreEqual ("<!--baz-->", element.InnerXml);
353 // If an exception is thrown the Document returns to original state.
354 document.NodeChanging += new XmlNodeChangedEventHandler (this.EventNodeChangingException);
355 element = document.CreateElement("foo");
356 comment = document.CreateComment ("bar");
357 element.AppendChild (comment);
358 Assert.AreEqual ("<!--bar-->", element.InnerXml);
361 comment.Value = "baz";
362 Assert.Fail ("Expected an exception to be thrown by the NodeChanging event handler method EventNodeChangingException().");
363 } catch (Exception) {}
364 Assert.AreEqual ("<!--bar-->", element.InnerXml);
366 // Yes it's a bit anal but this tests whether the node changing event exception fires before the
367 // ArgumentOutOfRangeException. Turns out it does so that means our implementation needs to raise
368 // the node changing event before doing any work.
371 comment.ReplaceData(-1, 0, "qux");
372 Assert.Fail ("Expected an ArgumentOutOfRangeException to be thrown.");
377 TODO: Insert this when XmlNode.InnerText() and XmlNode.InnerXml() have been implemented.
379 // Node that is part of the document.
380 element = document.CreateElement ("foo");
381 element.InnerText = "bar";
382 document.AppendChild(element);
383 element.InnerText = "baz";
384 Assert.IsTrue (eventStrings.Contains("NodeChanging, Change, bar, foo, foo"));
386 // Node that isn't part of the document but created by the document.
387 element = document.CreateElement("foo");
388 element.InnerText = "bar";
389 element.InnerText = "baz";
390 Assert.IsTrue (eventStrings.Contains("NodeChanging, Change, bar, foo, foo"));
392 // If an exception is thrown the Document returns to original state.
393 document.NodeChanging += new XmlNodeChangedEventHandler (this.EventNodeChangingException);
394 element = document.CreateElement("foo");
395 element.InnerText = "bar";
397 element.InnerText = "baz";
398 Assert.Fail ("Expected an exception to be thrown by the NodeChanging event handler method EventNodeChangingException().");
399 } catch (Exception) {}
400 Assert.AreEqual ("bar", element.InnerText);
405 public void EventNodeInserted()
409 document.NodeInserted += new XmlNodeChangedEventHandler (this.EventNodeInserted);
411 // Inserted 'foo' element to the document.
412 element = document.CreateElement ("foo");
413 document.AppendChild (element);
414 Assert.IsTrue (eventStrings.Contains ("NodeInserted, Insert, <foo />, <none>, #document"));
416 // Append child on node in document
417 element = document.CreateElement ("foo");
418 document.DocumentElement.AppendChild (element);
419 Assert.IsTrue (eventStrings.Contains ("NodeInserted, Insert, <foo />, <none>, foo"));
421 // Append child on node not in document but created by document
422 element = document.CreateElement ("bar");
423 element.AppendChild(document.CreateElement ("bar"));
424 Assert.IsTrue (eventStrings.Contains("NodeInserted, Insert, <bar />, <none>, bar"));
428 public void EventNodeInserting()
432 document.NodeInserting += new XmlNodeChangedEventHandler (this.EventNodeInserting);
434 // Inserting 'foo' element to the document.
435 element = document.CreateElement ("foo");
436 document.AppendChild (element);
437 Assert.IsTrue (eventStrings.Contains ("NodeInserting, Insert, <foo />, <none>, #document"));
439 // Append child on node in document
440 element = document.CreateElement ("foo");
441 document.DocumentElement.AppendChild (element);
442 Assert.IsTrue (eventStrings.Contains ("NodeInserting, Insert, <foo />, <none>, foo"));
444 // Append child on node not in document but created by document
445 element = document.CreateElement ("bar");
446 Assert.AreEqual (0, element.ChildNodes.Count);
447 element.AppendChild (document.CreateElement ("bar"));
448 Assert.IsTrue (eventStrings.Contains ("NodeInserting, Insert, <bar />, <none>, bar"));
449 Assert.AreEqual (1, element.ChildNodes.Count);
451 // If an exception is thrown the Document returns to original state.
452 document.NodeInserting += new XmlNodeChangedEventHandler (this.EventNodeInsertingException);
453 Assert.AreEqual (1, element.ChildNodes.Count);
456 element.AppendChild (document.CreateElement("baz"));
457 Assert.Fail ("Expected an exception to be thrown by the NodeInserting event handler method EventNodeInsertingException().");
460 Assert.AreEqual (1, element.ChildNodes.Count);
464 public void EventNodeRemoved()
469 document.NodeRemoved += new XmlNodeChangedEventHandler (this.EventNodeRemoved);
471 // Removed 'bar' element from 'foo' outside document.
472 element = document.CreateElement ("foo");
473 element2 = document.CreateElement ("bar");
474 element.AppendChild (element2);
475 Assert.AreEqual (1, element.ChildNodes.Count);
476 element.RemoveChild (element2);
477 Assert.IsTrue (eventStrings.Contains ("NodeRemoved, Remove, <bar />, foo, <none>"));
478 Assert.AreEqual (0, element.ChildNodes.Count);
481 * TODO: put this test back in when AttributeCollection.RemoveAll() is implemented.
484 element = document.CreateElement ("foo");
485 element2 = document.CreateElement ("bar");
486 element.AppendChild(element2);
487 Assert.AreEqual (1, element.ChildNodes.Count);
489 Assert.IsTrue (eventStrings.Contains ("NodeRemoved, Remove, <bar />, foo, <none>"));
490 Assert.AreEqual (0, element.ChildNodes.Count);
493 // Removed 'bar' element from 'foo' inside document.
494 element = document.CreateElement ("foo");
495 document.AppendChild (element);
496 element = document.CreateElement ("bar");
497 document.DocumentElement.AppendChild (element);
498 Assert.AreEqual (1, document.DocumentElement.ChildNodes.Count);
499 document.DocumentElement.RemoveChild (element);
500 Assert.IsTrue (eventStrings.Contains ("NodeRemoved, Remove, <bar />, foo, <none>"));
501 Assert.AreEqual (0, document.DocumentElement.ChildNodes.Count);
505 public void EventNodeRemoving()
510 document.NodeRemoving += new XmlNodeChangedEventHandler (this.EventNodeRemoving);
512 // Removing 'bar' element from 'foo' outside document.
513 element = document.CreateElement ("foo");
514 element2 = document.CreateElement ("bar");
515 element.AppendChild (element2);
516 Assert.AreEqual (1, element.ChildNodes.Count);
517 element.RemoveChild (element2);
518 Assert.IsTrue (eventStrings.Contains ("NodeRemoving, Remove, <bar />, foo, <none>"));
519 Assert.AreEqual (0, element.ChildNodes.Count);
522 * TODO: put this test back in when AttributeCollection.RemoveAll() is implemented.
525 element = document.CreateElement ("foo");
526 element2 = document.CreateElement ("bar");
527 element.AppendChild(element2);
528 Assert.AreEqual (1, element.ChildNodes.Count);
530 Assert.IsTrue (eventStrings.Contains ("NodeRemoving, Remove, <bar />, foo, <none>"));
531 Assert.AreEqual (0, element.ChildNodes.Count);
534 // Removing 'bar' element from 'foo' inside document.
535 element = document.CreateElement ("foo");
536 document.AppendChild (element);
537 element = document.CreateElement ("bar");
538 document.DocumentElement.AppendChild (element);
539 Assert.AreEqual (1, document.DocumentElement.ChildNodes.Count);
540 document.DocumentElement.RemoveChild (element);
541 Assert.IsTrue (eventStrings.Contains ("NodeRemoving, Remove, <bar />, foo, <none>"));
542 Assert.AreEqual (0, document.DocumentElement.ChildNodes.Count);
544 // If an exception is thrown the Document returns to original state.
545 document.NodeRemoving += new XmlNodeChangedEventHandler (this.EventNodeRemovingException);
546 element.AppendChild (element2);
547 Assert.AreEqual (1, element.ChildNodes.Count);
550 element.RemoveChild(element2);
551 Assert.Fail ("Expected an exception to be thrown by the NodeRemoving event handler method EventNodeRemovingException().");
554 Assert.AreEqual (1, element.ChildNodes.Count);
558 public void GetElementsByTagNameNoNameSpace ()
560 string xml = @"<library><book><title>XML Fun</title><author>John Doe</author>
561 <price>34.95</price></book><book><title>Bear and the Dragon</title>
562 <author>Tom Clancy</author><price>6.95</price></book><book>
563 <title>Bourne Identity</title><author>Robert Ludlum</author>
564 <price>9.95</price></book><Fluffer><Nutter><book>
565 <title>Bourne Ultimatum</title><author>Robert Ludlum</author>
566 <price>9.95</price></book></Nutter></Fluffer></library>";
568 MemoryStream memoryStream = new MemoryStream (Encoding.UTF8.GetBytes (xml));
569 document = new XmlDocument ();
570 document.Load (memoryStream);
571 XmlNodeList bookList = document.GetElementsByTagName ("book");
572 Assert.AreEqual (4, bookList.Count, "GetElementsByTagName (string) returned incorrect count.");
576 public void GetElementsByTagNameUsingNameSpace ()
578 StringBuilder xml = new StringBuilder ();
579 xml.Append ("<?xml version=\"1.0\" ?><library xmlns:North=\"http://www.foo.com\" ");
580 xml.Append ("xmlns:South=\"http://www.goo.com\"><North:book type=\"non-fiction\"> ");
581 xml.Append ("<North:title type=\"intro\">XML Fun</North:title> " );
582 xml.Append ("<North:author>John Doe</North:author> " );
583 xml.Append ("<North:price>34.95</North:price></North:book> " );
584 xml.Append ("<South:book type=\"fiction\"> " );
585 xml.Append ("<South:title>Bear and the Dragon</South:title> " );
586 xml.Append ("<South:author>Tom Clancy</South:author> " );
587 xml.Append ("<South:price>6.95</South:price></South:book> " );
588 xml.Append ("<South:book type=\"fiction\"><South:title>Bourne Identity</South:title> " );
589 xml.Append ("<South:author>Robert Ludlum</South:author> " );
590 xml.Append ("<South:price>9.95</South:price></South:book></library>");
592 MemoryStream memoryStream = new MemoryStream (Encoding.UTF8.GetBytes (xml.ToString ()));
593 document = new XmlDocument ();
594 document.Load (memoryStream);
595 XmlNodeList bookList = document.GetElementsByTagName ("book", "http://www.goo.com");
596 Assert.AreEqual (2, bookList.Count, "GetElementsByTagName (string, uri) returned incorrect count.");
600 public void GetElementsByTagNameNs2 ()
602 document.LoadXml (@"<root>
603 <x:a xmlns:x='urn:foo' id='a'>
604 <y:a xmlns:y='urn:foo' id='b'/>
608 <?a processing instruction ?>
612 // id='b' has different prefix. Should not caught by (name),
613 // while should caught by (name, ns).
614 XmlNodeList nl = document.GetElementsByTagName ("x:a");
615 Assert.AreEqual (2, nl.Count);
616 Assert.AreEqual ("a", nl [0].Attributes ["id"].Value);
617 Assert.AreEqual ("c", nl [1].Attributes ["id"].Value);
619 nl = document.GetElementsByTagName ("a", "urn:foo");
620 Assert.AreEqual (3, nl.Count);
621 Assert.AreEqual ("a", nl [0].Attributes ["id"].Value);
622 Assert.AreEqual ("b", nl [1].Attributes ["id"].Value);
623 Assert.AreEqual ("c", nl [2].Attributes ["id"].Value);
626 nl = document.GetElementsByTagName ("*");
627 Assert.AreEqual (6, nl.Count);
628 Assert.AreEqual ("root", nl [0].Name);
629 Assert.AreEqual ("a", nl [1].Attributes ["id"].Value);
630 Assert.AreEqual ("b", nl [2].Attributes ["id"].Value);
631 Assert.AreEqual ("c", nl [3].Attributes ["id"].Value);
632 Assert.AreEqual ("d", nl [4].Attributes ["id"].Value);
633 Assert.AreEqual ("e", nl [5].Attributes ["id"].Value);
635 // wildcard - local and ns
636 nl = document.GetElementsByTagName ("*", "*");
637 Assert.AreEqual (6, nl.Count);
638 Assert.AreEqual ("root", nl [0].Name);
639 Assert.AreEqual ("a", nl [1].Attributes ["id"].Value);
640 Assert.AreEqual ("b", nl [2].Attributes ["id"].Value);
641 Assert.AreEqual ("c", nl [3].Attributes ["id"].Value);
642 Assert.AreEqual ("d", nl [4].Attributes ["id"].Value);
643 Assert.AreEqual ("e", nl [5].Attributes ["id"].Value);
645 // namespace wildcard - namespace
646 nl = document.GetElementsByTagName ("*", "urn:foo");
647 Assert.AreEqual (4, nl.Count);
648 Assert.AreEqual ("a", nl [0].Attributes ["id"].Value);
649 Assert.AreEqual ("b", nl [1].Attributes ["id"].Value);
650 Assert.AreEqual ("c", nl [2].Attributes ["id"].Value);
651 Assert.AreEqual ("e", nl [3].Attributes ["id"].Value);
653 // namespace wildcard - local only. I dare say, such usage is not XML-ish!
654 nl = document.GetElementsByTagName ("a", "*");
655 Assert.AreEqual (3, nl.Count);
656 Assert.AreEqual ("a", nl [0].Attributes ["id"].Value);
657 Assert.AreEqual ("b", nl [1].Attributes ["id"].Value);
658 Assert.AreEqual ("c", nl [2].Attributes ["id"].Value);
662 public void Implementation ()
664 Assert.IsNotNull (new XmlDocument ().Implementation);
668 public void InnerAndOuterXml ()
670 Assert.AreEqual (String.Empty, document.InnerXml);
671 Assert.AreEqual (document.InnerXml, document.OuterXml);
673 XmlDeclaration declaration = document.CreateXmlDeclaration ("1.0", null, null);
674 document.AppendChild (declaration);
675 Assert.AreEqual ("<?xml version=\"1.0\"?>", document.InnerXml);
676 Assert.AreEqual (document.InnerXml, document.OuterXml);
678 XmlElement element = document.CreateElement ("foo");
679 document.AppendChild (element);
680 Assert.AreEqual ("<?xml version=\"1.0\"?><foo />", document.InnerXml);
681 Assert.AreEqual (document.InnerXml, document.OuterXml);
683 XmlComment comment = document.CreateComment ("bar");
684 document.DocumentElement.AppendChild (comment);
685 Assert.AreEqual ("<?xml version=\"1.0\"?><foo><!--bar--></foo>", document.InnerXml);
686 Assert.AreEqual (document.InnerXml, document.OuterXml);
688 XmlText text = document.CreateTextNode ("baz");
689 document.DocumentElement.AppendChild (text);
690 Assert.AreEqual ("<?xml version=\"1.0\"?><foo><!--bar-->baz</foo>", document.InnerXml);
691 Assert.AreEqual (document.InnerXml, document.OuterXml);
693 element = document.CreateElement ("quux");
694 element.SetAttribute ("quuux", "squonk");
695 document.DocumentElement.AppendChild (element);
696 Assert.AreEqual ("<?xml version=\"1.0\"?><foo><!--bar-->baz<quux quuux=\"squonk\" /></foo>", document.InnerXml);
697 Assert.AreEqual (document.InnerXml, document.OuterXml);
701 public void LoadWithSystemIOStream ()
703 string xml = @"<library><book><title>XML Fun</title><author>John Doe</author>
704 <price>34.95</price></book><book><title>Bear and the Dragon</title>
705 <author>Tom Clancy</author><price>6.95</price></book><book>
706 <title>Bourne Identity</title><author>Robert Ludlum</author>
707 <price>9.95</price></book><Fluffer><Nutter><book>
708 <title>Bourne Ultimatum</title><author>Robert Ludlum</author>
709 <price>9.95</price></book></Nutter></Fluffer></library>";
711 MemoryStream memoryStream = new MemoryStream (Encoding.UTF8.GetBytes (xml));
712 document = new XmlDocument ();
713 document.Load (memoryStream);
714 Assert.AreEqual (true, document.HasChildNodes, "Not Loaded From IOStream");
718 public void LoadXmlReaderNamespacesFalse ()
720 XmlTextReader xtr = new XmlTextReader (
721 "<root xmlns='urn:foo' />", XmlNodeType.Document, null);
722 xtr.Namespaces = false;
723 document.Load (xtr); // Don't complain about xmlns attribute with its namespaceURI == String.Empty.
727 public void LoadXmlCDATA ()
729 document.LoadXml ("<foo><![CDATA[bar]]></foo>");
730 Assert.IsTrue (document.DocumentElement.FirstChild.NodeType == XmlNodeType.CDATA);
731 Assert.AreEqual ("bar", document.DocumentElement.FirstChild.Value);
735 public void LoadXMLComment()
737 // XmlTextReader needs to throw this exception
739 // document.LoadXml("<!--foo-->");
740 // Assert.Fail ("XmlException should have been thrown.");
742 // catch (XmlException e) {
743 // Assert.AreEqual ("The root element is missing.", e.Message, "Exception message doesn't match.");
746 document.LoadXml ("<foo><!--Comment--></foo>");
747 Assert.IsTrue (document.DocumentElement.FirstChild.NodeType == XmlNodeType.Comment);
748 Assert.AreEqual ("Comment", document.DocumentElement.FirstChild.Value);
750 document.LoadXml (@"<foo><!--bar--></foo>");
751 Assert.AreEqual ("bar", ((XmlComment)document.FirstChild.FirstChild).Data, "Incorrect target.");
755 public void LoadXmlElementSingle ()
757 Assert.IsNull (document.DocumentElement);
758 document.LoadXml ("<foo/>");
760 Assert.IsNotNull (document.DocumentElement);
761 Assert.AreSame (document.FirstChild, document.DocumentElement);
763 Assert.AreEqual (String.Empty, document.DocumentElement.Prefix);
764 Assert.AreEqual ("foo", document.DocumentElement.LocalName);
765 Assert.AreEqual (String.Empty, document.DocumentElement.NamespaceURI);
766 Assert.AreEqual ("foo", document.DocumentElement.Name);
770 public void LoadXmlElementWithAttributes ()
772 Assert.IsNull (document.DocumentElement);
773 document.LoadXml ("<foo bar='baz' quux='quuux' hoge='hello & world' />");
775 XmlElement documentElement = document.DocumentElement;
777 Assert.AreEqual ("baz", documentElement.GetAttribute ("bar"));
778 Assert.AreEqual ("quuux", documentElement.GetAttribute ("quux"));
779 Assert.AreEqual ("hello & world", documentElement.GetAttribute ("hoge"));
780 Assert.AreEqual ("hello & world", documentElement.Attributes ["hoge"].Value);
781 Assert.AreEqual (1, documentElement.GetAttributeNode ("hoge").ChildNodes.Count);
785 public void LoadXmlElementWithChildElement ()
787 document.LoadXml ("<foo><bar/></foo>");
788 Assert.IsTrue (document.ChildNodes.Count == 1);
789 Assert.IsTrue (document.FirstChild.ChildNodes.Count == 1);
790 Assert.AreEqual ("foo", document.DocumentElement.LocalName);
791 Assert.AreEqual ("bar", document.DocumentElement.FirstChild.LocalName);
795 public void LoadXmlElementWithTextNode ()
797 document.LoadXml ("<foo>bar</foo>");
798 Assert.IsTrue (document.DocumentElement.FirstChild.NodeType == XmlNodeType.Text);
799 Assert.AreEqual ("bar", document.DocumentElement.FirstChild.Value);
803 public void LoadXmlExceptionClearsDocument ()
805 document.LoadXml ("<foo/>");
806 Assert.IsTrue (document.FirstChild != null);
809 document.LoadXml ("<123/>");
810 Assert.Fail ("An XmlException should have been thrown.");
811 } catch (XmlException) {}
813 Assert.IsTrue (document.FirstChild == null);
817 public void LoadXmlProcessingInstruction ()
819 document.LoadXml (@"<?foo bar='baaz' quux='quuux'?><quuuux></quuuux>");
820 Assert.AreEqual ("foo", ((XmlProcessingInstruction)document.FirstChild).Target, "Incorrect target.");
821 Assert.AreEqual ("bar='baaz' quux='quuux'", ((XmlProcessingInstruction)document.FirstChild).Data, "Incorrect data.");
825 public void OuterXml ()
829 xml = "<root><![CDATA[foo]]></root>";
830 document.LoadXml (xml);
831 Assert.AreEqual (xml, document.OuterXml, "XmlDocument with cdata OuterXml is incorrect.");
833 xml = "<root><!--foo--></root>";
834 document.LoadXml (xml);
835 Assert.AreEqual (xml, document.OuterXml, "XmlDocument with comment OuterXml is incorrect.");
837 xml = "<root><?foo bar?></root>";
838 document.LoadXml (xml);
839 Assert.AreEqual (xml, document.OuterXml, "XmlDocument with processing instruction OuterXml is incorrect.");
843 public void ParentNodes ()
845 document.LoadXml ("<foo><bar><baz/></bar></foo>");
846 XmlNode node = document.FirstChild.FirstChild.FirstChild;
847 Assert.AreEqual ("baz", node.LocalName, "Wrong child found.");
848 Assert.AreEqual ("bar", node.ParentNode.LocalName, "Wrong parent.");
849 Assert.AreEqual ("foo", node.ParentNode.ParentNode.LocalName, "Wrong parent.");
850 Assert.AreEqual ("#document", node.ParentNode.ParentNode.ParentNode.LocalName, "Wrong parent.");
851 Assert.IsNull (node.ParentNode.ParentNode.ParentNode.ParentNode, "Expected parent to be null.");
855 public void RemovedElementNextSibling ()
860 document.LoadXml ("<foo><child1/><child2/></foo>");
861 node = document.DocumentElement.FirstChild;
862 document.DocumentElement.RemoveChild (node);
863 nextSibling = node.NextSibling;
864 Assert.IsNull (nextSibling, "Expected removed node's next sibling to be null.");
869 public void ImportNode ()
873 string xlinkURI = "http://www.w3.org/1999/XLink";
874 string xml1 = "<?xml version='1.0' encoding='utf-8' ?><foo xmlns:xlink='" + xlinkURI + "'><bar a1='v1' xlink:href='#foo'><baz><![CDATA[cdata section.\n\titem 1\n\titem 2\n]]>From here, simple text node.</baz></bar></foo>";
875 document.LoadXml(xml1);
876 XmlDocument newDoc = new XmlDocument();
877 newDoc.LoadXml("<hoge><fuga /></hoge>");
878 XmlElement bar = document.DocumentElement.FirstChild as XmlElement;
881 n = newDoc.ImportNode(bar.GetAttributeNode("href", xlinkURI), true);
882 Assert.AreEqual ("href", n.LocalName, "#ImportNode.Attr.NS.LocalName");
883 Assert.AreEqual (xlinkURI, n.NamespaceURI, "#ImportNode.Attr.NS.NSURI");
884 Assert.AreEqual ("#foo", n.Value, "#ImportNode.Attr.NS.Value");
887 n = newDoc.ImportNode(bar.FirstChild.FirstChild, true);
888 Assert.AreEqual ("cdata section.\n\titem 1\n\titem 2\n", n.Value, "#ImportNode.CDATA");
891 XmlElement e = newDoc.ImportNode(bar, true) as XmlElement;
892 Assert.AreEqual ("bar", e.Name, "#ImportNode.Element.Name");
893 Assert.AreEqual ("#foo", e.GetAttribute("href", xlinkURI), "#ImportNode.Element.Attr");
894 Assert.AreEqual ("baz", e.FirstChild.Name, "#ImportNode.Element.deep");
897 // [2002/10/14] CreateEntityReference was not implemented.
898 // document.LoadXml("<!DOCTYPE test PUBLIC 'dummy' [<!ENTITY FOOENT 'foo'>]><root>&FOOENT;</root>");
899 // n = newDoc.ImportNode(document.DocumentElement.FirstChild);
900 // Assert.AreEqual ("FOOENT", n.Name, "#ImportNode.EntityReference");
901 // Assert.AreEqual ("foo_", n.Value, "#ImportNode.EntityReference");
903 // Processing Instruction
904 document.LoadXml("<foo><?xml-stylesheet href='foo.xsl' ?></foo>");
905 XmlProcessingInstruction pi = (XmlProcessingInstruction)newDoc.ImportNode(document.DocumentElement.FirstChild, false);
906 Assert.AreEqual ("xml-stylesheet", pi.Name, "#ImportNode.ProcessingInstruction.Name");
907 Assert.AreEqual ("href='foo.xsl'", pi.Data.Trim(), "#ImportNode.ProcessingInstruction.Data");
910 document.LoadXml(xml1);
911 n = newDoc.ImportNode((XmlText)bar.FirstChild.ChildNodes[1], true);
912 Assert.AreEqual ("From here, simple text node.", n.Value, "#ImportNode.Text");
915 document.LoadXml(xml1);
916 XmlDeclaration decl = (XmlDeclaration)newDoc.ImportNode(document.FirstChild, false);
917 Assert.AreEqual (XmlNodeType.XmlDeclaration, decl.NodeType, "#ImportNode.XmlDeclaration.Type");
918 Assert.AreEqual ("utf-8", decl.Encoding, "#ImportNode.XmlDeclaration.Encoding");
922 public void NameTable()
924 XmlDocument doc = new XmlDocument();
925 Assert.IsNotNull (doc.NameTable);
929 public void SingleEmptyRootDocument()
931 XmlDocument doc = new XmlDocument();
932 doc.LoadXml("<root />");
933 Assert.IsNotNull (doc.DocumentElement);
937 public void DocumentWithDoctypeDecl ()
939 XmlDocument doc = new XmlDocument ();
940 // In fact it is invalid, but it doesn't fail with MS.NET 1.0.
941 doc.LoadXml ("<!DOCTYPE test><root />");
942 Assert.IsNotNull (doc.DocumentType);
946 doc.LoadXml ("<!DOCTYPE test SYSTEM 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'><root />");
947 } catch (XmlException) {
948 Assert.Fail ("#DoctypeDecl.System");
951 doc.LoadXml ("<!DOCTYPE test PUBLIC '-//test' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'><root />");
952 } catch (XmlException) {
953 Assert.Fail ("#DoctypeDecl.Public");
956 // Should this be commented out?
957 doc.LoadXml ("<!DOCTYPE test [<!ELEMENT foo EMPTY>]><test><foo/></test>");
961 public void CloneNode ()
963 XmlDocument doc = new XmlDocument ();
964 doc.LoadXml ("<foo><bar /><baz hoge='fuga'>TEST Text</baz></foo>");
965 XmlDocument doc2 = (XmlDocument)doc.CloneNode (false);
966 Assert.AreEqual (0, doc2.ChildNodes.Count, "ShallowCopy");
967 doc2 = (XmlDocument)doc.CloneNode (true);
968 Assert.AreEqual ("foo", doc2.DocumentElement.Name, "DeepCopy");
972 public void OuterXmlWithDefaultXmlns ()
974 XmlDocument doc = new XmlDocument ();
975 doc.LoadXml ("<iq type=\"get\" id=\"ATECLIENT_1\"><query xmlns=\"jabber:iq:auth\"><username></username></query></iq>");
976 Assert.AreEqual ("<iq type=\"get\" id=\"ATECLIENT_1\"><query xmlns=\"jabber:iq:auth\"><username></username></query></iq>", doc.OuterXml);
980 public void PreserveWhitespace ()
983 "<?xml version=\"1.0\" encoding=\"utf-8\" ?><!-- --> <foo/>";
985 XmlDocument dom = new XmlDocument ();
986 XmlTextReader reader = new XmlTextReader (new StringReader (input));
989 Assert.AreEqual (XmlNodeType.Element, dom.FirstChild.NextSibling.NextSibling.NodeType);
993 public void PreserveWhitespace2 ()
995 XmlDocument doc = new XmlDocument ();
996 Assert.IsTrue (!doc.PreserveWhitespace);
997 doc.PreserveWhitespace = true;
998 XmlDocument d2 = doc.Clone () as XmlDocument;
999 Assert.IsTrue (!d2.PreserveWhitespace); // i.e. not cloned
1000 d2.AppendChild (d2.CreateElement ("root"));
1001 d2.DocumentElement.AppendChild (d2.CreateWhitespace (" "));
1002 StringWriter sw = new StringWriter ();
1003 d2.WriteTo (new XmlTextWriter (sw));
1004 Assert.AreEqual ("<root> </root>", sw.ToString ());
1008 public void CreateAttribute ()
1010 XmlDocument dom = new XmlDocument ();
1012 // Check that null prefix and namespace are allowed and
1014 XmlAttribute attr = dom.CreateAttribute (null, "FOO", null);
1015 Assert.AreEqual (attr.Prefix, "");
1016 Assert.AreEqual (attr.NamespaceURI, "");
1020 public void DocumentTypeNodes ()
1022 string entities = "<!ENTITY foo 'foo-ent'>";
1023 string dtd = "<!DOCTYPE root [<!ELEMENT root (#PCDATA)*> " + entities + "]>";
1024 string xml = dtd + "<root>&foo;</root>";
1025 XmlValidatingReader xvr = new XmlValidatingReader (xml, XmlNodeType.Document, null);
1026 document.Load (xvr);
1027 Assert.IsNotNull (document.DocumentType);
1028 Assert.AreEqual (1, document.DocumentType.Entities.Count);
1030 XmlEntity foo = document.DocumentType.Entities.GetNamedItem ("foo") as XmlEntity;
1031 Assert.IsNotNull (foo);
1032 Assert.IsNotNull (document.DocumentType.Entities.GetNamedItem ("foo", ""));
1033 Assert.AreEqual ("foo", foo.Name);
1034 Assert.IsNull (foo.Value);
1035 Assert.AreEqual ("foo-ent", foo.InnerText);
1039 public void DTDEntityAttributeHandling ()
1041 string dtd = "<!DOCTYPE root[<!ATTLIST root hoge CDATA 'hoge-def'><!ENTITY foo 'ent-foo'>]>";
1042 string xml = dtd + "<root>&foo;</root>";
1043 XmlValidatingReader xvr = new XmlValidatingReader (xml, XmlNodeType.Document,null);
1044 xvr.EntityHandling = EntityHandling.ExpandCharEntities;
1045 xvr.ValidationType = ValidationType.None;
1046 document.Load (xvr);
1047 // Don't include default attributes here.
1048 Assert.AreEqual (xml, document.OuterXml);
1049 Assert.AreEqual ("hoge-def", document.DocumentElement.GetAttribute ("hoge"));
1052 // [Test] Comment out in the meantime.
1053 // public void LoadExternalUri ()
1055 // // set any URL of well-formed XML.
1056 // document.Load ("http://www.go-mono.com/index.rss");
1059 // [Test] comment out in the meantime.
1060 // public void LoadDocumentWithIgnoreSection ()
1062 // // set any URL of well-formed XML.
1063 // document.Load ("xmlfiles/test.xml");
1067 [ExpectedException (typeof (XmlException))]
1068 public void LoadThrowsUndeclaredEntity ()
1070 string ent1 = "<!ENTITY ent 'entity string'>";
1071 string ent2 = "<!ENTITY ent2 '<foo/><foo/>'>]>";
1072 string dtd = "<!DOCTYPE root[<!ELEMENT root (#PCDATA|foo)*>" + ent1 + ent2;
1073 string xml = dtd + "<root>&ent3;&ent2;</root>";
1074 XmlTextReader xtr = new XmlTextReader (xml, XmlNodeType.Document, null);
1075 document.Load (xtr);
1080 public void CreateEntityReferencesWithoutDTD ()
1082 document.RemoveAll ();
1083 document.AppendChild (document.CreateElement ("root"));
1084 document.DocumentElement.AppendChild (document.CreateEntityReference ("foo"));
1088 public void LoadEntityReference ()
1090 string xml = "<!DOCTYPE root [<!ELEMENT root (#PCDATA)*><!ENTITY ent 'val'>]><root attr='a &ent; string'>&ent;</root>";
1091 XmlTextReader xtr = new XmlTextReader (xml, XmlNodeType.Document, null);
1092 XmlDocument doc = new XmlDocument ();
1094 Assert.AreEqual (XmlNodeType.EntityReference, doc.DocumentElement.FirstChild.NodeType, "#text node");
1095 Assert.AreEqual (XmlNodeType.EntityReference, doc.DocumentElement.Attributes [0].ChildNodes [1].NodeType, "#attribute");
1099 public void ReadNodeEmptyContent ()
1101 XmlTextReader xr = new XmlTextReader ("", XmlNodeType.Element, null);
1103 Console.WriteLine (xr.NodeType);
1104 XmlNode n = document.ReadNode (xr);
1109 public void ReadNodeWhitespace ()
1111 XmlTextReader xr = new XmlTextReader (" ", XmlNodeType.Element, null);
1113 Console.WriteLine (xr.NodeType);
1114 document.PreserveWhitespace = false; // Note this line.
1115 XmlNode n = document.ReadNode (xr);
1116 Assert.IsNotNull (n);
1117 Assert.AreEqual (XmlNodeType.Whitespace, n.NodeType);
1121 public void SavePreserveWhitespace ()
1123 string xml = "<root> <element>text\n</element></root>";
1124 XmlDocument doc = new XmlDocument ();
1125 doc.PreserveWhitespace = true;
1127 StringWriter sw = new StringWriter ();
1129 Assert.AreEqual ("<?xml version=\"1.0\" encoding=\"utf-16\"?>" + xml, sw.ToString ());
1131 doc.PreserveWhitespace = false;
1132 sw = new StringWriter ();
1134 string NEL = Environment.NewLine;
1135 Assert.AreEqual ("<?xml version=\"1.0\" encoding=\"utf-16\"?>"
1136 + NEL + "<root> <element>text"
1137 + "\n</element></root>",
1142 public void ReadNodeEntityReferenceFillsChildren ()
1144 string dtd = "<!DOCTYPE root [<!ELEMENT root (#PCDATA)*><!ENTITY ent 'val'>]>";
1146 string xml = dtd + "<root attr='a &ent; string'>&ent;</root>";
1147 XmlValidatingReader reader = new XmlValidatingReader (
1148 xml, XmlNodeType.Document, null);
1150 reader.EntityHandling = EntityHandling.ExpandCharEntities;
1151 reader.ValidationType = ValidationType.None;
1153 //skip the doctype delcaration
1157 XmlDocument doc = new XmlDocument ();
1161 doc.DocumentElement.FirstChild.ChildNodes.Count);
1165 public void LoadTreatsFixedAttributesAsIfItExisted ()
1167 string xml = @"<!DOCTYPE foo [<!ELEMENT foo EMPTY><!ATTLIST foo xmlns CDATA #FIXED 'urn:foo'>]><foo />";
1168 XmlDocument doc = new XmlDocument ();
1169 doc.Load (new StringReader (xml));
1170 Assert.AreEqual ("urn:foo", doc.DocumentElement.NamespaceURI);
1174 public void Bug79468 () // XmlNameEntryCache bug
1176 string xml = "<?xml version='1.0' encoding='UTF-8'?>"
1177 + "<ns0:DebtAmountRequest xmlns:ns0='http://whatever'>"
1178 + " <Signature xmlns='http://www.w3.org/2000/09/xmldsig#' />"
1179 + "</ns0:DebtAmountRequest>";
1180 XmlDocument doc = new XmlDocument ();
1182 XmlNodeList nodeList = doc.GetElementsByTagName ("Signature");
1185 class MyXmlDocument : XmlDocument
1187 public override XmlAttribute CreateAttribute (string p, string l, string n)
1189 return base.CreateAttribute (p, "hijacked", n);
1194 public void UseOverridenCreateAttribute ()
1196 XmlDocument doc = new MyXmlDocument ();
1197 doc.LoadXml ("<root a='sane' />");
1198 Assert.IsNotNull (doc.DocumentElement.GetAttributeNode ("hijacked"));
1199 Assert.IsNull (doc.DocumentElement.GetAttributeNode ("a"));