2003-02-09 Piers Haken <piersh@friskit.com>
[mono.git] / mcs / class / System.XML / Test / XmlDocumentTests.cs
1
2 // System.Xml.XmlDocumentTests
3 //
4 // Authors:
5 //   Jason Diamond <jason@injektilo.org>
6 //   Kral Ferch <kral_ferch@hotmail.com>
7 //
8 // (C) 2002 Jason Diamond, Kral Ferch
9 //
10
11 using System;
12 using System.Collections;
13 using System.Xml;
14 using System.IO;
15 using System.Text;
16
17 using NUnit.Framework;
18
19 namespace MonoTests.System.Xml
20 {
21         public class XmlDocumentTests : TestCase
22         {
23                 public XmlDocumentTests () : base ("MonoTests.System.Xml.XmlDocumentTests testsuite") {}
24                 public XmlDocumentTests (string name) : base (name) {}
25
26                 private XmlDocument document;
27                 private ArrayList eventStrings = new ArrayList();
28
29                 // These Event* methods support the TestEventNode* Tests in this file.
30                 // Most of them are event handlers for the XmlNodeChangedEventHandler
31                 // delegate.
32                 private void EventStringAdd(string eventName, XmlNodeChangedEventArgs e)
33                 {
34                         string oldParent = (e.OldParent != null) ? e.OldParent.Name : "<none>";
35                         string newParent = (e.NewParent != null) ? e.NewParent.Name : "<none>";
36                         eventStrings.Add (String.Format ("{0}, {1}, {2}, {3}, {4}", eventName, e.Action.ToString (), e.Node.OuterXml, oldParent, newParent));
37                 }
38
39                 private void EventNodeChanged(Object sender, XmlNodeChangedEventArgs e)
40                 {
41                         EventStringAdd ("NodeChanged", e);
42                 }
43
44                 private void EventNodeChanging (Object sender, XmlNodeChangedEventArgs e)
45                 {
46                         EventStringAdd ("NodeChanging", e);
47                 }
48
49                 private void EventNodeChangingException (Object sender, XmlNodeChangedEventArgs e)
50                 {
51                         throw new Exception ("don't change the value.");
52                 }
53
54                 private void EventNodeInserted(Object sender, XmlNodeChangedEventArgs e)
55                 {
56                         EventStringAdd ("NodeInserted", e);
57                 }
58
59                 private void EventNodeInserting(Object sender, XmlNodeChangedEventArgs e)
60                 {
61                         EventStringAdd ("NodeInserting", e);
62                 }
63
64                 private void EventNodeInsertingException(Object sender, XmlNodeChangedEventArgs e)
65                 {
66                         throw new Exception ("don't insert the element.");
67                 }
68
69                 private void EventNodeRemoved(Object sender, XmlNodeChangedEventArgs e)
70                 {
71                         EventStringAdd ("NodeRemoved", e);
72                 }
73
74                 private void EventNodeRemoving(Object sender, XmlNodeChangedEventArgs e)
75                 {
76                         EventStringAdd ("NodeRemoving", e);
77                 }
78
79                 private void EventNodeRemovingException(Object sender, XmlNodeChangedEventArgs e)
80                 {
81                         throw new Exception ("don't remove the element.");
82                 }
83
84                 protected override void SetUp ()
85                 {
86                         document = new XmlDocument ();
87                         document.PreserveWhitespace = true;
88                 }
89
90                 public void TestCreateNodeNodeTypeNameEmptyParams ()
91                 {
92                         XmlNode node;
93
94                         try {
95                                 node = document.CreateNode (null, null, null);
96                                 Fail ("Expected an ArgumentException to be thrown.");
97                         } catch (ArgumentException) {}
98
99                         try {
100                                 node = document.CreateNode ("attribute", null, null);
101                                 Fail ("Expected a NullReferenceException to be thrown.");
102                         } catch (NullReferenceException) {}
103
104                         try {
105                                 node = document.CreateNode ("attribute", "", null);
106                                 Fail ("Expected an ArgumentException to be thrown.");
107                         } catch (ArgumentException) {}
108
109                         try {
110                                 node = document.CreateNode ("element", null, null);
111                                 Fail ("Expected a NullReferenceException to be thrown.");
112                         } catch (NullReferenceException) {}
113
114                         try {
115                                 node = document.CreateNode ("element", "", null);
116                                 Fail ("Expected an ArgumentException to be thrown.");
117                         } catch (ArgumentException) {}
118
119                         try {
120                                 node = document.CreateNode ("entityreference", null, null);
121                                 Fail ("Expected a NullReferenceException to be thrown.");
122                         } catch (NullReferenceException) {}
123                 }
124
125                 public void TestCreateNodeInvalidXmlNodeType ()
126                 {
127                         XmlNode node;
128
129                         try {
130                                 node = document.CreateNode (XmlNodeType.EndElement, null, null);
131                                 Fail ("Expected an ArgumentOutOfRangeException to be thrown.");
132                         } catch (ArgumentOutOfRangeException) {}
133
134                         try {
135                                 node = document.CreateNode (XmlNodeType.EndEntity, null, null);
136                                 Fail ("Expected an ArgumentOutOfRangeException to be thrown.");
137                         } catch (ArgumentOutOfRangeException) {}
138
139                         try {
140                                 node = document.CreateNode (XmlNodeType.Entity, null, null);
141                                 Fail ("Expected an ArgumentOutOfRangeException to be thrown.");
142                         } catch (ArgumentOutOfRangeException) {}
143
144                         try {
145                                 node = document.CreateNode (XmlNodeType.None, null, null);
146                                 Fail ("Expected an ArgumentOutOfRangeException to be thrown.");
147                         } catch (ArgumentOutOfRangeException) {}
148
149                         try {
150                                 node = document.CreateNode (XmlNodeType.Notation, null, null);
151                                 Fail ("Expected an ArgumentOutOfRangeException to be thrown.");
152                         } catch (ArgumentOutOfRangeException) {}
153
154                         // TODO:  undocumented allowable type.
155                         node = document.CreateNode (XmlNodeType.XmlDeclaration, null, null);
156                         AssertEquals (XmlNodeType.XmlDeclaration, node.NodeType);
157                 }
158
159                 public void TestCreateNodeWhichParamIsUsed ()
160                 {
161                         XmlNode node;
162
163                         // No constructor params for Document, DocumentFragment.
164
165                         node = document.CreateNode (XmlNodeType.CDATA, "a", "b", "c");
166                         AssertEquals (String.Empty, ((XmlCDataSection)node).Value);
167
168                         node = document.CreateNode (XmlNodeType.Comment, "a", "b", "c");
169                         AssertEquals (String.Empty, ((XmlComment)node).Value);
170
171                         node = document.CreateNode (XmlNodeType.DocumentType, "a", "b", "c");
172                         AssertNull (((XmlDocumentType)node).Value);
173
174 // TODO: add this back in to test when it's implemented.
175 //                      node = document.CreateNode (XmlNodeType.EntityReference, "a", "b", "c");
176 //                      AssertNull (((XmlEntityReference)node).Value);
177
178                         node = document.CreateNode (XmlNodeType.ProcessingInstruction, "a", "b", "c");
179                         AssertEquals (String.Empty, ((XmlProcessingInstruction)node).Value);
180
181                         node = document.CreateNode (XmlNodeType.SignificantWhitespace, "a", "b", "c");
182                         AssertEquals (String.Empty, ((XmlSignificantWhitespace)node).Value);
183
184                         node = document.CreateNode (XmlNodeType.Text, "a", "b", "c");
185                         AssertEquals (String.Empty, ((XmlText)node).Value);
186
187                         node = document.CreateNode (XmlNodeType.Whitespace, "a", "b", "c");
188                         AssertEquals (String.Empty, ((XmlWhitespace)node).Value);
189
190                         node = document.CreateNode (XmlNodeType.XmlDeclaration, "a", "b", "c");
191                         AssertEquals ("version=\"1.0\"", ((XmlDeclaration)node).Value);
192                 }
193
194                 public void TestCreateNodeNodeTypeName ()
195                 {
196                         XmlNode node;
197
198                         try {
199                                 node = document.CreateNode ("foo", null, null);
200                                 Fail ("Expected an ArgumentException to be thrown.");
201                         } catch (ArgumentException) {}
202
203                         node = document.CreateNode("attribute", "foo", null);
204                         AssertEquals (XmlNodeType.Attribute, node.NodeType);
205
206                         node = document.CreateNode("cdatasection", null, null);
207                         AssertEquals (XmlNodeType.CDATA, node.NodeType);
208
209                         node = document.CreateNode("comment", null, null);
210                         AssertEquals (XmlNodeType.Comment, node.NodeType);
211
212                         node = document.CreateNode("document", null, null);
213                         AssertEquals (XmlNodeType.Document, node.NodeType);
214                         // TODO: test which constructor this ended up calling,
215                         // i.e. reuse underlying NameTable or not?
216
217 // TODO: add this back in to test when it's implemented.
218 //                      node = document.CreateNode("documentfragment", null, null);
219 //                      AssertEquals (XmlNodeType.DocumentFragment, node.NodeType);
220
221                         node = document.CreateNode("documenttype", null, null);
222                         AssertEquals (XmlNodeType.DocumentType, node.NodeType);
223
224                         node = document.CreateNode("element", "foo", null);
225                         AssertEquals (XmlNodeType.Element, node.NodeType);
226
227 // TODO: add this back in to test when it's implemented.
228 //                      node = document.CreateNode("entityreference", "foo", null);
229 //                      AssertEquals (XmlNodeType.EntityReference, node.NodeType);
230
231                         node = document.CreateNode("processinginstruction", null, null);
232                         AssertEquals (XmlNodeType.ProcessingInstruction, node.NodeType);
233
234                         node = document.CreateNode("significantwhitespace", null, null);
235                         AssertEquals (XmlNodeType.SignificantWhitespace, node.NodeType);
236
237                         node = document.CreateNode("text", null, null);
238                         AssertEquals (XmlNodeType.Text, node.NodeType);
239
240                         node = document.CreateNode("whitespace", null, null);
241                         AssertEquals (XmlNodeType.Whitespace, node.NodeType);
242                 }
243
244                 public void TestDocumentElement ()
245                 {
246                         AssertNull (document.DocumentElement);
247                         XmlElement element = document.CreateElement ("foo", "bar", "http://foo/");
248                         AssertNotNull (element);
249
250                         AssertEquals ("foo", element.Prefix);
251                         AssertEquals ("bar", element.LocalName);
252                         AssertEquals ("http://foo/", element.NamespaceURI);
253
254                         AssertEquals ("foo:bar", element.Name);
255
256                         AssertSame (element, document.AppendChild (element));
257
258                         AssertSame (element, document.DocumentElement);
259                 }
260
261                 public void TestDocumentEmpty()
262                 {
263                         AssertEquals ("Incorrect output for empty document.", "", document.OuterXml);
264                 }
265
266                 public void TestEventNodeChanged()
267                 {
268                         XmlElement element;
269                         XmlComment comment;
270
271                         document.NodeChanged += new XmlNodeChangedEventHandler (this.EventNodeChanged);
272
273                         // Node that is part of the document.
274                         document.AppendChild (document.CreateElement ("foo"));
275                         comment = document.CreateComment ("bar");
276                         document.DocumentElement.AppendChild (comment);
277                         AssertEquals ("<!--bar-->", document.DocumentElement.InnerXml);
278                         comment.Value = "baz";
279                         Assert (eventStrings.Contains ("NodeChanged, Change, <!--baz-->, foo, foo"));
280                         AssertEquals ("<!--baz-->", document.DocumentElement.InnerXml);
281
282                         // Node that isn't part of the document but created by the document.
283                         element = document.CreateElement ("foo");
284                         comment = document.CreateComment ("bar");
285                         element.AppendChild (comment);
286                         AssertEquals ("<!--bar-->", element.InnerXml);
287                         comment.Value = "baz";
288                         Assert (eventStrings.Contains ("NodeChanged, Change, <!--baz-->, foo, foo"));
289                         AssertEquals ("<!--baz-->", element.InnerXml);
290
291 /*
292  TODO:  Insert this when XmlNode.InnerText() and XmlNode.InnerXml() have been implemented.
293  
294                         // Node that is part of the document.
295                         element = document.CreateElement ("foo");
296                         element.InnerText = "bar";
297                         document.AppendChild(element);
298                         element.InnerText = "baz";
299                         Assert(eventStrings.Contains("NodeChanged, Change, baz, foo, foo"));
300                         
301                         // Node that isn't part of the document but created by the document.
302                         element = document.CreateElement("qux");
303                         element.InnerText = "quux";
304                         element.InnerText = "quuux";
305                         Assert(eventStrings.Contains("NodeChanged, Change, quuux, qux, qux"));
306 */
307                 }
308
309                 public void TestEventNodeChanging()
310                 {
311                         XmlElement element;
312                         XmlComment comment;
313
314                         document.NodeChanging += new XmlNodeChangedEventHandler (this.EventNodeChanging);
315
316                         // Node that is part of the document.
317                         document.AppendChild (document.CreateElement ("foo"));
318                         comment = document.CreateComment ("bar");
319                         document.DocumentElement.AppendChild (comment);
320                         AssertEquals ("<!--bar-->", document.DocumentElement.InnerXml);
321                         comment.Value = "baz";
322                         Assert (eventStrings.Contains ("NodeChanging, Change, <!--bar-->, foo, foo"));
323                         AssertEquals ("<!--baz-->", document.DocumentElement.InnerXml);
324
325                         // Node that isn't part of the document but created by the document.
326                         element = document.CreateElement ("foo");
327                         comment = document.CreateComment ("bar");
328                         element.AppendChild (comment);
329                         AssertEquals ("<!--bar-->", element.InnerXml);
330                         comment.Value = "baz";
331                         Assert (eventStrings.Contains ("NodeChanging, Change, <!--bar-->, foo, foo"));
332                         AssertEquals ("<!--baz-->", element.InnerXml);
333
334                         // If an exception is thrown the Document returns to original state.
335                         document.NodeChanging += new XmlNodeChangedEventHandler (this.EventNodeChangingException);
336                         element = document.CreateElement("foo");
337                         comment = document.CreateComment ("bar");
338                         element.AppendChild (comment);
339                         AssertEquals ("<!--bar-->", element.InnerXml);
340                         try 
341                         {
342                                 comment.Value = "baz";
343                                 Fail("Expected an exception to be thrown by the NodeChanging event handler method EventNodeChangingException().");
344                         } catch (Exception) {}
345                         AssertEquals ("<!--bar-->", element.InnerXml);
346
347                         // Yes it's a bit anal but this tests whether the node changing event exception fires before the
348                         // ArgumentOutOfRangeException.  Turns out it does so that means our implementation needs to raise
349                         // the node changing event before doing any work.
350                         try 
351                         {
352                                 comment.ReplaceData(-1, 0, "qux");
353                                 Fail("Expected an ArgumentOutOfRangeException to be thrown.");
354                         } 
355                         catch (Exception) {}
356
357                         /*
358  TODO:  Insert this when XmlNode.InnerText() and XmlNode.InnerXml() have been implemented.
359  
360                         // Node that is part of the document.
361                         element = document.CreateElement ("foo");
362                         element.InnerText = "bar";
363                         document.AppendChild(element);
364                         element.InnerText = "baz";
365                         Assert(eventStrings.Contains("NodeChanging, Change, bar, foo, foo"));
366
367                         // Node that isn't part of the document but created by the document.
368                         element = document.CreateElement("foo");
369                         element.InnerText = "bar";
370                         element.InnerText = "baz";
371                         Assert(eventStrings.Contains("NodeChanging, Change, bar, foo, foo"));
372
373                         // If an exception is thrown the Document returns to original state.
374                         document.NodeChanging += new XmlNodeChangedEventHandler (this.EventNodeChangingException);
375                         element = document.CreateElement("foo");
376                         element.InnerText = "bar";
377                         try {
378                                 element.InnerText = "baz";
379                                 Fail("Expected an exception to be thrown by the NodeChanging event handler method EventNodeChangingException().");
380                         } catch (Exception) {}
381                         AssertEquals("bar", element.InnerText);
382 */
383                 }
384
385                 public void TestEventNodeInserted()
386                 {
387                         XmlElement element;
388
389                         document.NodeInserted += new XmlNodeChangedEventHandler (this.EventNodeInserted);
390
391                         // Inserted 'foo' element to the document.
392                         element = document.CreateElement ("foo");
393                         document.AppendChild (element);
394                         Assert (eventStrings.Contains ("NodeInserted, Insert, <foo />, <none>, #document"));
395
396                         // Append child on node in document
397                         element = document.CreateElement ("foo");
398                         document.DocumentElement.AppendChild (element);
399                         Assert (eventStrings.Contains ("NodeInserted, Insert, <foo />, <none>, foo"));
400
401                         // Append child on node not in document but created by document
402                         element = document.CreateElement ("bar");
403                         element.AppendChild(document.CreateElement ("bar"));
404                         Assert(eventStrings.Contains("NodeInserted, Insert, <bar />, <none>, bar"));
405                 }
406
407                 public void TestEventNodeInserting()
408                 {
409                         XmlElement element;
410
411                         document.NodeInserting += new XmlNodeChangedEventHandler (this.EventNodeInserting);
412
413                         // Inserting 'foo' element to the document.
414                         element = document.CreateElement ("foo");
415                         document.AppendChild (element);
416                         Assert (eventStrings.Contains ("NodeInserting, Insert, <foo />, <none>, #document"));
417
418                         // Append child on node in document
419                         element = document.CreateElement ("foo");
420                         document.DocumentElement.AppendChild (element);
421                         Assert(eventStrings.Contains ("NodeInserting, Insert, <foo />, <none>, foo"));
422
423                         // Append child on node not in document but created by document
424                         element = document.CreateElement ("bar");
425                         AssertEquals (0, element.ChildNodes.Count);
426                         element.AppendChild (document.CreateElement ("bar"));
427                         Assert (eventStrings.Contains ("NodeInserting, Insert, <bar />, <none>, bar"));
428                         AssertEquals (1, element.ChildNodes.Count);
429
430                         // If an exception is thrown the Document returns to original state.
431                         document.NodeInserting += new XmlNodeChangedEventHandler (this.EventNodeInsertingException);
432                         AssertEquals (1, element.ChildNodes.Count);
433                         try 
434                         {
435                                 element.AppendChild (document.CreateElement("baz"));
436                                 Fail ("Expected an exception to be thrown by the NodeInserting event handler method EventNodeInsertingException().");
437                         } 
438                         catch (Exception) {}
439                         AssertEquals (1, element.ChildNodes.Count);
440                 }
441
442                 public void TestEventNodeRemoved()
443                 {
444                         XmlElement element;
445                         XmlElement element2;
446
447                         document.NodeRemoved += new XmlNodeChangedEventHandler (this.EventNodeRemoved);
448
449                         // Removed 'bar' element from 'foo' outside document.
450                         element = document.CreateElement ("foo");
451                         element2 = document.CreateElement ("bar");
452                         element.AppendChild (element2);
453                         AssertEquals (1, element.ChildNodes.Count);
454                         element.RemoveChild (element2);
455                         Assert (eventStrings.Contains ("NodeRemoved, Remove, <bar />, foo, <none>"));
456                         AssertEquals (0, element.ChildNodes.Count);
457
458 /*
459  * TODO:  put this test back in when AttributeCollection.RemoveAll() is implemented.
460
461                         // RemoveAll.
462                         element = document.CreateElement ("foo");
463                         element2 = document.CreateElement ("bar");
464                         element.AppendChild(element2);
465                         AssertEquals(1, element.ChildNodes.Count);
466                         element.RemoveAll();
467                         Assert (eventStrings.Contains ("NodeRemoved, Remove, <bar />, foo, <none>"));
468                         AssertEquals(0, element.ChildNodes.Count);
469 */
470
471                         // Removed 'bar' element from 'foo' inside document.
472                         element = document.CreateElement ("foo");
473                         document.AppendChild (element);
474                         element = document.CreateElement ("bar");
475                         document.DocumentElement.AppendChild (element);
476                         AssertEquals (1, document.DocumentElement.ChildNodes.Count);
477                         document.DocumentElement.RemoveChild (element);
478                         Assert (eventStrings.Contains ("NodeRemoved, Remove, <bar />, foo, <none>"));
479                         AssertEquals (0, document.DocumentElement.ChildNodes.Count);
480                 }
481         
482                 public void TestEventNodeRemoving()
483                 {
484                         XmlElement element;
485                         XmlElement element2;
486
487                         document.NodeRemoving += new XmlNodeChangedEventHandler (this.EventNodeRemoving);
488
489                         // Removing 'bar' element from 'foo' outside document.
490                         element = document.CreateElement ("foo");
491                         element2 = document.CreateElement ("bar");
492                         element.AppendChild (element2);
493                         AssertEquals (1, element.ChildNodes.Count);
494                         element.RemoveChild (element2);
495                         Assert (eventStrings.Contains ("NodeRemoving, Remove, <bar />, foo, <none>"));
496                         AssertEquals (0, element.ChildNodes.Count);
497
498 /*
499  * TODO:  put this test back in when AttributeCollection.RemoveAll() is implemented.
500
501                         // RemoveAll.
502                         element = document.CreateElement ("foo");
503                         element2 = document.CreateElement ("bar");
504                         element.AppendChild(element2);
505                         AssertEquals(1, element.ChildNodes.Count);
506                         element.RemoveAll();
507                         Assert (eventStrings.Contains ("NodeRemoving, Remove, <bar />, foo, <none>"));
508                         AssertEquals(0, element.ChildNodes.Count);
509 */
510
511                         // Removing 'bar' element from 'foo' inside document.
512                         element = document.CreateElement ("foo");
513                         document.AppendChild (element);
514                         element = document.CreateElement ("bar");
515                         document.DocumentElement.AppendChild (element);
516                         AssertEquals (1, document.DocumentElement.ChildNodes.Count);
517                         document.DocumentElement.RemoveChild (element);
518                         Assert (eventStrings.Contains ("NodeRemoving, Remove, <bar />, foo, <none>"));
519                         AssertEquals (0, document.DocumentElement.ChildNodes.Count);
520
521                         // If an exception is thrown the Document returns to original state.
522                         document.NodeRemoving += new XmlNodeChangedEventHandler (this.EventNodeRemovingException);
523                         element.AppendChild (element2);
524                         AssertEquals (1, element.ChildNodes.Count);
525                         try 
526                         {
527                                 element.RemoveChild(element2);
528                                 Fail ("Expected an exception to be thrown by the NodeRemoving event handler method EventNodeRemovingException().");
529                         } 
530                         catch (Exception) {}
531                         AssertEquals (1, element.ChildNodes.Count);
532                 }
533
534                 public void TestGetElementsByTagNameNoNameSpace ()
535                 {
536                         string xml = @"<library><book><title>XML Fun</title><author>John Doe</author>
537                                 <price>34.95</price></book><book><title>Bear and the Dragon</title>
538                                 <author>Tom Clancy</author><price>6.95</price></book><book>
539                                 <title>Bourne Identity</title><author>Robert Ludlum</author>
540                                 <price>9.95</price></book><Fluffer><Nutter><book>
541                                 <title>Bourne Ultimatum</title><author>Robert Ludlum</author>
542                                 <price>9.95</price></book></Nutter></Fluffer></library>";
543
544                         MemoryStream memoryStream = new MemoryStream (Encoding.UTF8.GetBytes (xml));
545                         document = new XmlDocument ();
546                         document.Load (memoryStream);
547                         XmlNodeList bookList = document.GetElementsByTagName ("book");
548                         AssertEquals ("GetElementsByTagName (string) returned incorrect count.", 4, bookList.Count);
549                 }
550
551                 public void TestGetElementsByTagNameUsingNameSpace ()
552                 {
553                         StringBuilder xml = new StringBuilder ();
554                         xml.Append ("<?xml version=\"1.0\" ?><library xmlns:North=\"http://www.foo.com\" ");
555                         xml.Append ("xmlns:South=\"http://www.goo.com\"><North:book type=\"non-fiction\"> ");
556                         xml.Append ("<North:title type=\"intro\">XML Fun</North:title> " );
557                         xml.Append ("<North:author>John Doe</North:author> " );
558                         xml.Append ("<North:price>34.95</North:price></North:book> " );
559                         xml.Append ("<South:book type=\"fiction\"> " );
560                         xml.Append ("<South:title>Bear and the Dragon</South:title> " );
561                         xml.Append ("<South:author>Tom Clancy</South:author> " );
562                         xml.Append ("<South:price>6.95</South:price></South:book> " );
563                         xml.Append ("<South:book type=\"fiction\"><South:title>Bourne Identity</South:title> " );
564                         xml.Append ("<South:author>Robert Ludlum</South:author> " );
565                         xml.Append ("<South:price>9.95</South:price></South:book></library>");
566
567                         MemoryStream memoryStream = new MemoryStream (Encoding.UTF8.GetBytes (xml.ToString ()));
568                         document = new XmlDocument ();
569                         document.Load (memoryStream);
570                         XmlNodeList bookList = document.GetElementsByTagName ("book", "http://www.goo.com");
571                         AssertEquals ("GetElementsByTagName (string, uri) returned incorrect count.", 2, bookList.Count);
572                 }
573
574         
575                 public void TestInnerAndOuterXml ()
576                 {
577                         AssertEquals (String.Empty, document.InnerXml);
578                         AssertEquals (document.InnerXml, document.OuterXml);
579
580                         XmlDeclaration declaration = document.CreateXmlDeclaration ("1.0", null, null);
581                         document.AppendChild (declaration);
582                         AssertEquals ("<?xml version=\"1.0\"?>", document.InnerXml);
583                         AssertEquals (document.InnerXml, document.OuterXml);
584
585                         XmlElement element = document.CreateElement ("foo");
586                         document.AppendChild (element);
587                         AssertEquals ("<?xml version=\"1.0\"?><foo />", document.InnerXml);
588                         AssertEquals (document.InnerXml, document.OuterXml);
589
590                         XmlComment comment = document.CreateComment ("bar");
591                         document.DocumentElement.AppendChild (comment);
592                         AssertEquals ("<?xml version=\"1.0\"?><foo><!--bar--></foo>", document.InnerXml);
593                         AssertEquals (document.InnerXml, document.OuterXml);
594
595                         XmlText text = document.CreateTextNode ("baz");
596                         document.DocumentElement.AppendChild (text);
597                         AssertEquals ("<?xml version=\"1.0\"?><foo><!--bar-->baz</foo>", document.InnerXml);
598                         AssertEquals (document.InnerXml, document.OuterXml);
599
600                         element = document.CreateElement ("quux");
601                         element.SetAttribute ("quuux", "squonk");
602                         document.DocumentElement.AppendChild (element);
603                         AssertEquals ("<?xml version=\"1.0\"?><foo><!--bar-->baz<quux quuux=\"squonk\" /></foo>", document.InnerXml);
604                         AssertEquals (document.InnerXml, document.OuterXml);
605                 }
606
607                 public void TestLoadWithSystemIOStream ()
608                 {                       
609                         string xml = @"<library><book><title>XML Fun</title><author>John Doe</author>
610                                 <price>34.95</price></book><book><title>Bear and the Dragon</title>
611                                 <author>Tom Clancy</author><price>6.95</price></book><book>
612                                 <title>Bourne Identity</title><author>Robert Ludlum</author>
613                                 <price>9.95</price></book><Fluffer><Nutter><book>
614                                 <title>Bourne Ultimatum</title><author>Robert Ludlum</author>
615                                 <price>9.95</price></book></Nutter></Fluffer></library>";
616
617                         MemoryStream memoryStream = new MemoryStream (Encoding.UTF8.GetBytes (xml));
618                         document = new XmlDocument ();
619                         document.Load (memoryStream);
620                         AssertEquals ("Not Loaded From IOStream", true, document.HasChildNodes);
621                 }
622
623                 public void TestLoadXmlCDATA ()
624                 {
625                         document.LoadXml ("<foo><![CDATA[bar]]></foo>");
626                         Assert (document.DocumentElement.FirstChild.NodeType == XmlNodeType.CDATA);
627                         AssertEquals ("bar", document.DocumentElement.FirstChild.Value);
628                 }
629
630                 public void TestLoadXMLComment()
631                 {
632 // XmlTextReader needs to throw this exception
633 //                      try {
634 //                              document.LoadXml("<!--foo-->");
635 //                              Fail("XmlException should have been thrown.");
636 //                      }
637 //                      catch (XmlException e) {
638 //                              AssertEquals("Exception message doesn't match.", "The root element is missing.", e.Message);
639 //                      }
640
641                         document.LoadXml ("<foo><!--Comment--></foo>");
642                         Assert (document.DocumentElement.FirstChild.NodeType == XmlNodeType.Comment);
643                         AssertEquals ("Comment", document.DocumentElement.FirstChild.Value);
644
645                         document.LoadXml (@"<foo><!--bar--></foo>");
646                         AssertEquals ("Incorrect target.", "bar", ((XmlComment)document.FirstChild.FirstChild).Data);
647                 }
648
649                 public void TestLoadXmlElementSingle ()
650                 {
651                         AssertNull (document.DocumentElement);
652                         document.LoadXml ("<foo/>");
653
654                         AssertNotNull (document.DocumentElement);
655                         AssertSame (document.FirstChild, document.DocumentElement);
656
657                         AssertEquals (String.Empty, document.DocumentElement.Prefix);
658                         AssertEquals ("foo", document.DocumentElement.LocalName);
659                         AssertEquals (String.Empty, document.DocumentElement.NamespaceURI);
660                         AssertEquals ("foo", document.DocumentElement.Name);
661                 }
662
663                 public void TestLoadXmlElementWithAttributes ()
664                 {
665                         AssertNull (document.DocumentElement);
666                         document.LoadXml ("<foo bar='baz' quux='quuux' hoge='hello &amp; world' />");
667
668                         XmlElement documentElement = document.DocumentElement;
669
670                         AssertEquals ("baz", documentElement.GetAttribute ("bar"));
671                         AssertEquals ("quuux", documentElement.GetAttribute ("quux"));
672                         AssertEquals ("hello & world", documentElement.GetAttribute ("hoge"));
673                         AssertEquals ("hello & world", documentElement.Attributes ["hoge"].Value);
674                         AssertEquals (1, documentElement.GetAttributeNode ("hoge").ChildNodes.Count);
675                 }
676
677                 public void TestLoadXmlElementWithChildElement ()
678                 {
679                         document.LoadXml ("<foo><bar/></foo>");
680                         Assert (document.ChildNodes.Count == 1);
681                         Assert (document.FirstChild.ChildNodes.Count == 1);
682                         AssertEquals ("foo", document.DocumentElement.LocalName);
683                         AssertEquals ("bar", document.DocumentElement.FirstChild.LocalName);
684                 }
685
686                 public void TestLoadXmlElementWithTextNode ()
687                 {
688                         document.LoadXml ("<foo>bar</foo>");
689                         Assert (document.DocumentElement.FirstChild.NodeType == XmlNodeType.Text);
690                         AssertEquals ("bar", document.DocumentElement.FirstChild.Value);
691                 }
692
693                 public void TestLoadXmlExceptionClearsDocument ()
694                 {
695                         document.LoadXml ("<foo/>");
696                         Assert (document.FirstChild != null);
697                         
698                         try {
699                                 document.LoadXml ("<123/>");
700                                 Fail ("An XmlException should have been thrown.");
701                         } catch (XmlException) {}
702
703                         Assert (document.FirstChild == null);
704                 }
705
706                 public void TestLoadXmlProcessingInstruction ()
707                 {
708                         document.LoadXml (@"<?foo bar='baaz' quux='quuux'?><quuuux></quuuux>");
709                         AssertEquals ("Incorrect target.", "foo", ((XmlProcessingInstruction)document.FirstChild).Target);
710                         AssertEquals ("Incorrect data.", "bar='baaz' quux='quuux'", ((XmlProcessingInstruction)document.FirstChild).Data);
711                 }
712
713                 public void TestOuterXml ()
714                 {
715                         string xml;
716                         
717                         xml = "<root><![CDATA[foo]]></root>";
718                         document.LoadXml (xml);
719                         AssertEquals("XmlDocument with cdata OuterXml is incorrect.", xml, document.OuterXml);
720
721                         xml = "<root><!--foo--></root>";
722                         document.LoadXml (xml);
723                         AssertEquals("XmlDocument with comment OuterXml is incorrect.", xml, document.OuterXml);
724
725                         xml = "<root><?foo bar?></root>";
726                         document.LoadXml (xml);
727                         AssertEquals("XmlDocument with processing instruction OuterXml is incorrect.", xml, document.OuterXml);
728                 }
729
730                 public void TestParentNodes ()
731                 {
732                         document.LoadXml ("<foo><bar><baz/></bar></foo>");
733                         XmlNode node = document.FirstChild.FirstChild.FirstChild;
734                         AssertEquals ("Wrong child found.", "baz", node.LocalName);
735                         AssertEquals ("Wrong parent.", "bar", node.ParentNode.LocalName);
736                         AssertEquals ("Wrong parent.", "foo", node.ParentNode.ParentNode.LocalName);
737                         AssertEquals ("Wrong parent.", "#document", node.ParentNode.ParentNode.ParentNode.LocalName);
738                         AssertNull ("Expected parent to be null.", node.ParentNode.ParentNode.ParentNode.ParentNode);
739                 }
740
741                 public void TestRemovedElementNextSibling ()
742                 {
743                         XmlNode node;
744                         XmlNode nextSibling;
745
746                         document.LoadXml ("<foo><child1/><child2/></foo>");
747                         node = document.DocumentElement.FirstChild;
748                         document.DocumentElement.RemoveChild (node);
749                         nextSibling = node.NextSibling;
750                         AssertNull ("Expected removed node's next sibling to be null.", nextSibling);
751                 }
752
753                 // ImportNode
754                 public void TestImportNode ()
755                 {
756                         XmlNode n;
757
758                         string xlinkURI = "http://www.w3.org/1999/XLink";
759                         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>";
760                         document.LoadXml(xml1);
761                         XmlDocument newDoc = new XmlDocument();
762                         newDoc.LoadXml("<hoge><fuga /></hoge>");
763                         XmlElement bar = document.DocumentElement.FirstChild as XmlElement;
764
765                         // Attribute
766                         n = newDoc.ImportNode(bar.GetAttributeNode("href", xlinkURI), true);
767                         AssertEquals("#ImportNode.Attr.NS.LocalName", "href", n.LocalName);
768                         AssertEquals("#ImportNode.Attr.NS.NSURI", xlinkURI, n.NamespaceURI);
769                         AssertEquals("#ImportNode.Attr.NS.Value", "#foo", n.Value);
770
771                         // CDATA
772                         n = newDoc.ImportNode(bar.FirstChild.FirstChild, true);
773                         AssertEquals("#ImportNode.CDATA", "cdata section.\n\titem 1\n\titem 2\n", n.Value);
774
775                         // Element
776                         XmlElement e = newDoc.ImportNode(bar, true) as XmlElement;
777                         AssertEquals("#ImportNode.Element.Name", "bar", e.Name);
778                         AssertEquals("#ImportNode.Element.Attr", "#foo", e.GetAttribute("href", xlinkURI));
779                         AssertEquals("#ImportNode.Element.deep", "baz", e.FirstChild.Name);
780
781                         // Entity Reference:
782                         //   [2002/10/14] CreateEntityReference was not implemented.
783 //                      document.LoadXml("<!DOCTYPE test PUBLIC 'dummy' [<!ENTITY FOOENT 'foo'>]><root>&FOOENT;</root>");
784 //                      n = newDoc.ImportNode(document.DocumentElement.FirstChild);
785 //                      AssertEquals("#ImportNode.EntityReference", "FOOENT", n.Name);
786 //                      AssertEquals("#ImportNode.EntityReference", "foo_", n.Value);
787
788                         // Processing Instruction
789                         document.LoadXml("<foo><?xml-stylesheet href='foo.xsl' ?></foo>");
790                         XmlProcessingInstruction pi = (XmlProcessingInstruction)newDoc.ImportNode(document.DocumentElement.FirstChild, false);
791                         AssertEquals("#ImportNode.ProcessingInstruction.Name", "xml-stylesheet", pi.Name);
792                         AssertEquals("#ImportNode.ProcessingInstruction.Data", "href='foo.xsl'", pi.Data.Trim());
793                         
794                         // Text
795                         document.LoadXml(xml1);
796                         n = newDoc.ImportNode((XmlText)bar.FirstChild.ChildNodes[1], true);
797                         AssertEquals("#ImportNode.Text", "From here, simple text node.", n.Value);
798
799                         // XmlDeclaration
800                         document.LoadXml(xml1);
801                         XmlDeclaration decl = (XmlDeclaration)newDoc.ImportNode(document.FirstChild, false);
802                         AssertEquals("#ImportNode.XmlDeclaration.Type", XmlNodeType.XmlDeclaration, decl.NodeType);
803                         AssertEquals("#ImportNode.XmlDeclaration.Encoding", "utf-8", decl.Encoding);
804                 }
805
806                 public void TestNameTable()
807                 {
808                         XmlDocument doc = new XmlDocument();
809                         AssertNotNull(doc.NameTable);
810                 }
811
812                 public void TestSingleEmptyRootDocument()
813                 {
814                         XmlDocument doc = new XmlDocument();
815                         doc.LoadXml("<root />");
816                         AssertNotNull(doc.DocumentElement);
817                 }
818
819                 public void TestDocumentWithDoctypeDecl ()
820                 {
821                         XmlDocument doc = new XmlDocument ();
822                         try {
823                                 doc.LoadXml ("<!DOCTYPE test><root />");
824                         } catch (XmlException) {
825                                 Fail ("#DoctypeDecl.OnlyName");
826                         }
827                         try 
828                         {
829                                 doc.LoadXml ("<!DOCTYPE test SYSTEM 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'><root />");
830                         } catch (XmlException) {
831                                 Fail("#DoctypeDecl.System");
832                         }
833                         try {
834                                 doc.LoadXml ("<!DOCTYPE test PUBLIC '-//test' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'><root />");
835                         } catch (XmlException) {
836                                 Fail ("#DoctypeDecl.Public");
837                         }
838                         // Should this be commented out?
839 //                      try {
840 //                              doc.LoadXml ("<!DOCTYPE test [<!ELEMENT foo >]><root />");
841 //                      } catch (XmlException) {
842 //                              Fail("#DoctypeDecl.ElementDecl");
843 //                      }
844                 }
845
846                 public void TestCloneNode ()
847                 {
848                         XmlDocument doc = new XmlDocument ();
849                         doc.LoadXml ("<foo><bar /><baz hoge='fuga'>TEST Text</baz></foo>");
850                         XmlDocument doc2 = (XmlDocument)doc.CloneNode (false);
851                         AssertEquals ("ShallowCopy", 0, doc2.ChildNodes.Count);
852                         doc2 = (XmlDocument)doc.CloneNode (true);
853                         AssertEquals ("DeepCopy", "foo", doc2.DocumentElement.Name);
854                 }
855
856                 public void TestOuterXmlWithDefaultXmlns ()
857                 {
858                         XmlDocument doc = new XmlDocument ();
859                         doc.LoadXml ("<iq type=\"get\" id=\"ATECLIENT_1\"><query xmlns=\"jabber:iq:auth\"><username></username></query></iq>");
860                         AssertEquals ("<iq type=\"get\" id=\"ATECLIENT_1\"><query xmlns=\"jabber:iq:auth\"><username /></query></iq>", doc.OuterXml);
861                 }
862
863                 public void TestPreserveWhitespace ()
864                 {
865                         string input = 
866                                 "<?xml version=\"1.0\" encoding=\"utf-8\" ?><!-- --> <foo/>";
867
868                         XmlDocument dom = new XmlDocument ();
869                         XmlTextReader reader = new XmlTextReader (new StringReader (input));
870                         dom.Load (reader);
871
872                         AssertEquals (XmlNodeType.Element, dom.FirstChild.NextSibling.NextSibling.NodeType);
873                 }
874         }
875 }