3 // Atsushi Enomoto <atsushi@ximian.com>
5 // Copyright (C) 2010 Novell, Inc.
6 // (C) 2003 Atsushi Enomoto <ginga@kit.hi-ho.ne.jp>
8 // Permission is hereby granted, free of charge, to any person obtaining
9 // a copy of this software and associated documentation files (the
10 // "Software"), to deal in the Software without restriction, including
11 // without limitation the rights to use, copy, modify, merge, publish,
12 // distribute, sublicense, and/or sell copies of the Software, and to
13 // permit persons to whom the Software is furnished to do so, subject to
14 // the following conditions:
16 // The above copyright notice and this permission notice shall be
17 // included in all copies or substantial portions of the Software.
19 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
23 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
24 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
25 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 // (based on XPathNavigatorCommonTests)
33 using System.Collections;
37 using System.Xml.Linq;
38 using System.Xml.XPath;
39 using NUnit.Framework;
40 using System.Collections.Generic;
42 namespace MonoTests.System.Xml
44 public static class Helpers
46 public static string NormalizeNewline(this string str)
48 return str.Replace("\r\n", "\n");
53 public class ExtensionsTest
57 private void AssertNavigator (string label, XPathNavigator nav, XPathNodeType type, string prefix, string localName, string ns, string name, string value, bool hasAttributes, bool hasChildren, bool isEmptyElement)
59 label += nav.GetType ();
60 Assert.AreEqual (type, nav.NodeType, label + "NodeType");
61 Assert.AreEqual (prefix, nav.Prefix, label + "Prefix");
62 Assert.AreEqual (localName, nav.LocalName, label + "LocalName");
63 Assert.AreEqual (ns, nav.NamespaceURI, label + "Namespace");
64 Assert.AreEqual (name, nav.Name, label + "Name");
65 Assert.AreEqual (value, nav.Value, label + "Value");
66 Assert.AreEqual (hasAttributes, nav.HasAttributes, label + "HasAttributes");
67 Assert.AreEqual (hasChildren, nav.HasChildren, label + "HasChildren");
68 Assert.AreEqual (isEmptyElement, nav.IsEmptyElement, label + "IsEmptyElement");
72 public void DocumentWithXmlDeclaration ()
74 string xml = "<?xml version=\"1.0\" standalone=\"yes\"?><foo>bar</foo>";
76 nav = XDocument.Parse (xml).CreateNavigator ();
77 DocumentWithXmlDeclaration (nav);
80 public void DocumentWithXmlDeclaration (XPathNavigator nav)
82 nav.MoveToFirstChild ();
83 AssertNavigator ("#1", nav, XPathNodeType.Element, "", "foo", "", "foo", "bar", false, true, false);
87 public void DocumentWithProcessingInstruction ()
89 string xml = "<?xml-stylesheet href='foo.xsl' type='text/xsl' ?><foo />";
91 nav = XDocument.Parse (xml).CreateNavigator ();
92 DocumentWithProcessingInstruction (nav);
95 public void DocumentWithProcessingInstruction (XPathNavigator nav)
97 Assert.IsTrue (nav.MoveToFirstChild ());
98 AssertNavigator ("#1", nav, XPathNodeType.ProcessingInstruction, "", "xml-stylesheet", "", "xml-stylesheet", "href='foo.xsl' type='text/xsl' ", false, false, false);
99 Assert.IsTrue (!nav.MoveToFirstChild ());
103 public void XmlRootElementOnly ()
105 string xml = "<foo />";
107 nav = XDocument.Parse (xml).CreateNavigator ();
108 XmlRootElementOnly (nav);
111 private void XmlRootElementOnly (XPathNavigator nav)
113 AssertNavigator ("#1", nav, XPathNodeType.Root, "", "", "", "", "", false, true, false);
114 Assert.IsTrue (nav.MoveToFirstChild ());
115 AssertNavigator ("#2", nav, XPathNodeType.Element, "", "foo", "", "foo", "", false, false, true);
116 Assert.IsTrue (!nav.MoveToFirstChild ());
117 Assert.IsTrue (!nav.MoveToNext ());
118 Assert.IsTrue (!nav.MoveToPrevious ());
120 AssertNavigator ("#3", nav, XPathNodeType.Root, "", "", "", "", "", false, true, false);
121 Assert.IsTrue (!nav.MoveToNext ());
125 public void XmlSimpleTextContent ()
127 string xml = "<foo>Test.</foo>";
129 nav = XDocument.Parse (xml).CreateNavigator ();
130 XmlSimpleTextContent (nav);
133 private void XmlSimpleTextContent (XPathNavigator nav)
135 AssertNavigator ("#1", nav, XPathNodeType.Root, "", "", "", "", "Test.", false, true, false);
136 Assert.IsTrue (nav.MoveToFirstChild (), "#x1");
137 AssertNavigator ("#2", nav, XPathNodeType.Element, "", "foo", "", "foo", "Test.", false, true, false);
138 Assert.IsTrue (!nav.MoveToNext (), "#x2");
139 Assert.IsTrue (!nav.MoveToPrevious (), "#x3");
140 Assert.IsTrue (nav.MoveToFirstChild (), "#x4");
141 AssertNavigator ("#3", nav, XPathNodeType.Text, "", "", "", "", "Test.", false, false, false);
143 Assert.IsTrue (nav.MoveToParent (), "#x5");
144 AssertNavigator ("#4", nav, XPathNodeType.Element, "", "foo", "", "foo", "Test.", false, true, false);
146 Assert.IsTrue (nav.MoveToParent (), "#x6");
147 AssertNavigator ("#5", nav, XPathNodeType.Root, "", "", "", "", "Test.", false, true, false);
149 nav.MoveToFirstChild ();
150 nav.MoveToFirstChild ();
152 AssertNavigator ("#6", nav, XPathNodeType.Root, "", "", "", "", "Test.", false, true, false);
153 Assert.IsTrue (!nav.MoveToNext (), "#x7");
157 public void XmlSimpleElementContent ()
159 string xml = "<foo><bar /></foo>";
161 nav = XDocument.Parse (xml).CreateNavigator ();
162 XmlSimpleElementContent (nav);
165 private void XmlSimpleElementContent (XPathNavigator nav)
167 AssertNavigator ("#1", nav, XPathNodeType.Root, "", "", "", "", "", false, true, false);
168 Assert.IsTrue (nav.MoveToFirstChild ());
169 AssertNavigator ("#2", nav, XPathNodeType.Element, "", "foo", "", "foo", "", false, true, false);
170 Assert.IsTrue (!nav.MoveToNext ());
171 Assert.IsTrue (!nav.MoveToPrevious ());
173 Assert.IsTrue (nav.MoveToFirstChild ());
174 AssertNavigator ("#3", nav, XPathNodeType.Element, "", "bar", "", "bar", "", false, false, true);
176 Assert.IsTrue (nav.MoveToParent ());
177 AssertNavigator ("#4", nav, XPathNodeType.Element, "", "foo", "", "foo", "", false, true, false);
180 AssertNavigator ("#5", nav, XPathNodeType.Root, "", "", "", "", "", false, true, false);
181 Assert.IsTrue (!nav.MoveToNext ());
185 public void XmlTwoElementsContent ()
187 string xml = "<foo><bar /><baz /></foo>";
189 nav = XDocument.Parse (xml).CreateNavigator ();
190 XmlTwoElementsContent (nav);
193 private void XmlTwoElementsContent (XPathNavigator nav)
195 AssertNavigator ("#1", nav, XPathNodeType.Root, "", "", "", "", "", false, true, false);
197 Assert.IsTrue (nav.MoveToFirstChild ());
198 AssertNavigator ("#2", nav, XPathNodeType.Element, "", "foo", "", "foo", "", false, true, false);
199 Assert.IsTrue (!nav.MoveToNext ());
200 Assert.IsTrue (!nav.MoveToPrevious ());
202 Assert.IsTrue (nav.MoveToFirstChild ());
203 AssertNavigator ("#3", nav, XPathNodeType.Element, "", "bar", "", "bar", "", false, false, true);
204 Assert.IsTrue (!nav.MoveToFirstChild ());
206 Assert.IsTrue (nav.MoveToNext ());
207 AssertNavigator ("#4", nav, XPathNodeType.Element, "", "baz", "", "baz", "", false, false, true);
208 Assert.IsTrue (!nav.MoveToFirstChild ());
210 Assert.IsTrue (nav.MoveToPrevious ());
211 AssertNavigator ("#5", nav, XPathNodeType.Element, "", "bar", "", "bar", "", false, false, true);
214 AssertNavigator ("#6", nav, XPathNodeType.Root, "", "", "", "", "", false, true, false);
215 Assert.IsTrue (!nav.MoveToNext ());
219 public void XmlElementWithAttributes ()
221 string xml = "<img src='foo.png' alt='image Fooooooo!' />";
223 nav = XDocument.Parse (xml).CreateNavigator ();
224 XmlElementWithAttributes (nav);
227 private void XmlElementWithAttributes (XPathNavigator nav)
229 nav.MoveToFirstChild ();
230 AssertNavigator ("#1", nav, XPathNodeType.Element, "", "img", "", "img", "", true, false, true);
231 Assert.IsTrue (!nav.MoveToNext (), "#x1");
232 Assert.IsTrue (!nav.MoveToPrevious (), "#x2");
234 Assert.IsTrue (nav.MoveToFirstAttribute (), "#x3");
235 AssertNavigator ("#2", nav, XPathNodeType.Attribute, "", "src", "", "src", "foo.png", false, false, false);
236 Assert.IsTrue (!nav.MoveToFirstAttribute (), "#x4"); // On attributes, it fails.
238 Assert.IsTrue (nav.MoveToNextAttribute (), "#x5");
239 AssertNavigator ("#3", nav, XPathNodeType.Attribute, "", "alt", "", "alt", "image Fooooooo!", false, false, false);
240 Assert.IsTrue (!nav.MoveToNextAttribute (), "#x6");
242 Assert.IsTrue (nav.MoveToParent (), "#x7");
243 AssertNavigator ("#4", nav, XPathNodeType.Element, "", "img", "", "img", "", true, false, true);
245 Assert.IsTrue (nav.MoveToAttribute ("alt", ""), "#x8");
246 AssertNavigator ("#5", nav, XPathNodeType.Attribute, "", "alt", "", "alt", "image Fooooooo!", false, false, false);
247 Assert.IsTrue (!nav.MoveToAttribute ("src", ""), "#x9"); // On attributes, it fails.
248 Assert.IsTrue (nav.MoveToParent (), "#x10");
249 Assert.IsTrue (nav.MoveToAttribute ("src", ""), "#x11");
250 AssertNavigator ("#6", nav, XPathNodeType.Attribute, "", "src", "", "src", "foo.png", false, false, false);
253 AssertNavigator ("#7", nav, XPathNodeType.Root, "", "", "", "", "", false, true, false);
257 // seems like MS does not want to fix their long-time-known
258 // XPathNavigator bug, so just set it as NotDotNet.
260 [Category ("NotDotNet")]
261 public void XmlNamespaceNode ()
263 string xml = "<html xmlns='http://www.w3.org/1999/xhtml'><body>test.</body></html>";
265 nav = XDocument.Parse (xml).CreateNavigator ();
266 XmlNamespaceNode (nav);
269 private void XmlNamespaceNode (XPathNavigator nav)
271 string xhtml = "http://www.w3.org/1999/xhtml";
272 string xmlNS = "http://www.w3.org/XML/1998/namespace";
273 nav.MoveToFirstChild ();
274 AssertNavigator ("#1", nav, XPathNodeType.Element,
275 "", "html", xhtml, "html", "test.", false, true, false);
276 Assert.IsTrue (nav.MoveToFirstNamespace (XPathNamespaceScope.Local));
277 AssertNavigator ("#2", nav, XPathNodeType.Namespace,
278 "", "", "", "", xhtml, false, false, false);
280 // Test difference between Local, ExcludeXml and All.
281 Assert.IsTrue (!nav.MoveToNextNamespace (XPathNamespaceScope.Local));
282 Assert.IsTrue (!nav.MoveToNextNamespace (XPathNamespaceScope.ExcludeXml));
283 // LAMESPEC: MS.NET 1.0 XmlDocument seems to have some bugs around here.
284 // see http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q316808
286 Assert.IsTrue (nav.MoveToNextNamespace (XPathNamespaceScope.All));
287 AssertNavigator ("#3", nav, XPathNodeType.Namespace,
288 "", "xml", "", "xml", xmlNS, false, false, false);
289 Assert.IsTrue (!nav.MoveToNextNamespace (XPathNamespaceScope.All));
291 // Test to check if MoveToRoot() resets Namespace node status.
293 AssertNavigator ("#4", nav, XPathNodeType.Root, "", "", "", "", "test.", false, true, false);
294 nav.MoveToFirstChild ();
296 // Test without XPathNamespaceScope argument.
297 Assert.IsTrue (nav.MoveToFirstNamespace ());
298 Assert.IsTrue (nav.MoveToNextNamespace ());
299 AssertNavigator ("#5", nav, XPathNodeType.Namespace,
300 "", "xml", "", "xml", xmlNS, false, false, false);
302 // Test MoveToParent()
303 Assert.IsTrue (nav.MoveToParent ());
304 AssertNavigator ("#6", nav, XPathNodeType.Element,
305 "", "html", xhtml, "html", "test.", false, true, false);
307 nav.MoveToFirstChild (); // body
308 // Test difference between Local and ExcludeXml
309 Assert.IsTrue (!nav.MoveToFirstNamespace (XPathNamespaceScope.Local), "Local should fail");
310 Assert.IsTrue (nav.MoveToFirstNamespace (XPathNamespaceScope.ExcludeXml), "ExcludeXml should succeed");
311 AssertNavigator ("#7", nav, XPathNodeType.Namespace,
312 "", "", "", "", xhtml, false, false, false);
314 Assert.IsTrue (nav.MoveToNextNamespace (XPathNamespaceScope.All));
315 AssertNavigator ("#8", nav, XPathNodeType.Namespace,
316 "", "xml", "", "xml", xmlNS, false, false, false);
317 Assert.IsTrue (nav.MoveToParent ());
318 AssertNavigator ("#9", nav, XPathNodeType.Element,
319 "", "body", xhtml, "body", "test.", false, true, false);
322 AssertNavigator ("#10", nav, XPathNodeType.Root, "", "", "", "", "test.", false, true, false);
326 public void MoveToNamespaces ()
328 string xml = "<a xmlns:x='urn:x'><b xmlns:y='urn:y'/><c/><d><e attr='a'/></d></a>";
330 nav = XDocument.Parse (xml).CreateNavigator ();
331 MoveToNamespaces (nav);
334 private void MoveToNamespaces (XPathNavigator nav)
336 XPathNodeIterator iter = nav.Select ("//e");
338 nav.MoveTo (iter.Current);
339 Assert.AreEqual ("e", nav.Name, "#1");
340 nav.MoveToFirstNamespace ();
341 Assert.AreEqual ("x", nav.Name, "#2");
342 nav.MoveToNextNamespace ();
343 Assert.AreEqual ("xml", nav.Name, "#3");
347 public void IsDescendant ()
349 string xml = "<a><b/><c/><d><e attr='a'/></d></a>";
351 nav = XDocument.Parse (xml).CreateNavigator ();
355 private void IsDescendant (XPathNavigator nav)
357 XPathNavigator tmp = nav.Clone ();
358 XPathNodeIterator iter = nav.Select ("//e");
360 Assert.IsTrue (nav.MoveTo (iter.Current), "#1");
361 Assert.IsTrue (nav.MoveToFirstAttribute (), "#2");
362 Assert.AreEqual ("attr", nav.Name, "#3");
363 Assert.AreEqual ("", tmp.Name, "#4");
364 Assert.IsTrue (tmp.IsDescendant (nav), "#5");
365 Assert.IsTrue (!nav.IsDescendant (tmp), "#6");
366 tmp.MoveToFirstChild ();
367 Assert.AreEqual ("a", tmp.Name, "#7");
368 Assert.IsTrue (tmp.IsDescendant (nav), "#8");
369 Assert.IsTrue (!nav.IsDescendant (tmp), "#9");
370 tmp.MoveTo (iter.Current);
371 Assert.AreEqual ("e", tmp.Name, "#10");
372 Assert.IsTrue (tmp.IsDescendant (nav), "#11");
373 Assert.IsTrue (!nav.IsDescendant (tmp), "#12");
377 public void LiterallySplitText ()
379 string xml = "<root><![CDATA[test]]> string</root>";
381 nav = XDocument.Parse (xml).CreateNavigator ();
382 LiterallySplitText (nav);
385 private void LiterallySplitText (XPathNavigator nav)
387 nav.MoveToFirstChild ();
388 nav.MoveToFirstChild ();
389 Assert.AreEqual (XPathNodeType.Text, nav.NodeType, "#1");
390 Assert.AreEqual ("test string", nav.Value, "#2");
395 public void SelectChildren ()
397 string xml = "<root><foo xmlns='urn:foo' /><ns:foo xmlns:ns='urn:foo' /></root>";
399 nav = XDocument.Parse (xml).CreateNavigator ();
400 SelectChildrenNS (nav);
403 private void SelectChildrenNS (XPathNavigator nav)
405 nav.MoveToFirstChild (); // root
406 XPathNodeIterator iter = nav.SelectChildren ("foo", "urn:foo");
407 Assert.AreEqual (2, iter.Count, "#1");
413 public void OuterXml ()
415 string xml = @"<?xml version=""1.0""?>
417 <two>Some data.</two>
420 nav = XDocument.Parse (xml).CreateNavigator ();
424 private void OuterXml (XPathNavigator nav)
427 <two>Some data.</two>
429 Assert.AreEqual (ret.NormalizeNewline (), nav.OuterXml.NormalizeNewline (), "#1");
433 public void ReadSubtreeLookupNamespace ()
435 string xml = "<x:foo xmlns:x='urn:x'><bar>x:val</bar></x:foo>";
436 var doc = new XmlDocument ();
438 XPathNavigator nav = doc.LastChild.LastChild.CreateNavigator ();
439 var xr = nav.ReadSubtree ();
441 xr.Read (); // should be at x:val
442 Assert.AreEqual ("urn:x", xr.LookupNamespace ("x"), "#1");
446 public void GetNamespaceConsistentTree ()
448 string xml = "<x:root xmlns:x='urn:x'> <x:foo xmlns='ns1'> <x:bar /> </x:foo> <x:foo xmlns:y='ns2'> <x:bar /> </x:foo></x:root>";
449 nav = XDocument.Parse (xml).CreateNavigator ();
450 GetNamespaceConsistentTree (nav);
453 private void GetNamespaceConsistentTree (XPathNavigator nav)
455 nav.MoveToFirstChild ();
456 nav.MoveToFirstChild ();
458 Assert.AreEqual (String.Empty, nav.GetNamespace (""), "#1." + nav.GetType ());
461 Assert.AreEqual ("", nav.GetNamespace (""), "#2." + nav.GetType ());
465 public void EvaluateNodeSetAsEnumerable ()
467 String xml = "<root a='value'/>";
468 XDocument d = XDocument.Parse (xml);
469 IEnumerable att = (IEnumerable) d.XPathEvaluate ("/root/@a");
470 att.Cast<XAttribute> ().FirstOrDefault ();
474 public void EvaluateNodeSetAsEnumerableOfObject ()
476 var root = XDocument.Parse("<config><item name=\"A\" /></config>");
477 Assert.IsTrue (root.XPathSelectElements ("config/*").First ().XPathEvaluate (".") is IEnumerable<object>);
481 public void RemoveDoesSnapshotCopy ()
483 var xml = XElement.Parse ("<p><n>one</n><n>two</n><n>three</n></p>");
484 xml.Elements ().Last ().NodesBeforeSelf ().Remove ();
488 public void RemoveDoesSnapshotCopy2 ()
490 var xml = XElement.Parse ("<p><n>one</n><n>two</n><n>three</n></p>");
491 xml.Elements ().First ().NodesAfterSelf ().Remove ();
492 Assert.IsTrue (!xml.ToString ().Contains ("three"), "#1");