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;
21 using InvalidNodeTypeArgException = System.ArgumentException;
23 namespace MonoTests.System.Xml
26 public class XmlDocumentTests
28 private XmlDocument document;
29 private ArrayList eventStrings = new ArrayList();
31 // These Event* methods support the TestEventNode* Tests in this file.
32 // Most of them are event handlers for the XmlNodeChangedEventHandler
34 private void EventStringAdd(string eventName, XmlNodeChangedEventArgs e)
36 string oldParent = (e.OldParent != null) ? e.OldParent.Name : "<none>";
37 string newParent = (e.NewParent != null) ? e.NewParent.Name : "<none>";
38 eventStrings.Add (String.Format ("{0}, {1}, {2}, {3}, {4}", eventName, e.Action.ToString (), e.Node.OuterXml, oldParent, newParent));
41 private void EventNodeChanged(Object sender, XmlNodeChangedEventArgs e)
43 EventStringAdd ("NodeChanged", e);
46 private void EventNodeChanging (Object sender, XmlNodeChangedEventArgs e)
48 EventStringAdd ("NodeChanging", e);
51 private void EventNodeChangingException (Object sender, XmlNodeChangedEventArgs e)
53 throw new Exception ("don't change the value.");
56 private void EventNodeInserted(Object sender, XmlNodeChangedEventArgs e)
58 EventStringAdd ("NodeInserted", e);
61 private void EventNodeInserting(Object sender, XmlNodeChangedEventArgs e)
63 EventStringAdd ("NodeInserting", e);
66 private void EventNodeInsertingException(Object sender, XmlNodeChangedEventArgs e)
68 throw new Exception ("don't insert the element.");
71 private void EventNodeRemoved(Object sender, XmlNodeChangedEventArgs e)
73 EventStringAdd ("NodeRemoved", e);
76 private void EventNodeRemoving(Object sender, XmlNodeChangedEventArgs e)
78 EventStringAdd ("NodeRemoving", e);
81 private void EventNodeRemovingException(Object sender, XmlNodeChangedEventArgs e)
83 throw new Exception ("don't remove the element.");
87 public void GetReady ()
89 document = new XmlDocument ();
90 document.PreserveWhitespace = true;
94 public void CreateNodeNodeTypeNameEmptyParams ()
97 document.CreateNode (null, null, null);
98 Assert.Fail ("Expected an ArgumentException to be thrown.");
99 } catch (ArgumentException) {}
102 document.CreateNode ("attribute", null, null);
103 Assert.Fail ("Expected a NullReferenceException to be thrown.");
104 } catch (NullReferenceException) {}
107 document.CreateNode ("attribute", "", null);
108 Assert.Fail ("Expected an ArgumentException to be thrown.");
109 } catch (ArgumentException) {}
112 document.CreateNode ("element", null, null);
113 Assert.Fail ("Expected a NullReferenceException to be thrown.");
114 } catch (NullReferenceException) {}
117 document.CreateNode ("element", "", null);
118 Assert.Fail ("Expected an ArgumentException to be thrown.");
119 } catch (ArgumentException) {}
122 document.CreateNode ("entityreference", null, null);
123 Assert.Fail ("Expected a NullReferenceException to be thrown.");
124 } catch (NullReferenceException) {}
128 public void CreateNodeInvalidXmlNodeType ()
133 node = document.CreateNode (XmlNodeType.EndElement, null, null);
134 Assert.Fail ("Expected an ArgumentOutOfRangeException to be thrown.");
135 } catch (InvalidNodeTypeArgException) {}
138 node = document.CreateNode (XmlNodeType.EndEntity, null, null);
139 Assert.Fail ("Expected an ArgumentOutOfRangeException to be thrown.");
140 } catch (InvalidNodeTypeArgException) {}
143 node = document.CreateNode (XmlNodeType.Entity, null, null);
144 Assert.Fail ("Expected an ArgumentOutOfRangeException to be thrown.");
145 } catch (InvalidNodeTypeArgException) {}
148 node = document.CreateNode (XmlNodeType.None, null, null);
149 Assert.Fail ("Expected an ArgumentOutOfRangeException to be thrown.");
150 } catch (InvalidNodeTypeArgException) {}
153 node = document.CreateNode (XmlNodeType.Notation, null, null);
154 Assert.Fail ("Expected an ArgumentOutOfRangeException to be thrown.");
155 } catch (InvalidNodeTypeArgException) {}
157 // TODO: undocumented allowable type.
158 node = document.CreateNode (XmlNodeType.XmlDeclaration, null, null);
159 Assert.AreEqual (XmlNodeType.XmlDeclaration, node.NodeType);
163 public void CreateNodeWhichParamIsUsed ()
167 // No constructor params for Document, DocumentFragment.
169 node = document.CreateNode (XmlNodeType.CDATA, "a", "b", "c");
170 Assert.AreEqual (String.Empty, ((XmlCDataSection)node).Value);
172 node = document.CreateNode (XmlNodeType.Comment, "a", "b", "c");
173 Assert.AreEqual (String.Empty, ((XmlComment)node).Value);
175 node = document.CreateNode (XmlNodeType.DocumentType, "a", "b", "c");
176 Assert.IsNull (((XmlDocumentType)node).Value);
178 // TODO: add this back in to test when it's implemented.
179 // node = document.CreateNode (XmlNodeType.EntityReference, "a", "b", "c");
180 // Assert.IsNull (((XmlEntityReference)node).Value);
182 // TODO: add this back in to test when it's implemented.
183 // node = document.CreateNode (XmlNodeType.ProcessingInstruction, "a", "b", "c");
184 // Assert.AreEqual (String.Empty, ((XmlProcessingInstruction)node).Value);
186 node = document.CreateNode (XmlNodeType.SignificantWhitespace, "a", "b", "c");
187 Assert.AreEqual (String.Empty, ((XmlSignificantWhitespace)node).Value);
189 node = document.CreateNode (XmlNodeType.Text, "a", "b", "c");
190 Assert.AreEqual (String.Empty, ((XmlText)node).Value);
192 node = document.CreateNode (XmlNodeType.Whitespace, "a", "b", "c");
193 Assert.AreEqual (String.Empty, ((XmlWhitespace)node).Value);
195 node = document.CreateNode (XmlNodeType.XmlDeclaration, "a", "b", "c");
196 Assert.AreEqual ("version=\"1.0\"", ((XmlDeclaration)node).Value);
200 [Category ("NotDotNet")] // enbug in 2.0
201 public void CreateNodeNodeTypeName ()
206 node = document.CreateNode ("foo", null, null);
207 Assert.Fail ("Expected an ArgumentException to be thrown.");
208 } catch (ArgumentException) {}
210 // .NET 2.0 fails here.
211 node = document.CreateNode("attribute", "foo", null);
212 Assert.AreEqual (XmlNodeType.Attribute, node.NodeType);
214 node = document.CreateNode("cdatasection", null, null);
215 Assert.AreEqual (XmlNodeType.CDATA, node.NodeType);
217 node = document.CreateNode("comment", null, null);
218 Assert.AreEqual (XmlNodeType.Comment, node.NodeType);
220 node = document.CreateNode("document", null, null);
221 Assert.AreEqual (XmlNodeType.Document, node.NodeType);
222 // TODO: test which constructor this ended up calling,
223 // i.e. reuse underlying NameTable or not?
225 node = document.CreateNode("documentfragment", null, null);
226 Assert.AreEqual (XmlNodeType.DocumentFragment, node.NodeType);
228 node = document.CreateNode("documenttype", null, null);
229 Assert.AreEqual (XmlNodeType.DocumentType, node.NodeType);
231 node = document.CreateNode("element", "foo", null);
232 Assert.AreEqual (XmlNodeType.Element, node.NodeType);
234 // TODO: add this back in to test when it's implemented.
235 // ---> It is implemented, but it is LAMESPEC that allows null entity reference name.
236 // node = document.CreateNode("entityreference", "foo", null);
237 // Assert.AreEqual (XmlNodeType.EntityReference, node.NodeType);
239 // LAMESPEC: null PI name is silly.
240 // node = document.CreateNode("processinginstruction", null, null);
241 // Assert.AreEqual (XmlNodeType.ProcessingInstruction, node.NodeType);
243 node = document.CreateNode("significantwhitespace", null, null);
244 Assert.AreEqual (XmlNodeType.SignificantWhitespace, node.NodeType);
246 node = document.CreateNode("text", null, null);
247 Assert.AreEqual (XmlNodeType.Text, node.NodeType);
249 node = document.CreateNode("whitespace", null, null);
250 Assert.AreEqual (XmlNodeType.Whitespace, node.NodeType);
254 public void DocumentElement ()
256 Assert.IsNull (document.DocumentElement);
257 XmlElement element = document.CreateElement ("foo", "bar", "http://foo/");
258 Assert.IsNotNull (element);
260 Assert.AreEqual ("foo", element.Prefix);
261 Assert.AreEqual ("bar", element.LocalName);
262 Assert.AreEqual ("http://foo/", element.NamespaceURI);
264 Assert.AreEqual ("foo:bar", element.Name);
266 Assert.AreSame (element, document.AppendChild (element));
268 Assert.AreSame (element, document.DocumentElement);
272 public void DocumentEmpty()
274 Assert.AreEqual ("", document.OuterXml, "Incorrect output for empty document.");
278 public void EventNodeChanged()
283 document.NodeChanged += new XmlNodeChangedEventHandler (this.EventNodeChanged);
285 // Node that is part of the document.
286 document.AppendChild (document.CreateElement ("foo"));
287 comment = document.CreateComment ("bar");
288 document.DocumentElement.AppendChild (comment);
289 Assert.AreEqual ("<!--bar-->", document.DocumentElement.InnerXml);
290 comment.Value = "baz";
291 Assert.IsTrue (eventStrings.Contains ("NodeChanged, Change, <!--baz-->, foo, foo"));
292 Assert.AreEqual ("<!--baz-->", document.DocumentElement.InnerXml);
294 // Node that isn't part of the document but created by the document.
295 element = document.CreateElement ("foo");
296 comment = document.CreateComment ("bar");
297 element.AppendChild (comment);
298 Assert.AreEqual ("<!--bar-->", element.InnerXml);
299 comment.Value = "baz";
300 Assert.IsTrue (eventStrings.Contains ("NodeChanged, Change, <!--baz-->, foo, foo"));
301 Assert.AreEqual ("<!--baz-->", element.InnerXml);
304 TODO: Insert this when XmlNode.InnerText() and XmlNode.InnerXml() have been implemented.
306 // Node that is part of the document.
307 element = document.CreateElement ("foo");
308 element.InnerText = "bar";
309 document.AppendChild(element);
310 element.InnerText = "baz";
311 Assert.IsTrue (eventStrings.Contains("NodeChanged, Change, baz, foo, foo"));
313 // Node that isn't part of the document but created by the document.
314 element = document.CreateElement("qux");
315 element.InnerText = "quux";
316 element.InnerText = "quuux";
317 Assert.IsTrue (eventStrings.Contains("NodeChanged, Change, quuux, qux, qux"));
322 public void EventNodeChanging()
327 document.NodeChanging += new XmlNodeChangedEventHandler (this.EventNodeChanging);
329 // Node that is part of the document.
330 document.AppendChild (document.CreateElement ("foo"));
331 comment = document.CreateComment ("bar");
332 document.DocumentElement.AppendChild (comment);
333 Assert.AreEqual ("<!--bar-->", document.DocumentElement.InnerXml);
334 comment.Value = "baz";
335 Assert.IsTrue (eventStrings.Contains ("NodeChanging, Change, <!--bar-->, foo, foo"));
336 Assert.AreEqual ("<!--baz-->", document.DocumentElement.InnerXml);
338 // Node that isn't part of the document but created by the document.
339 element = document.CreateElement ("foo");
340 comment = document.CreateComment ("bar");
341 element.AppendChild (comment);
342 Assert.AreEqual ("<!--bar-->", element.InnerXml);
343 comment.Value = "baz";
344 Assert.IsTrue (eventStrings.Contains ("NodeChanging, Change, <!--bar-->, foo, foo"));
345 Assert.AreEqual ("<!--baz-->", element.InnerXml);
347 // If an exception is thrown the Document returns to original state.
348 document.NodeChanging += new XmlNodeChangedEventHandler (this.EventNodeChangingException);
349 element = document.CreateElement("foo");
350 comment = document.CreateComment ("bar");
351 element.AppendChild (comment);
352 Assert.AreEqual ("<!--bar-->", element.InnerXml);
355 comment.Value = "baz";
356 Assert.Fail ("Expected an exception to be thrown by the NodeChanging event handler method EventNodeChangingException().");
357 } catch (Exception) {}
358 Assert.AreEqual ("<!--bar-->", element.InnerXml);
360 // Yes it's a bit anal but this tests whether the node changing event exception fires before the
361 // ArgumentOutOfRangeException. Turns out it does so that means our implementation needs to raise
362 // the node changing event before doing any work.
365 comment.ReplaceData(-1, 0, "qux");
366 Assert.Fail ("Expected an ArgumentOutOfRangeException to be thrown.");
371 TODO: Insert this when XmlNode.InnerText() and XmlNode.InnerXml() have been implemented.
373 // Node that is part of the document.
374 element = document.CreateElement ("foo");
375 element.InnerText = "bar";
376 document.AppendChild(element);
377 element.InnerText = "baz";
378 Assert.IsTrue (eventStrings.Contains("NodeChanging, Change, bar, foo, foo"));
380 // Node that isn't part of the document but created by the document.
381 element = document.CreateElement("foo");
382 element.InnerText = "bar";
383 element.InnerText = "baz";
384 Assert.IsTrue (eventStrings.Contains("NodeChanging, Change, bar, foo, foo"));
386 // If an exception is thrown the Document returns to original state.
387 document.NodeChanging += new XmlNodeChangedEventHandler (this.EventNodeChangingException);
388 element = document.CreateElement("foo");
389 element.InnerText = "bar";
391 element.InnerText = "baz";
392 Assert.Fail ("Expected an exception to be thrown by the NodeChanging event handler method EventNodeChangingException().");
393 } catch (Exception) {}
394 Assert.AreEqual ("bar", element.InnerText);
399 public void EventNodeInserted()
403 document.NodeInserted += new XmlNodeChangedEventHandler (this.EventNodeInserted);
405 // Inserted 'foo' element to the document.
406 element = document.CreateElement ("foo");
407 document.AppendChild (element);
408 Assert.IsTrue (eventStrings.Contains ("NodeInserted, Insert, <foo />, <none>, #document"));
410 // Append child on node in document
411 element = document.CreateElement ("foo");
412 document.DocumentElement.AppendChild (element);
413 Assert.IsTrue (eventStrings.Contains ("NodeInserted, Insert, <foo />, <none>, foo"));
415 // Append child on node not in document but created by document
416 element = document.CreateElement ("bar");
417 element.AppendChild(document.CreateElement ("bar"));
418 Assert.IsTrue (eventStrings.Contains("NodeInserted, Insert, <bar />, <none>, bar"));
422 public void EventNodeInserting()
426 document.NodeInserting += new XmlNodeChangedEventHandler (this.EventNodeInserting);
428 // Inserting 'foo' element to the document.
429 element = document.CreateElement ("foo");
430 document.AppendChild (element);
431 Assert.IsTrue (eventStrings.Contains ("NodeInserting, Insert, <foo />, <none>, #document"));
433 // Append child on node in document
434 element = document.CreateElement ("foo");
435 document.DocumentElement.AppendChild (element);
436 Assert.IsTrue (eventStrings.Contains ("NodeInserting, Insert, <foo />, <none>, foo"));
438 // Append child on node not in document but created by document
439 element = document.CreateElement ("bar");
440 Assert.AreEqual (0, element.ChildNodes.Count);
441 element.AppendChild (document.CreateElement ("bar"));
442 Assert.IsTrue (eventStrings.Contains ("NodeInserting, Insert, <bar />, <none>, bar"));
443 Assert.AreEqual (1, element.ChildNodes.Count);
445 // If an exception is thrown the Document returns to original state.
446 document.NodeInserting += new XmlNodeChangedEventHandler (this.EventNodeInsertingException);
447 Assert.AreEqual (1, element.ChildNodes.Count);
450 element.AppendChild (document.CreateElement("baz"));
451 Assert.Fail ("Expected an exception to be thrown by the NodeInserting event handler method EventNodeInsertingException().");
454 Assert.AreEqual (1, element.ChildNodes.Count);
458 public void EventNodeRemoved()
463 document.NodeRemoved += new XmlNodeChangedEventHandler (this.EventNodeRemoved);
465 // Removed 'bar' element from 'foo' outside document.
466 element = document.CreateElement ("foo");
467 element2 = document.CreateElement ("bar");
468 element.AppendChild (element2);
469 Assert.AreEqual (1, element.ChildNodes.Count);
470 element.RemoveChild (element2);
471 Assert.IsTrue (eventStrings.Contains ("NodeRemoved, Remove, <bar />, foo, <none>"));
472 Assert.AreEqual (0, element.ChildNodes.Count);
475 * TODO: put this test back in when AttributeCollection.RemoveAll() is implemented.
478 element = document.CreateElement ("foo");
479 element2 = document.CreateElement ("bar");
480 element.AppendChild(element2);
481 Assert.AreEqual (1, element.ChildNodes.Count);
483 Assert.IsTrue (eventStrings.Contains ("NodeRemoved, Remove, <bar />, foo, <none>"));
484 Assert.AreEqual (0, element.ChildNodes.Count);
487 // Removed 'bar' element from 'foo' inside document.
488 element = document.CreateElement ("foo");
489 document.AppendChild (element);
490 element = document.CreateElement ("bar");
491 document.DocumentElement.AppendChild (element);
492 Assert.AreEqual (1, document.DocumentElement.ChildNodes.Count);
493 document.DocumentElement.RemoveChild (element);
494 Assert.IsTrue (eventStrings.Contains ("NodeRemoved, Remove, <bar />, foo, <none>"));
495 Assert.AreEqual (0, document.DocumentElement.ChildNodes.Count);
499 public void EventNodeRemoving()
504 document.NodeRemoving += new XmlNodeChangedEventHandler (this.EventNodeRemoving);
506 // Removing 'bar' element from 'foo' outside document.
507 element = document.CreateElement ("foo");
508 element2 = document.CreateElement ("bar");
509 element.AppendChild (element2);
510 Assert.AreEqual (1, element.ChildNodes.Count);
511 element.RemoveChild (element2);
512 Assert.IsTrue (eventStrings.Contains ("NodeRemoving, Remove, <bar />, foo, <none>"));
513 Assert.AreEqual (0, element.ChildNodes.Count);
516 * TODO: put this test back in when AttributeCollection.RemoveAll() is implemented.
519 element = document.CreateElement ("foo");
520 element2 = document.CreateElement ("bar");
521 element.AppendChild(element2);
522 Assert.AreEqual (1, element.ChildNodes.Count);
524 Assert.IsTrue (eventStrings.Contains ("NodeRemoving, Remove, <bar />, foo, <none>"));
525 Assert.AreEqual (0, element.ChildNodes.Count);
528 // Removing 'bar' element from 'foo' inside document.
529 element = document.CreateElement ("foo");
530 document.AppendChild (element);
531 element = document.CreateElement ("bar");
532 document.DocumentElement.AppendChild (element);
533 Assert.AreEqual (1, document.DocumentElement.ChildNodes.Count);
534 document.DocumentElement.RemoveChild (element);
535 Assert.IsTrue (eventStrings.Contains ("NodeRemoving, Remove, <bar />, foo, <none>"));
536 Assert.AreEqual (0, document.DocumentElement.ChildNodes.Count);
538 // If an exception is thrown the Document returns to original state.
539 document.NodeRemoving += new XmlNodeChangedEventHandler (this.EventNodeRemovingException);
540 element.AppendChild (element2);
541 Assert.AreEqual (1, element.ChildNodes.Count);
544 element.RemoveChild(element2);
545 Assert.Fail ("Expected an exception to be thrown by the NodeRemoving event handler method EventNodeRemovingException().");
548 Assert.AreEqual (1, element.ChildNodes.Count);
552 public void GetElementsByTagNameNoNameSpace ()
554 string xml = @"<library><book><title>XML Fun</title><author>John Doe</author>
555 <price>34.95</price></book><book><title>Bear and the Dragon</title>
556 <author>Tom Clancy</author><price>6.95</price></book><book>
557 <title>Bourne Identity</title><author>Robert Ludlum</author>
558 <price>9.95</price></book><Fluffer><Nutter><book>
559 <title>Bourne Ultimatum</title><author>Robert Ludlum</author>
560 <price>9.95</price></book></Nutter></Fluffer></library>";
562 MemoryStream memoryStream = new MemoryStream (Encoding.UTF8.GetBytes (xml));
563 document = new XmlDocument ();
564 document.Load (memoryStream);
565 XmlNodeList bookList = document.GetElementsByTagName ("book");
566 Assert.AreEqual (4, bookList.Count, "GetElementsByTagName (string) returned incorrect count.");
570 public void GetElementsByTagNameUsingNameSpace ()
572 StringBuilder xml = new StringBuilder ();
573 xml.Append ("<?xml version=\"1.0\" ?><library xmlns:North=\"http://www.foo.com\" ");
574 xml.Append ("xmlns:South=\"http://www.goo.com\"><North:book type=\"non-fiction\"> ");
575 xml.Append ("<North:title type=\"intro\">XML Fun</North:title> " );
576 xml.Append ("<North:author>John Doe</North:author> " );
577 xml.Append ("<North:price>34.95</North:price></North:book> " );
578 xml.Append ("<South:book type=\"fiction\"> " );
579 xml.Append ("<South:title>Bear and the Dragon</South:title> " );
580 xml.Append ("<South:author>Tom Clancy</South:author> " );
581 xml.Append ("<South:price>6.95</South:price></South:book> " );
582 xml.Append ("<South:book type=\"fiction\"><South:title>Bourne Identity</South:title> " );
583 xml.Append ("<South:author>Robert Ludlum</South:author> " );
584 xml.Append ("<South:price>9.95</South:price></South:book></library>");
586 MemoryStream memoryStream = new MemoryStream (Encoding.UTF8.GetBytes (xml.ToString ()));
587 document = new XmlDocument ();
588 document.Load (memoryStream);
589 XmlNodeList bookList = document.GetElementsByTagName ("book", "http://www.goo.com");
590 Assert.AreEqual (2, bookList.Count, "GetElementsByTagName (string, uri) returned incorrect count.");
594 public void GetElementsByTagNameNs2 ()
596 document.LoadXml (@"<root>
597 <x:a xmlns:x='urn:foo' id='a'>
598 <y:a xmlns:y='urn:foo' id='b'/>
602 <?a processing instruction ?>
606 // id='b' has different prefix. Should not caught by (name),
607 // while should caught by (name, ns).
608 XmlNodeList nl = document.GetElementsByTagName ("x:a");
609 Assert.AreEqual (2, nl.Count);
610 Assert.AreEqual ("a", nl [0].Attributes ["id"].Value);
611 Assert.AreEqual ("c", nl [1].Attributes ["id"].Value);
613 nl = document.GetElementsByTagName ("a", "urn:foo");
614 Assert.AreEqual (3, nl.Count);
615 Assert.AreEqual ("a", nl [0].Attributes ["id"].Value);
616 Assert.AreEqual ("b", nl [1].Attributes ["id"].Value);
617 Assert.AreEqual ("c", nl [2].Attributes ["id"].Value);
620 nl = document.GetElementsByTagName ("*");
621 Assert.AreEqual (6, nl.Count);
622 Assert.AreEqual ("root", nl [0].Name);
623 Assert.AreEqual ("a", nl [1].Attributes ["id"].Value);
624 Assert.AreEqual ("b", nl [2].Attributes ["id"].Value);
625 Assert.AreEqual ("c", nl [3].Attributes ["id"].Value);
626 Assert.AreEqual ("d", nl [4].Attributes ["id"].Value);
627 Assert.AreEqual ("e", nl [5].Attributes ["id"].Value);
629 // wildcard - local and ns
630 nl = document.GetElementsByTagName ("*", "*");
631 Assert.AreEqual (6, nl.Count);
632 Assert.AreEqual ("root", nl [0].Name);
633 Assert.AreEqual ("a", nl [1].Attributes ["id"].Value);
634 Assert.AreEqual ("b", nl [2].Attributes ["id"].Value);
635 Assert.AreEqual ("c", nl [3].Attributes ["id"].Value);
636 Assert.AreEqual ("d", nl [4].Attributes ["id"].Value);
637 Assert.AreEqual ("e", nl [5].Attributes ["id"].Value);
639 // namespace wildcard - namespace
640 nl = document.GetElementsByTagName ("*", "urn:foo");
641 Assert.AreEqual (4, nl.Count);
642 Assert.AreEqual ("a", nl [0].Attributes ["id"].Value);
643 Assert.AreEqual ("b", nl [1].Attributes ["id"].Value);
644 Assert.AreEqual ("c", nl [2].Attributes ["id"].Value);
645 Assert.AreEqual ("e", nl [3].Attributes ["id"].Value);
647 // namespace wildcard - local only. I dare say, such usage is not XML-ish!
648 nl = document.GetElementsByTagName ("a", "*");
649 Assert.AreEqual (3, nl.Count);
650 Assert.AreEqual ("a", nl [0].Attributes ["id"].Value);
651 Assert.AreEqual ("b", nl [1].Attributes ["id"].Value);
652 Assert.AreEqual ("c", nl [2].Attributes ["id"].Value);
656 public void Implementation ()
658 Assert.IsNotNull (new XmlDocument ().Implementation);
662 public void InnerAndOuterXml ()
664 Assert.AreEqual (String.Empty, document.InnerXml);
665 Assert.AreEqual (document.InnerXml, document.OuterXml);
667 XmlDeclaration declaration = document.CreateXmlDeclaration ("1.0", null, null);
668 document.AppendChild (declaration);
669 Assert.AreEqual ("<?xml version=\"1.0\"?>", document.InnerXml);
670 Assert.AreEqual (document.InnerXml, document.OuterXml);
672 XmlElement element = document.CreateElement ("foo");
673 document.AppendChild (element);
674 Assert.AreEqual ("<?xml version=\"1.0\"?><foo />", document.InnerXml);
675 Assert.AreEqual (document.InnerXml, document.OuterXml);
677 XmlComment comment = document.CreateComment ("bar");
678 document.DocumentElement.AppendChild (comment);
679 Assert.AreEqual ("<?xml version=\"1.0\"?><foo><!--bar--></foo>", document.InnerXml);
680 Assert.AreEqual (document.InnerXml, document.OuterXml);
682 XmlText text = document.CreateTextNode ("baz");
683 document.DocumentElement.AppendChild (text);
684 Assert.AreEqual ("<?xml version=\"1.0\"?><foo><!--bar-->baz</foo>", document.InnerXml);
685 Assert.AreEqual (document.InnerXml, document.OuterXml);
687 element = document.CreateElement ("quux");
688 element.SetAttribute ("quuux", "squonk");
689 document.DocumentElement.AppendChild (element);
690 Assert.AreEqual ("<?xml version=\"1.0\"?><foo><!--bar-->baz<quux quuux=\"squonk\" /></foo>", document.InnerXml);
691 Assert.AreEqual (document.InnerXml, document.OuterXml);
695 public void LoadWithSystemIOStream ()
697 string xml = @"<library><book><title>XML Fun</title><author>John Doe</author>
698 <price>34.95</price></book><book><title>Bear and the Dragon</title>
699 <author>Tom Clancy</author><price>6.95</price></book><book>
700 <title>Bourne Identity</title><author>Robert Ludlum</author>
701 <price>9.95</price></book><Fluffer><Nutter><book>
702 <title>Bourne Ultimatum</title><author>Robert Ludlum</author>
703 <price>9.95</price></book></Nutter></Fluffer></library>";
705 MemoryStream memoryStream = new MemoryStream (Encoding.UTF8.GetBytes (xml));
706 document = new XmlDocument ();
707 document.Load (memoryStream);
708 Assert.AreEqual (true, document.HasChildNodes, "Not Loaded From IOStream");
712 public void LoadXmlReaderNamespacesFalse ()
714 XmlTextReader xtr = new XmlTextReader (
715 "<root xmlns='urn:foo' />", XmlNodeType.Document, null);
716 xtr.Namespaces = false;
717 document.Load (xtr); // Don't complain about xmlns attribute with its namespaceURI == String.Empty.
721 public void LoadXmlCDATA ()
723 document.LoadXml ("<foo><![CDATA[bar]]></foo>");
724 Assert.IsTrue (document.DocumentElement.FirstChild.NodeType == XmlNodeType.CDATA);
725 Assert.AreEqual ("bar", document.DocumentElement.FirstChild.Value);
729 public void LoadXMLComment()
731 // XmlTextReader needs to throw this exception
733 // document.LoadXml("<!--foo-->");
734 // Assert.Fail ("XmlException should have been thrown.");
736 // catch (XmlException e) {
737 // Assert.AreEqual ("The root element is missing.", e.Message, "Exception message doesn't match.");
740 document.LoadXml ("<foo><!--Comment--></foo>");
741 Assert.IsTrue (document.DocumentElement.FirstChild.NodeType == XmlNodeType.Comment);
742 Assert.AreEqual ("Comment", document.DocumentElement.FirstChild.Value);
744 document.LoadXml (@"<foo><!--bar--></foo>");
745 Assert.AreEqual ("bar", ((XmlComment)document.FirstChild.FirstChild).Data, "Incorrect target.");
749 public void LoadXmlElementSingle ()
751 Assert.IsNull (document.DocumentElement);
752 document.LoadXml ("<foo/>");
754 Assert.IsNotNull (document.DocumentElement);
755 Assert.AreSame (document.FirstChild, document.DocumentElement);
757 Assert.AreEqual (String.Empty, document.DocumentElement.Prefix);
758 Assert.AreEqual ("foo", document.DocumentElement.LocalName);
759 Assert.AreEqual (String.Empty, document.DocumentElement.NamespaceURI);
760 Assert.AreEqual ("foo", document.DocumentElement.Name);
764 public void LoadXmlElementWithAttributes ()
766 Assert.IsNull (document.DocumentElement);
767 document.LoadXml ("<foo bar='baz' quux='quuux' hoge='hello & world' />");
769 XmlElement documentElement = document.DocumentElement;
771 Assert.AreEqual ("baz", documentElement.GetAttribute ("bar"));
772 Assert.AreEqual ("quuux", documentElement.GetAttribute ("quux"));
773 Assert.AreEqual ("hello & world", documentElement.GetAttribute ("hoge"));
774 Assert.AreEqual ("hello & world", documentElement.Attributes ["hoge"].Value);
775 Assert.AreEqual (1, documentElement.GetAttributeNode ("hoge").ChildNodes.Count);
779 public void LoadXmlElementWithChildElement ()
781 document.LoadXml ("<foo><bar/></foo>");
782 Assert.IsTrue (document.ChildNodes.Count == 1);
783 Assert.IsTrue (document.FirstChild.ChildNodes.Count == 1);
784 Assert.AreEqual ("foo", document.DocumentElement.LocalName);
785 Assert.AreEqual ("bar", document.DocumentElement.FirstChild.LocalName);
789 public void LoadXmlElementWithTextNode ()
791 document.LoadXml ("<foo>bar</foo>");
792 Assert.IsTrue (document.DocumentElement.FirstChild.NodeType == XmlNodeType.Text);
793 Assert.AreEqual ("bar", document.DocumentElement.FirstChild.Value);
797 public void LoadXmlExceptionClearsDocument ()
799 document.LoadXml ("<foo/>");
800 Assert.IsTrue (document.FirstChild != null);
803 document.LoadXml ("<123/>");
804 Assert.Fail ("An XmlException should have been thrown.");
805 } catch (XmlException) {}
807 Assert.IsTrue (document.FirstChild == null);
811 public void LoadXmlProcessingInstruction ()
813 document.LoadXml (@"<?foo bar='baaz' quux='quuux'?><quuuux></quuuux>");
814 Assert.AreEqual ("foo", ((XmlProcessingInstruction)document.FirstChild).Target, "Incorrect target.");
815 Assert.AreEqual ("bar='baaz' quux='quuux'", ((XmlProcessingInstruction)document.FirstChild).Data, "Incorrect data.");
819 public void OuterXml ()
823 xml = "<root><![CDATA[foo]]></root>";
824 document.LoadXml (xml);
825 Assert.AreEqual (xml, document.OuterXml, "XmlDocument with cdata OuterXml is incorrect.");
827 xml = "<root><!--foo--></root>";
828 document.LoadXml (xml);
829 Assert.AreEqual (xml, document.OuterXml, "XmlDocument with comment OuterXml is incorrect.");
831 xml = "<root><?foo bar?></root>";
832 document.LoadXml (xml);
833 Assert.AreEqual (xml, document.OuterXml, "XmlDocument with processing instruction OuterXml is incorrect.");
837 public void ParentNodes ()
839 document.LoadXml ("<foo><bar><baz/></bar></foo>");
840 XmlNode node = document.FirstChild.FirstChild.FirstChild;
841 Assert.AreEqual ("baz", node.LocalName, "Wrong child found.");
842 Assert.AreEqual ("bar", node.ParentNode.LocalName, "Wrong parent.");
843 Assert.AreEqual ("foo", node.ParentNode.ParentNode.LocalName, "Wrong parent.");
844 Assert.AreEqual ("#document", node.ParentNode.ParentNode.ParentNode.LocalName, "Wrong parent.");
845 Assert.IsNull (node.ParentNode.ParentNode.ParentNode.ParentNode, "Expected parent to be null.");
849 public void RemovedElementNextSibling ()
854 document.LoadXml ("<foo><child1/><child2/></foo>");
855 node = document.DocumentElement.FirstChild;
856 document.DocumentElement.RemoveChild (node);
857 nextSibling = node.NextSibling;
858 Assert.IsNull (nextSibling, "Expected removed node's next sibling to be null.");
863 public void ImportNode ()
867 string xlinkURI = "http://www.w3.org/1999/XLink";
868 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>";
869 document.LoadXml(xml1);
870 XmlDocument newDoc = new XmlDocument();
871 newDoc.LoadXml("<hoge><fuga /></hoge>");
872 XmlElement bar = document.DocumentElement.FirstChild as XmlElement;
875 n = newDoc.ImportNode(bar.GetAttributeNode("href", xlinkURI), true);
876 Assert.AreEqual ("href", n.LocalName, "#ImportNode.Attr.NS.LocalName");
877 Assert.AreEqual (xlinkURI, n.NamespaceURI, "#ImportNode.Attr.NS.NSURI");
878 Assert.AreEqual ("#foo", n.Value, "#ImportNode.Attr.NS.Value");
881 n = newDoc.ImportNode(bar.FirstChild.FirstChild, true);
882 Assert.AreEqual ("cdata section.\n\titem 1\n\titem 2\n", n.Value, "#ImportNode.CDATA");
885 XmlElement e = newDoc.ImportNode(bar, true) as XmlElement;
886 Assert.AreEqual ("bar", e.Name, "#ImportNode.Element.Name");
887 Assert.AreEqual ("#foo", e.GetAttribute("href", xlinkURI), "#ImportNode.Element.Attr");
888 Assert.AreEqual ("baz", e.FirstChild.Name, "#ImportNode.Element.deep");
891 // [2002/10/14] CreateEntityReference was not implemented.
892 // document.LoadXml("<!DOCTYPE test PUBLIC 'dummy' [<!ENTITY FOOENT 'foo'>]><root>&FOOENT;</root>");
893 // n = newDoc.ImportNode(document.DocumentElement.FirstChild);
894 // Assert.AreEqual ("FOOENT", n.Name, "#ImportNode.EntityReference");
895 // Assert.AreEqual ("foo_", n.Value, "#ImportNode.EntityReference");
897 // Processing Instruction
898 document.LoadXml("<foo><?xml-stylesheet href='foo.xsl' ?></foo>");
899 XmlProcessingInstruction pi = (XmlProcessingInstruction)newDoc.ImportNode(document.DocumentElement.FirstChild, false);
900 Assert.AreEqual ("xml-stylesheet", pi.Name, "#ImportNode.ProcessingInstruction.Name");
901 Assert.AreEqual ("href='foo.xsl'", pi.Data.Trim(), "#ImportNode.ProcessingInstruction.Data");
904 document.LoadXml(xml1);
905 n = newDoc.ImportNode((XmlText)bar.FirstChild.ChildNodes[1], true);
906 Assert.AreEqual ("From here, simple text node.", n.Value, "#ImportNode.Text");
909 document.LoadXml(xml1);
910 XmlDeclaration decl = (XmlDeclaration)newDoc.ImportNode(document.FirstChild, false);
911 Assert.AreEqual (XmlNodeType.XmlDeclaration, decl.NodeType, "#ImportNode.XmlDeclaration.Type");
912 Assert.AreEqual ("utf-8", decl.Encoding, "#ImportNode.XmlDeclaration.Encoding");
916 public void NameTable()
918 XmlDocument doc = new XmlDocument();
919 Assert.IsNotNull (doc.NameTable);
923 public void SingleEmptyRootDocument()
925 XmlDocument doc = new XmlDocument();
926 doc.LoadXml("<root />");
927 Assert.IsNotNull (doc.DocumentElement);
931 public void DocumentWithDoctypeDecl ()
933 XmlDocument doc = new XmlDocument ();
934 // In fact it is invalid, but it doesn't fail with MS.NET 1.0.
935 doc.LoadXml ("<!DOCTYPE test><root />");
936 Assert.IsNotNull (doc.DocumentType);
940 doc.LoadXml ("<!DOCTYPE test SYSTEM 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'><root />");
941 } catch (XmlException) {
942 Assert.Fail ("#DoctypeDecl.System");
945 doc.LoadXml ("<!DOCTYPE test PUBLIC '-//test' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'><root />");
946 } catch (XmlException) {
947 Assert.Fail ("#DoctypeDecl.Public");
950 // Should this be commented out?
951 doc.LoadXml ("<!DOCTYPE test [<!ELEMENT foo EMPTY>]><test><foo/></test>");
955 public void CloneNode ()
957 XmlDocument doc = new XmlDocument ();
958 doc.LoadXml ("<foo><bar /><baz hoge='fuga'>TEST Text</baz></foo>");
959 XmlDocument doc2 = (XmlDocument)doc.CloneNode (false);
960 Assert.AreEqual (0, doc2.ChildNodes.Count, "ShallowCopy");
961 doc2 = (XmlDocument)doc.CloneNode (true);
962 Assert.AreEqual ("foo", doc2.DocumentElement.Name, "DeepCopy");
966 public void OuterXmlWithDefaultXmlns ()
968 XmlDocument doc = new XmlDocument ();
969 doc.LoadXml ("<iq type=\"get\" id=\"ATECLIENT_1\"><query xmlns=\"jabber:iq:auth\"><username></username></query></iq>");
970 Assert.AreEqual ("<iq type=\"get\" id=\"ATECLIENT_1\"><query xmlns=\"jabber:iq:auth\"><username></username></query></iq>", doc.OuterXml);
974 public void PreserveWhitespace ()
977 "<?xml version=\"1.0\" encoding=\"utf-8\" ?><!-- --> <foo/>";
979 XmlDocument dom = new XmlDocument ();
980 XmlTextReader reader = new XmlTextReader (new StringReader (input));
983 Assert.AreEqual (XmlNodeType.Element, dom.FirstChild.NextSibling.NextSibling.NodeType);
987 public void PreserveWhitespace2 ()
989 XmlDocument doc = new XmlDocument ();
990 Assert.IsTrue (!doc.PreserveWhitespace);
991 doc.PreserveWhitespace = true;
992 XmlDocument d2 = doc.Clone () as XmlDocument;
993 Assert.IsTrue (!d2.PreserveWhitespace); // i.e. not cloned
994 d2.AppendChild (d2.CreateElement ("root"));
995 d2.DocumentElement.AppendChild (d2.CreateWhitespace (" "));
996 StringWriter sw = new StringWriter ();
997 d2.WriteTo (new XmlTextWriter (sw));
998 Assert.AreEqual ("<root> </root>", sw.ToString ());
1002 public void CreateAttribute ()
1004 XmlDocument dom = new XmlDocument ();
1006 // Check that null prefix and namespace are allowed and
1008 XmlAttribute attr = dom.CreateAttribute (null, "FOO", null);
1009 Assert.AreEqual (attr.Prefix, "");
1010 Assert.AreEqual (attr.NamespaceURI, "");
1014 public void DocumentTypeNodes ()
1016 string entities = "<!ENTITY foo 'foo-ent'>";
1017 string dtd = "<!DOCTYPE root [<!ELEMENT root (#PCDATA)*> " + entities + "]>";
1018 string xml = dtd + "<root>&foo;</root>";
1019 XmlValidatingReader xvr = new XmlValidatingReader (xml, XmlNodeType.Document, null);
1020 document.Load (xvr);
1021 Assert.IsNotNull (document.DocumentType);
1022 Assert.AreEqual (1, document.DocumentType.Entities.Count);
1024 XmlEntity foo = document.DocumentType.Entities.GetNamedItem ("foo") as XmlEntity;
1025 Assert.IsNotNull (foo);
1026 Assert.IsNotNull (document.DocumentType.Entities.GetNamedItem ("foo", ""));
1027 Assert.AreEqual ("foo", foo.Name);
1028 Assert.IsNull (foo.Value);
1029 Assert.AreEqual ("foo-ent", foo.InnerText);
1033 public void DTDEntityAttributeHandling ()
1035 string dtd = "<!DOCTYPE root[<!ATTLIST root hoge CDATA 'hoge-def'><!ENTITY foo 'ent-foo'>]>";
1036 string xml = dtd + "<root>&foo;</root>";
1037 XmlValidatingReader xvr = new XmlValidatingReader (xml, XmlNodeType.Document,null);
1038 xvr.EntityHandling = EntityHandling.ExpandCharEntities;
1039 xvr.ValidationType = ValidationType.None;
1040 document.Load (xvr);
1041 // Don't include default attributes here.
1042 Assert.AreEqual (xml, document.OuterXml);
1043 Assert.AreEqual ("hoge-def", document.DocumentElement.GetAttribute ("hoge"));
1046 // [Test] Comment out in the meantime.
1047 // public void LoadExternalUri ()
1049 // // set any URL of well-formed XML.
1050 // document.Load ("http://www.go-mono.com/index.rss");
1053 // [Test] comment out in the meantime.
1054 // public void LoadDocumentWithIgnoreSection ()
1056 // // set any URL of well-formed XML.
1057 // document.Load ("xmlfiles/test.xml");
1061 [ExpectedException (typeof (XmlException))]
1062 public void LoadThrowsUndeclaredEntity ()
1064 string ent1 = "<!ENTITY ent 'entity string'>";
1065 string ent2 = "<!ENTITY ent2 '<foo/><foo/>'>]>";
1066 string dtd = "<!DOCTYPE root[<!ELEMENT root (#PCDATA|foo)*>" + ent1 + ent2;
1067 string xml = dtd + "<root>&ent3;&ent2;</root>";
1068 XmlTextReader xtr = new XmlTextReader (xml, XmlNodeType.Document, null);
1069 document.Load (xtr);
1074 public void CreateEntityReferencesWithoutDTD ()
1076 document.RemoveAll ();
1077 document.AppendChild (document.CreateElement ("root"));
1078 document.DocumentElement.AppendChild (document.CreateEntityReference ("foo"));
1082 public void LoadEntityReference ()
1084 string xml = "<!DOCTYPE root [<!ELEMENT root (#PCDATA)*><!ENTITY ent 'val'>]><root attr='a &ent; string'>&ent;</root>";
1085 XmlTextReader xtr = new XmlTextReader (xml, XmlNodeType.Document, null);
1086 XmlDocument doc = new XmlDocument ();
1088 Assert.AreEqual (XmlNodeType.EntityReference, doc.DocumentElement.FirstChild.NodeType, "#text node");
1089 Assert.AreEqual (XmlNodeType.EntityReference, doc.DocumentElement.Attributes [0].ChildNodes [1].NodeType, "#attribute");
1093 public void ReadNodeEmptyContent ()
1095 XmlTextReader xr = new XmlTextReader ("", XmlNodeType.Element, null);
1097 Console.WriteLine (xr.NodeType);
1098 XmlNode n = document.ReadNode (xr);
1103 public void ReadNodeWhitespace ()
1105 XmlTextReader xr = new XmlTextReader (" ", XmlNodeType.Element, null);
1107 Console.WriteLine (xr.NodeType);
1108 document.PreserveWhitespace = false; // Note this line.
1109 XmlNode n = document.ReadNode (xr);
1110 Assert.IsNotNull (n);
1111 Assert.AreEqual (XmlNodeType.Whitespace, n.NodeType);
1115 public void SavePreserveWhitespace ()
1117 string xml = "<root> <element>text\n</element></root>";
1118 XmlDocument doc = new XmlDocument ();
1119 doc.PreserveWhitespace = true;
1121 StringWriter sw = new StringWriter ();
1123 Assert.AreEqual ("<?xml version=\"1.0\" encoding=\"utf-16\"?>" + xml, sw.ToString ());
1125 doc.PreserveWhitespace = false;
1126 sw = new StringWriter ();
1128 string NEL = Environment.NewLine;
1129 Assert.AreEqual ("<?xml version=\"1.0\" encoding=\"utf-16\"?>"
1130 + NEL + "<root> <element>text"
1131 + "\n</element></root>",
1136 public void ReadNodeEntityReferenceFillsChildren ()
1138 string dtd = "<!DOCTYPE root [<!ELEMENT root (#PCDATA)*><!ENTITY ent 'val'>]>";
1140 string xml = dtd + "<root attr='a &ent; string'>&ent;</root>";
1141 XmlValidatingReader reader = new XmlValidatingReader (
1142 xml, XmlNodeType.Document, null);
1144 reader.EntityHandling = EntityHandling.ExpandCharEntities;
1145 reader.ValidationType = ValidationType.None;
1147 //skip the doctype delcaration
1151 XmlDocument doc = new XmlDocument ();
1155 doc.DocumentElement.FirstChild.ChildNodes.Count);
1159 public void LoadTreatsFixedAttributesAsIfItExisted ()
1161 string xml = @"<!DOCTYPE foo [<!ELEMENT foo EMPTY><!ATTLIST foo xmlns CDATA #FIXED 'urn:foo'>]><foo />";
1162 XmlDocument doc = new XmlDocument ();
1163 doc.Load (new StringReader (xml));
1164 Assert.AreEqual ("urn:foo", doc.DocumentElement.NamespaceURI);
1168 public void Bug79468 () // XmlNameEntryCache bug
1170 string xml = "<?xml version='1.0' encoding='UTF-8'?>"
1171 + "<ns0:DebtAmountRequest xmlns:ns0='http://whatever'>"
1172 + " <Signature xmlns='http://www.w3.org/2000/09/xmldsig#' />"
1173 + "</ns0:DebtAmountRequest>";
1174 XmlDocument doc = new XmlDocument ();
1176 XmlNodeList nodeList = doc.GetElementsByTagName ("Signature");
1179 class MyXmlDocument : XmlDocument
1181 public override XmlAttribute CreateAttribute (string p, string l, string n)
1183 return base.CreateAttribute (p, "hijacked", n);
1188 public void UseOverridenCreateAttribute ()
1190 XmlDocument doc = new MyXmlDocument ();
1191 doc.LoadXml ("<root a='sane' />");
1192 Assert.IsNotNull (doc.DocumentElement.GetAttributeNode ("hijacked"));
1193 Assert.IsNull (doc.DocumentElement.GetAttributeNode ("a"));
1197 public void LoadFromMiddleOfDocument ()
1200 string xml = @"<?xml version='1.0' encoding='utf-8' ?>
1203 <ConsolePort value='9998' />
1206 var r = new XmlTextReader (new StringReader (xml));
1207 r.WhitespaceHandling = WhitespaceHandling.All;
1210 var doc = new XmlDocument ();
1212 Assert.AreEqual (XmlNodeType.EndElement, r.NodeType, "#1");