XmlNodeTests.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  1. //
  2. // System.Xml.XmlNodeTests
  3. //
  4. // Authors:
  5. // Kral Ferch <[email protected]>
  6. // Martin Willemoes Hansen
  7. //
  8. // (C) 2002 Kral Ferch
  9. // (C) 2003 Martin Willemoes Hansen
  10. //
  11. using System;
  12. using System.IO;
  13. using System.Text;
  14. using System.Xml;
  15. using NUnit.Framework;
  16. namespace MonoTests.System.Xml
  17. {
  18. [TestFixture]
  19. public class XmlNodeTests : Assertion
  20. {
  21. XmlDocument document;
  22. XmlElement element;
  23. XmlElement element2;
  24. bool inserted;
  25. bool inserting;
  26. bool changed;
  27. bool changing;
  28. bool removed;
  29. bool removing;
  30. [SetUp]
  31. public void GetReady ()
  32. {
  33. document = new XmlDocument ();
  34. document.NodeInserted += new XmlNodeChangedEventHandler (this.EventNodeInserted);
  35. document.NodeInserting += new XmlNodeChangedEventHandler (this.EventNodeInserting);
  36. document.NodeRemoved += new XmlNodeChangedEventHandler (this.EventNodeRemoved);
  37. document.NodeRemoving += new XmlNodeChangedEventHandler (this.EventNodeRemoving);
  38. element = document.CreateElement ("foo");
  39. element2 = document.CreateElement ("bar");
  40. }
  41. private void EventNodeInserted(Object sender, XmlNodeChangedEventArgs e)
  42. {
  43. inserted = true;
  44. }
  45. private void EventNodeInserting (Object sender, XmlNodeChangedEventArgs e)
  46. {
  47. inserting = true;
  48. }
  49. private void EventNodeChanged(Object sender, XmlNodeChangedEventArgs e)
  50. {
  51. changed = true;
  52. }
  53. private void EventNodeChanging (Object sender, XmlNodeChangedEventArgs e)
  54. {
  55. changing = true;
  56. }
  57. private void EventNodeRemoved(Object sender, XmlNodeChangedEventArgs e)
  58. {
  59. removed = true;
  60. }
  61. private void EventNodeRemoving (Object sender, XmlNodeChangedEventArgs e)
  62. {
  63. removing = true;
  64. }
  65. [Test]
  66. public void AppendChild ()
  67. {
  68. XmlComment comment;
  69. inserted = false;
  70. inserting = false;
  71. element.AppendChild (element2);
  72. Assert (inserted);
  73. Assert (inserting);
  74. // Can only append to elements, documents, and attributes
  75. try
  76. {
  77. comment = document.CreateComment ("baz");
  78. comment.AppendChild (element2);
  79. Fail ("Expected an InvalidOperationException to be thrown.");
  80. }
  81. catch (InvalidOperationException) {}
  82. // Can't append a node from one document into another document.
  83. XmlDocument document2 = new XmlDocument();
  84. AssertEquals (1, element.ChildNodes.Count);
  85. try
  86. {
  87. element2 = document2.CreateElement ("qux");
  88. element.AppendChild (element2);
  89. Fail ("Expected an ArgumentException to be thrown.");
  90. }
  91. catch (ArgumentException) {}
  92. AssertEquals (1, element.ChildNodes.Count);
  93. // Can't append to a readonly node.
  94. /* TODO put this in when I figure out how to create a read-only node.
  95. try
  96. {
  97. XmlElement element3 = (XmlElement)element.CloneNode (false);
  98. Assert (!element.IsReadOnly);
  99. Assert (element3.IsReadOnly);
  100. element2 = document.CreateElement ("quux");
  101. element3.AppendChild (element2);
  102. Fail ("Expected an ArgumentException to be thrown.");
  103. }
  104. catch (ArgumentException) {}
  105. */
  106. }
  107. [Test]
  108. public void GetNamespaceOfPrefix ()
  109. {
  110. document.LoadXml ("<root xmlns='urn:default' attr='value' "
  111. + "xml:lang='en' xmlns:foo='urn:foo' foo:att='fooatt'>text node</root>");
  112. XmlNode n = document.DocumentElement;
  113. AssertEquals ("#1", "urn:default", n.GetNamespaceOfPrefix (String.Empty));
  114. AssertEquals ("#2", "urn:foo", n.GetNamespaceOfPrefix ("foo"));
  115. AssertEquals ("#3", String.Empty, n.GetNamespaceOfPrefix ("bar"));
  116. #if NET_2_0
  117. AssertEquals ("#4", "http://www.w3.org/XML/1998/namespace", n.GetNamespaceOfPrefix ("xml"));
  118. AssertEquals ("#5", "http://www.w3.org/2000/xmlns/", n.GetNamespaceOfPrefix ("xmlns"));
  119. #else
  120. AssertEquals ("#4", String.Empty, n.GetNamespaceOfPrefix ("xml"));
  121. AssertEquals ("#5", String.Empty, n.GetNamespaceOfPrefix ("xmlns"));
  122. #endif
  123. n = document.DocumentElement.FirstChild;
  124. AssertEquals ("#6", "urn:default", n.GetNamespaceOfPrefix (String.Empty));
  125. AssertEquals ("#7", "urn:foo", n.GetNamespaceOfPrefix ("foo"));
  126. AssertEquals ("#8", String.Empty, n.GetNamespaceOfPrefix ("bar"));
  127. #if NET_2_0
  128. AssertEquals ("#9", "http://www.w3.org/XML/1998/namespace", n.GetNamespaceOfPrefix ("xml"));
  129. AssertEquals ("#10", "http://www.w3.org/2000/xmlns/", n.GetNamespaceOfPrefix ("xmlns"));
  130. #else
  131. AssertEquals ("#9", String.Empty, n.GetNamespaceOfPrefix ("xml"));
  132. AssertEquals ("#10", String.Empty, n.GetNamespaceOfPrefix ("xmlns"));
  133. #endif
  134. }
  135. [Test]
  136. [ExpectedException (typeof (ArgumentNullException))]
  137. public void GetNamespaceOfPrefixNullArg ()
  138. {
  139. new XmlDocument ().GetNamespaceOfPrefix (null);
  140. }
  141. [Test]
  142. public void InsertBefore()
  143. {
  144. document = new XmlDocument();
  145. document.LoadXml("<root><sub /></root>");
  146. XmlElement docelem = document.DocumentElement;
  147. docelem.InsertBefore(document.CreateElement("good_child"), docelem.FirstChild);
  148. AssertEquals("InsertBefore.Normal", "good_child", docelem.FirstChild.Name);
  149. // These are required for .NET 1.0 but not for .NET 1.1.
  150. try {
  151. document.InsertBefore (document.CreateElement ("BAD_MAN"), docelem);
  152. Fail ("#InsertBefore.BadPositionButNoError.1");
  153. }
  154. catch (Exception) {}
  155. }
  156. [Test]
  157. public void InsertAfter()
  158. {
  159. document = new XmlDocument();
  160. document.LoadXml("<root><sub1 /><sub2 /></root>");
  161. XmlElement docelem = document.DocumentElement;
  162. XmlElement newelem = document.CreateElement("good_child");
  163. docelem.InsertAfter(newelem, docelem.FirstChild);
  164. AssertEquals("InsertAfter.Normal", 3, docelem.ChildNodes.Count);
  165. AssertEquals("InsertAfter.First", "sub1", docelem.FirstChild.Name);
  166. AssertEquals("InsertAfter.Last", "sub2", docelem.LastChild.Name);
  167. AssertEquals("InsertAfter.Prev", "good_child", docelem.FirstChild.NextSibling.Name);
  168. AssertEquals("InsertAfter.Next", "good_child", docelem.LastChild.PreviousSibling.Name);
  169. // this doesn't throw any exception *only on .NET 1.1*
  170. // .NET 1.0 throws an exception.
  171. try {
  172. document.InsertAfter(document.CreateElement("BAD_MAN"), docelem);
  173. #if USE_VERSION_1_1
  174. AssertEquals("InsertAfter with bad location",
  175. "<root><sub1 /><good_child /><sub2 /></root><BAD_MAN />",
  176. document.InnerXml);
  177. } catch (XmlException ex) {
  178. throw ex;
  179. }
  180. #else
  181. } catch (Exception) {}
  182. #endif
  183. }
  184. [Test]
  185. public void Normalize ()
  186. {
  187. XmlDocument doc = new XmlDocument ();
  188. doc.LoadXml ("<root>This is the <b>hardest</b> one.</root>");
  189. doc.NodeInserted += new XmlNodeChangedEventHandler (EventNodeInserted);
  190. doc.NodeChanged += new XmlNodeChangedEventHandler (EventNodeChanged);
  191. doc.NodeRemoved += new XmlNodeChangedEventHandler (EventNodeRemoved);
  192. AssertEquals (3, doc.DocumentElement.ChildNodes.Count);
  193. doc.DocumentElement.Normalize ();
  194. AssertEquals (3, doc.DocumentElement.ChildNodes.Count);
  195. Assert (changed);
  196. inserted = changed = removed = false;
  197. doc.DocumentElement.AppendChild (doc.CreateTextNode ("Addendum."));
  198. AssertEquals (4, doc.DocumentElement.ChildNodes.Count);
  199. inserted = changed = removed = false;
  200. doc.DocumentElement.Normalize ();
  201. AssertEquals (3, doc.DocumentElement.ChildNodes.Count);
  202. Assert (changed);
  203. Assert (removed);
  204. inserted = changed = removed = false;
  205. doc.DocumentElement.SetAttribute ("attr", "");
  206. XmlAttribute attr = doc.DocumentElement.Attributes [0] as XmlAttribute;
  207. AssertEquals (1, attr.ChildNodes.Count);
  208. inserted = changed = removed = false;
  209. attr.Normalize ();
  210. // Such behavior violates DOM Level 2 Node#normalize(),
  211. // but MS DOM is designed as such.
  212. AssertEquals (1, attr.ChildNodes.Count);
  213. }
  214. [Test]
  215. public void Normalize2 ()
  216. {
  217. XmlDocument doc = new XmlDocument ();
  218. doc.PreserveWhitespace = true;
  219. doc.LoadXml ("<root> </root>");
  220. XmlElement root = doc.DocumentElement;
  221. root.AppendChild (doc.CreateTextNode ("foo"));
  222. root.AppendChild (doc.CreateTextNode ("bar"));
  223. root.AppendChild (doc.CreateWhitespace (" "));
  224. root.AppendChild (doc.CreateTextNode ("baz"));
  225. doc.NodeInserted += new XmlNodeChangedEventHandler (OnChange);
  226. doc.NodeChanged += new XmlNodeChangedEventHandler (OnChange);
  227. doc.NodeRemoved += new XmlNodeChangedEventHandler (OnChange);
  228. AssertEquals ("Before Normalize()", 5, root.ChildNodes.Count);
  229. root.Normalize ();
  230. AssertEquals ("<root> foobar baz</root>", root.OuterXml);
  231. AssertEquals ("After Normalize()", 1, root.ChildNodes.Count);
  232. }
  233. int normalize2Count;
  234. private void OnChange (object o, XmlNodeChangedEventArgs e)
  235. {
  236. switch (normalize2Count) {
  237. case 0:
  238. AssertEquals ("Action0", XmlNodeChangedAction.Remove, e.Action);
  239. AssertEquals ("Value0", " ", e.Node.Value);
  240. break;
  241. case 1:
  242. AssertEquals ("Action1", XmlNodeChangedAction.Remove, e.Action);
  243. AssertEquals ("Value1", "bar", e.Node.Value);
  244. break;
  245. case 2:
  246. AssertEquals ("Action2", XmlNodeChangedAction.Remove, e.Action);
  247. AssertEquals ("Value2", " ", e.Node.Value);
  248. break;
  249. case 3:
  250. AssertEquals ("Action3", XmlNodeChangedAction.Remove, e.Action);
  251. AssertEquals ("Value3", "baz", e.Node.Value);
  252. break;
  253. case 4:
  254. AssertEquals ("Action4", XmlNodeChangedAction.Change, e.Action);
  255. AssertEquals ("Value4", " foobar baz", e.Node.Value);
  256. break;
  257. default:
  258. Fail (String.Format ("Unexpected event. Action = {0}, node type = {1}, node name = {2}, node value = {3}", e.Action, e.Node.NodeType, e.Node.Name, e.Node.Value));
  259. break;
  260. }
  261. normalize2Count++;
  262. }
  263. [Test]
  264. public void PrependChild()
  265. {
  266. document = new XmlDocument();
  267. document.LoadXml("<root><sub1 /><sub2 /></root>");
  268. XmlElement docelem = document.DocumentElement;
  269. docelem.PrependChild(document.CreateElement("prepender"));
  270. AssertEquals("PrependChild", "prepender", docelem.FirstChild.Name);
  271. }
  272. public void saveTestRemoveAll ()
  273. {
  274. // TODO: put this test back in when AttributeCollection.RemoveAll() is implemented.
  275. element.AppendChild(element2);
  276. removed = false;
  277. removing = false;
  278. element.RemoveAll ();
  279. Assert (removed);
  280. Assert (removing);
  281. }
  282. [Test]
  283. public void RemoveChild ()
  284. {
  285. element.AppendChild(element2);
  286. removed = false;
  287. removing = false;
  288. element.RemoveChild (element2);
  289. Assert (removed);
  290. Assert (removing);
  291. }
  292. [Test]
  293. public void RemoveLastChild ()
  294. {
  295. element.InnerXml = "<foo/><bar/><baz/>";
  296. element.RemoveChild (element.LastChild);
  297. AssertNotNull (element.FirstChild);
  298. }
  299. [Test]
  300. public void GetPrefixOfNamespace ()
  301. {
  302. document.LoadXml ("<root><c1 xmlns='urn:foo'><c2 xmlns:foo='urn:foo' xmlns='urn:bar'><c3 xmlns=''/></c2></c1></root>");
  303. AssertEquals ("root", String.Empty, document.DocumentElement.GetPrefixOfNamespace ("urn:foo"));
  304. AssertEquals ("c1", String.Empty, document.DocumentElement.GetPrefixOfNamespace ("urn:foo"));
  305. AssertEquals ("c2", String.Empty, document.DocumentElement.FirstChild.GetPrefixOfNamespace ("urn:foo"));
  306. AssertEquals ("c3", "foo", document.DocumentElement.FirstChild.FirstChild.GetPrefixOfNamespace ("urn:foo"));
  307. // disconnected nodes.
  308. XmlNode n = document.CreateElement ("foo");
  309. AssertEquals (String.Empty, n.GetPrefixOfNamespace ("foo"));
  310. n = document.CreateTextNode ("text"); // does not have Attributes
  311. AssertEquals (String.Empty, n.GetPrefixOfNamespace ("foo"));
  312. n = document.CreateXmlDeclaration ("1.0", null, null); // does not have Attributes
  313. AssertEquals (String.Empty, n.GetPrefixOfNamespace ("foo"));
  314. }
  315. [Test]
  316. public void ReplaceChild ()
  317. {
  318. document.LoadXml ("<root/>");
  319. document.NodeInserted += new XmlNodeChangedEventHandler (this.EventNodeInserted);
  320. document.NodeChanged += new XmlNodeChangedEventHandler (this.EventNodeChanged);
  321. document.NodeRemoved += new XmlNodeChangedEventHandler (this.EventNodeRemoved);
  322. inserted = changed = removed = false;
  323. XmlElement el = document.CreateElement("root2");
  324. document.ReplaceChild (el, document.DocumentElement);
  325. AssertEquals ("root2", document.DocumentElement.Name);
  326. AssertEquals (1, document.ChildNodes.Count);
  327. Assert (inserted && removed && !changed);
  328. }
  329. [Test]
  330. public void InnerText ()
  331. {
  332. document.LoadXml ("<root>This is <b>mixed</b> content. Also includes <![CDATA[CDATA section]]>.<!-- Should be ignored --></root>");
  333. string total = "This is mixed content. Also includes CDATA section.";
  334. XmlNode elemB = document.DocumentElement.ChildNodes [1];
  335. AssertEquals ("mixed", elemB.FirstChild.InnerText); // text node
  336. AssertEquals ("mixed", elemB.InnerText); // element b
  337. AssertEquals (total, document.DocumentElement.InnerText); // element root
  338. AssertEquals (total, document.InnerText); // whole document
  339. }
  340. [Test]
  341. public void InnerXmlWithXmlns ()
  342. {
  343. XmlDocument document = new XmlDocument ();
  344. XmlElement xel = document.CreateElement ("KeyValue", "http://www.w3.org/2000/09/xmldsig#");
  345. xel.SetAttribute ("xmlns", "http://www.w3.org/2000/09/xmldsig#");
  346. xel.InnerXml = "<DSAKeyValue>blablabla</DSAKeyValue>";
  347. string expected = "<KeyValue xmlns=\"http://www.w3.org/2000/09/xmldsig#\"><DSAKeyValue>blablabla</DSAKeyValue></KeyValue>";
  348. AssertEquals (expected, xel.OuterXml);
  349. }
  350. [Test]
  351. public void SelectNodes ()
  352. {
  353. // This test is done in this class since it tests only XmlDocumentNavigator.
  354. string xpath = "//@*|//namespace::*";
  355. XmlDocument doc = new XmlDocument ();
  356. doc.LoadXml ("<element xmlns='urn:foo'><foo><bar>test</bar></foo></element>");
  357. XmlNodeList nl = doc.SelectNodes (xpath);
  358. AssertEquals (6, nl.Count);
  359. // BTW, as for namespace nodes, Node does not exist
  360. // in the tree, so the return value should be
  361. // implementation dependent.
  362. AssertEquals ("#1", XmlNodeType.Attribute, nl [0].NodeType);
  363. AssertEquals ("#2", XmlNodeType.Attribute, nl [1].NodeType);
  364. AssertEquals ("#3", XmlNodeType.Attribute, nl [2].NodeType);
  365. AssertEquals ("#4", XmlNodeType.Attribute, nl [3].NodeType);
  366. AssertEquals ("#5", XmlNodeType.Attribute, nl [4].NodeType);
  367. AssertEquals ("#6", XmlNodeType.Attribute, nl [5].NodeType);
  368. AssertEquals ("xmlns", nl [0].LocalName);
  369. AssertEquals ("xml", nl [1].LocalName);
  370. AssertEquals ("xmlns", nl [2].LocalName);
  371. AssertEquals ("xml", nl [3].LocalName);
  372. AssertEquals ("xmlns", nl [4].LocalName);
  373. AssertEquals ("xml", nl [5].LocalName);
  374. }
  375. [Test]
  376. [Ignore ("MS.NET has a bug; it fails to return nodes in document order.")]
  377. public void SelectNodes2 ()
  378. {
  379. // This test is done in this class since it tests only XmlDocumentNavigator.
  380. string xpath = "//*|//@*|//namespace::*";
  381. XmlDocument doc = new XmlDocument ();
  382. doc.LoadXml ("<element xmlns='urn:foo'><foo><bar>test</bar></foo></element>");
  383. XmlNodeList nl = doc.SelectNodes (xpath);
  384. AssertEquals (9, nl.Count);
  385. AssertEquals (XmlNodeType.Element, nl [0].NodeType);
  386. AssertEquals (XmlNodeType.Attribute, nl [1].NodeType);
  387. AssertEquals (XmlNodeType.Attribute, nl [2].NodeType);
  388. AssertEquals (XmlNodeType.Element, nl [3].NodeType);
  389. AssertEquals (XmlNodeType.Attribute, nl [4].NodeType);
  390. AssertEquals (XmlNodeType.Attribute, nl [5].NodeType);
  391. AssertEquals (XmlNodeType.Element, nl [6].NodeType);
  392. AssertEquals (XmlNodeType.Attribute, nl [7].NodeType);
  393. AssertEquals (XmlNodeType.Attribute, nl [8].NodeType);
  394. AssertEquals ("element", nl [0].LocalName);
  395. AssertEquals ("xmlns", nl [1].LocalName);
  396. AssertEquals ("xml", nl [2].LocalName);
  397. AssertEquals ("foo", nl [3].LocalName);
  398. AssertEquals ("xmlns", nl [4].LocalName);
  399. AssertEquals ("xml", nl [5].LocalName);
  400. AssertEquals ("bar", nl [6].LocalName);
  401. AssertEquals ("xmlns", nl [7].LocalName);
  402. AssertEquals ("xml", nl [8].LocalName);
  403. }
  404. [Test]
  405. public void BaseURI ()
  406. {
  407. // See bug #64120.
  408. XmlDocument doc = new XmlDocument ();
  409. doc.Load ("Test/XmlFiles/simple.xml");
  410. XmlElement el = doc.CreateElement ("foo");
  411. AssertEquals (String.Empty, el.BaseURI);
  412. doc.DocumentElement.AppendChild (el);
  413. Assert (String.Empty != el.BaseURI);
  414. XmlAttribute attr = doc.CreateAttribute ("attr");
  415. AssertEquals (String.Empty, attr.BaseURI);
  416. }
  417. [Test]
  418. public void CloneReadonlyNode ()
  419. {
  420. // Clone() should return such node that is not readonly
  421. string dtd = "<!DOCTYPE root ["
  422. + "<!ELEMENT root (#PCDATA|foo)*>"
  423. + "<!ELEMENT foo EMPTY>"
  424. + "<!ENTITY ent1 '<foo /><![CDATA[cdata]]>'>]>";
  425. string xml = dtd + "<root>&ent1;</root>";
  426. XmlDocument doc = new XmlDocument ();
  427. doc.LoadXml (xml);
  428. XmlNode n = doc.DocumentElement.FirstChild.FirstChild;
  429. Assert ("#1", n.IsReadOnly);
  430. Assert ("#2", !n.CloneNode (true).IsReadOnly);
  431. }
  432. }
  433. }