// // System.Xml.XmlNodeTests // // Authors: // Kral Ferch // Martin Willemoes Hansen // // (C) 2002 Kral Ferch // (C) 2003 Martin Willemoes Hansen // using System; using System.IO; using System.Text; using System.Xml; using NUnit.Framework; namespace MonoTests.System.Xml { [TestFixture] public class XmlNodeTests : Assertion { XmlDocument document; XmlElement element; XmlElement element2; bool inserted; bool inserting; bool changed; bool changing; bool removed; bool removing; [SetUp] public void GetReady () { document = new XmlDocument (); document.NodeInserted += new XmlNodeChangedEventHandler (this.EventNodeInserted); document.NodeInserting += new XmlNodeChangedEventHandler (this.EventNodeInserting); document.NodeRemoved += new XmlNodeChangedEventHandler (this.EventNodeRemoved); document.NodeRemoving += new XmlNodeChangedEventHandler (this.EventNodeRemoving); element = document.CreateElement ("foo"); element2 = document.CreateElement ("bar"); } private void EventNodeInserted(Object sender, XmlNodeChangedEventArgs e) { inserted = true; } private void EventNodeInserting (Object sender, XmlNodeChangedEventArgs e) { inserting = true; } private void EventNodeChanged(Object sender, XmlNodeChangedEventArgs e) { changed = true; } private void EventNodeChanging (Object sender, XmlNodeChangedEventArgs e) { changing = true; } private void EventNodeRemoved(Object sender, XmlNodeChangedEventArgs e) { removed = true; } private void EventNodeRemoving (Object sender, XmlNodeChangedEventArgs e) { removing = true; } [Test] public void AppendChild () { XmlComment comment; inserted = false; inserting = false; element.AppendChild (element2); Assert (inserted); Assert (inserting); // Can only append to elements, documents, and attributes try { comment = document.CreateComment ("baz"); comment.AppendChild (element2); Fail ("Expected an InvalidOperationException to be thrown."); } catch (InvalidOperationException) {} // Can't append a node from one document into another document. XmlDocument document2 = new XmlDocument(); AssertEquals (1, element.ChildNodes.Count); try { element2 = document2.CreateElement ("qux"); element.AppendChild (element2); Fail ("Expected an ArgumentException to be thrown."); } catch (ArgumentException) {} AssertEquals (1, element.ChildNodes.Count); // Can't append to a readonly node. /* TODO put this in when I figure out how to create a read-only node. try { XmlElement element3 = (XmlElement)element.CloneNode (false); Assert (!element.IsReadOnly); Assert (element3.IsReadOnly); element2 = document.CreateElement ("quux"); element3.AppendChild (element2); Fail ("Expected an ArgumentException to be thrown."); } catch (ArgumentException) {} */ } [Test] public void GetNamespaceOfPrefix () { document.LoadXml ("text node"); XmlNode n = document.DocumentElement; AssertEquals ("urn:default", n.GetNamespaceOfPrefix (String.Empty)); AssertEquals ("urn:foo", n.GetNamespaceOfPrefix ("foo")); AssertEquals (String.Empty, n.GetNamespaceOfPrefix ("bar")); AssertEquals (String.Empty, n.GetNamespaceOfPrefix ("xml")); AssertEquals (String.Empty, n.GetNamespaceOfPrefix ("xmlns")); n = document.DocumentElement.FirstChild; AssertEquals ("urn:default", n.GetNamespaceOfPrefix (String.Empty)); AssertEquals ("urn:foo", n.GetNamespaceOfPrefix ("foo")); AssertEquals (String.Empty, n.GetNamespaceOfPrefix ("bar")); AssertEquals (String.Empty, n.GetNamespaceOfPrefix ("xml")); AssertEquals (String.Empty, n.GetNamespaceOfPrefix ("xmlns")); } [Test] [ExpectedException (typeof (ArgumentNullException))] public void GetNamespaceOfPrefixNullArg () { new XmlDocument ().GetNamespaceOfPrefix (null); } [Test] public void InsertBefore() { document = new XmlDocument(); document.LoadXml(""); XmlElement docelem = document.DocumentElement; docelem.InsertBefore(document.CreateElement("good_child"), docelem.FirstChild); AssertEquals("InsertBefore.Normal", "good_child", docelem.FirstChild.Name); // These are required for .NET 1.0 but not for .NET 1.1. try { document.InsertBefore (document.CreateElement ("BAD_MAN"), docelem); Fail ("#InsertBefore.BadPositionButNoError.1"); } catch (Exception) {} } [Test] public void InsertAfter() { document = new XmlDocument(); document.LoadXml(""); XmlElement docelem = document.DocumentElement; XmlElement newelem = document.CreateElement("good_child"); docelem.InsertAfter(newelem, docelem.FirstChild); AssertEquals("InsertAfter.Normal", 3, docelem.ChildNodes.Count); AssertEquals("InsertAfter.First", "sub1", docelem.FirstChild.Name); AssertEquals("InsertAfter.Last", "sub2", docelem.LastChild.Name); AssertEquals("InsertAfter.Prev", "good_child", docelem.FirstChild.NextSibling.Name); AssertEquals("InsertAfter.Next", "good_child", docelem.LastChild.PreviousSibling.Name); // this doesn't throw any exception *only on .NET 1.1* // .NET 1.0 throws an exception. try { document.InsertAfter(document.CreateElement("BAD_MAN"), docelem); #if USE_VERSION_1_1 AssertEquals("InsertAfter with bad location", "", document.InnerXml); } catch (XmlException ex) { throw ex; } #else } catch (Exception) {} #endif } [Test] public void Normalize () { XmlDocument doc = new XmlDocument (); doc.LoadXml ("This is the hardest one."); doc.NodeInserted += new XmlNodeChangedEventHandler (EventNodeInserted); doc.NodeChanged += new XmlNodeChangedEventHandler (EventNodeChanged); doc.NodeRemoved += new XmlNodeChangedEventHandler (EventNodeRemoved); AssertEquals (3, doc.DocumentElement.ChildNodes.Count); doc.DocumentElement.Normalize (); AssertEquals (3, doc.DocumentElement.ChildNodes.Count); Assert (changed); inserted = changed = removed = false; doc.DocumentElement.AppendChild (doc.CreateTextNode ("Addendum.")); AssertEquals (4, doc.DocumentElement.ChildNodes.Count); inserted = changed = removed = false; doc.DocumentElement.Normalize (); AssertEquals (3, doc.DocumentElement.ChildNodes.Count); Assert (changed); Assert (removed); inserted = changed = removed = false; doc.DocumentElement.SetAttribute ("attr", ""); XmlAttribute attr = doc.DocumentElement.Attributes [0] as XmlAttribute; AssertEquals (1, attr.ChildNodes.Count); inserted = changed = removed = false; attr.Normalize (); // Such behavior violates DOM Level 2 Node#normalize(), // but MS DOM is designed as such. AssertEquals (1, attr.ChildNodes.Count); } [Test] public void PrependChild() { document = new XmlDocument(); document.LoadXml(""); XmlElement docelem = document.DocumentElement; docelem.PrependChild(document.CreateElement("prepender")); AssertEquals("PrependChild", "prepender", docelem.FirstChild.Name); } public void saveTestRemoveAll () { // TODO: put this test back in when AttributeCollection.RemoveAll() is implemented. element.AppendChild(element2); removed = false; removing = false; element.RemoveAll (); Assert (removed); Assert (removing); } [Test] public void RemoveChild () { element.AppendChild(element2); removed = false; removing = false; element.RemoveChild (element2); Assert (removed); Assert (removing); } [Test] public void RemoveLastChild () { element.InnerXml = ""; element.RemoveChild (element.LastChild); AssertNotNull (element.FirstChild); } [Test] public void GetPrefixOfNamespace () { document.LoadXml (""); AssertEquals ("root", String.Empty, document.DocumentElement.GetPrefixOfNamespace ("urn:foo")); AssertEquals ("c1", String.Empty, document.DocumentElement.GetPrefixOfNamespace ("urn:foo")); AssertEquals ("c2", String.Empty, document.DocumentElement.FirstChild.GetPrefixOfNamespace ("urn:foo")); AssertEquals ("c3", "foo", document.DocumentElement.FirstChild.FirstChild.GetPrefixOfNamespace ("urn:foo")); // disconnected nodes. XmlNode n = document.CreateElement ("foo"); AssertEquals (String.Empty, n.GetPrefixOfNamespace ("foo")); n = document.CreateTextNode ("text"); // does not have Attributes AssertEquals (String.Empty, n.GetPrefixOfNamespace ("foo")); n = document.CreateXmlDeclaration ("1.0", null, null); // does not have Attributes AssertEquals (String.Empty, n.GetPrefixOfNamespace ("foo")); } [Test] public void ReplaceChild () { document.LoadXml (""); document.NodeInserted += new XmlNodeChangedEventHandler (this.EventNodeInserted); document.NodeChanged += new XmlNodeChangedEventHandler (this.EventNodeChanged); document.NodeRemoved += new XmlNodeChangedEventHandler (this.EventNodeRemoved); inserted = changed = removed = false; XmlElement el = document.CreateElement("root2"); document.ReplaceChild (el, document.DocumentElement); AssertEquals ("root2", document.DocumentElement.Name); AssertEquals (1, document.ChildNodes.Count); Assert (inserted && removed && !changed); } [Test] public void InnerText () { document.LoadXml ("This is mixed content. Also includes ."); string total = "This is mixed content. Also includes CDATA section."; XmlNode elemB = document.DocumentElement.ChildNodes [1]; AssertEquals ("mixed", elemB.FirstChild.InnerText); // text node AssertEquals ("mixed", elemB.InnerText); // element b AssertEquals (total, document.DocumentElement.InnerText); // element root AssertEquals (total, document.InnerText); // whole document } [Test] public void InnerXmlWithXmlns () { XmlDocument document = new XmlDocument (); XmlElement xel = document.CreateElement ("KeyValue", "http://www.w3.org/2000/09/xmldsig#"); xel.SetAttribute ("xmlns", "http://www.w3.org/2000/09/xmldsig#"); xel.InnerXml = "blablabla"; string expected = "blablabla"; AssertEquals (expected, xel.OuterXml); } [Test] public void SelectNodes () { // This test is done in this class since it tests only XmlDocumentNavigator. string xpath = "//@*|//namespace::*"; XmlDocument doc = new XmlDocument (); doc.LoadXml ("test"); XmlNodeList nl = doc.SelectNodes (xpath); AssertEquals (6, nl.Count); // BTW, as for namespace nodes, Node does not exist // in the tree, so the return value should be // implementation dependent. AssertEquals (XmlNodeType.Attribute, nl [0].NodeType); AssertEquals (XmlNodeType.Attribute, nl [1].NodeType); AssertEquals (XmlNodeType.Attribute, nl [2].NodeType); AssertEquals (XmlNodeType.Attribute, nl [3].NodeType); AssertEquals (XmlNodeType.Attribute, nl [4].NodeType); AssertEquals (XmlNodeType.Attribute, nl [5].NodeType); AssertEquals ("xmlns", nl [0].LocalName); AssertEquals ("xml", nl [1].LocalName); AssertEquals ("xmlns", nl [2].LocalName); AssertEquals ("xml", nl [3].LocalName); AssertEquals ("xmlns", nl [4].LocalName); AssertEquals ("xml", nl [5].LocalName); } [Test] [Ignore ("MS.NET has a bug; it fails to return nodes in document order.")] public void SelectNodes2 () { // This test is done in this class since it tests only XmlDocumentNavigator. string xpath = "//*|//@*|//namespace::*"; XmlDocument doc = new XmlDocument (); doc.LoadXml ("test"); XmlNodeList nl = doc.SelectNodes (xpath); AssertEquals (9, nl.Count); AssertEquals (XmlNodeType.Element, nl [0].NodeType); AssertEquals (XmlNodeType.Attribute, nl [1].NodeType); AssertEquals (XmlNodeType.Attribute, nl [2].NodeType); AssertEquals (XmlNodeType.Element, nl [3].NodeType); AssertEquals (XmlNodeType.Attribute, nl [4].NodeType); AssertEquals (XmlNodeType.Attribute, nl [5].NodeType); AssertEquals (XmlNodeType.Element, nl [6].NodeType); AssertEquals (XmlNodeType.Attribute, nl [7].NodeType); AssertEquals (XmlNodeType.Attribute, nl [8].NodeType); AssertEquals ("element", nl [0].LocalName); AssertEquals ("xmlns", nl [1].LocalName); AssertEquals ("xml", nl [2].LocalName); AssertEquals ("foo", nl [3].LocalName); AssertEquals ("xmlns", nl [4].LocalName); AssertEquals ("xml", nl [5].LocalName); AssertEquals ("bar", nl [6].LocalName); AssertEquals ("xmlns", nl [7].LocalName); AssertEquals ("xml", nl [8].LocalName); } } }