[corlib] ExecutionContext and other contexts from reference sources. Fixes #28793...
[mono.git] / mcs / class / System.XML / Test / System.Xml.XPath / XPathNavigatorTests.cs
1 //
2 // MonoTests.System.Xml.XPathNavigatorTests
3 //
4 // Authors:
5 //   Jason Diamond <jason@injektilo.org>
6 //   Martin Willemoes Hansen <mwh@sysrq.dk>
7 //   Atsushi Enomoto <atsushi@ximian.com>
8 //
9 // (C) 2002 Jason Diamond
10 // (C) 2003 Martin Willemoes Hansen
11 // (C) 2004-2006 Novell, Inc.
12 //
13
14 using System;
15 using System.IO;
16 using System.Xml;
17 using System.Xml.XPath;
18 using System.Xml.Xsl;
19
20 using NUnit.Framework;
21
22 namespace MonoTests.System.Xml
23 {
24         [TestFixture]
25         public class XPathNavigatorTests
26         {
27                 XmlDocument document;
28                 XPathNavigator navigator;
29
30                 [SetUp]
31                 public void GetReady ()
32                 {
33                         document = new XmlDocument ();
34                 }
35                 
36                 [Test]
37                 public void CreateNavigator ()
38                 {
39                         document.LoadXml ("<foo />");
40                         navigator = document.CreateNavigator ();
41                         Assert.IsNotNull (navigator);
42                 }
43
44                 [Test]
45                 public void PropertiesOnDocument ()
46                 {
47                         document.LoadXml ("<foo:bar xmlns:foo='#foo' />");
48                         navigator = document.CreateNavigator ();
49                         
50                         Assert.AreEqual (XPathNodeType.Root, navigator.NodeType, "#1");
51                         Assert.AreEqual (String.Empty, navigator.Name, "#2");
52                         Assert.AreEqual (String.Empty, navigator.LocalName, "#3");
53                         Assert.AreEqual (String.Empty, navigator.NamespaceURI, "#4");
54                         Assert.AreEqual (String.Empty, navigator.Prefix, "#5");
55                         Assert.IsTrue (!navigator.HasAttributes, "#6");
56                         Assert.IsTrue (navigator.HasChildren, "#7");
57                         Assert.IsTrue (!navigator.IsEmptyElement, "#8");
58                 }
59
60                 [Test]
61                 public void PropertiesOnElement ()
62                 {
63                         document.LoadXml ("<foo:bar xmlns:foo='#foo' />");
64                         navigator = document.DocumentElement.CreateNavigator ();
65                         
66                         Assert.AreEqual (XPathNodeType.Element, navigator.NodeType, "#1");
67                         Assert.AreEqual ("foo:bar", navigator.Name, "#2");
68                         Assert.AreEqual ("bar", navigator.LocalName, "#3");
69                         Assert.AreEqual ("#foo", navigator.NamespaceURI, "#4");
70                         Assert.AreEqual ("foo", navigator.Prefix, "#5");
71                         Assert.IsTrue (!navigator.HasAttributes, "#6");
72                         Assert.IsTrue (!navigator.HasChildren, "#7");
73                         Assert.IsTrue (navigator.IsEmptyElement, "#8");
74                 }
75
76                 [Test]
77                 public void PropertiesOnAttribute ()
78                 {
79                         document.LoadXml ("<foo bar:baz='quux' xmlns:bar='#bar' />");
80                         navigator = document.DocumentElement.GetAttributeNode("baz", "#bar").CreateNavigator ();
81                         
82                         Assert.AreEqual (XPathNodeType.Attribute, navigator.NodeType, "#1");
83                         Assert.AreEqual ("bar:baz", navigator.Name, "#2");
84                         Assert.AreEqual ("baz", navigator.LocalName, "#3");
85                         Assert.AreEqual ("#bar", navigator.NamespaceURI, "#4");
86                         Assert.AreEqual ("bar", navigator.Prefix, "#5");
87                         Assert.IsTrue (!navigator.HasAttributes, "#6");
88                         Assert.IsTrue (!navigator.HasChildren, "#7");
89                         Assert.IsTrue (!navigator.IsEmptyElement, "#8");
90                 }
91
92                 [Test]
93                 public void PropertiesOnNamespace ()
94                 {
95                         document.LoadXml ("<root xmlns='urn:foo' />");
96                         navigator = document.DocumentElement.Attributes [0].CreateNavigator ();
97                         Assert.AreEqual (XPathNodeType.Namespace, navigator.NodeType, "#1");
98                 }
99
100                 [Test]
101                 public void Navigation ()
102                 {
103                         document.LoadXml ("<foo><bar /><baz /></foo>");
104                         navigator = document.DocumentElement.CreateNavigator ();
105                         
106                         Assert.AreEqual ("foo", navigator.Name, "#1");
107                         Assert.IsTrue (navigator.MoveToFirstChild (), "#2");
108                         Assert.AreEqual ("bar", navigator.Name, "#3");
109                         Assert.IsTrue (navigator.MoveToNext (), "#4");
110                         Assert.AreEqual ("baz", navigator.Name, "#5");
111                         Assert.IsTrue (!navigator.MoveToNext (), "#6");
112                         Assert.AreEqual ("baz", navigator.Name, "#7");
113                         Assert.IsTrue (navigator.MoveToPrevious (), "#8");
114                         Assert.AreEqual ("bar", navigator.Name, "#9");
115                         Assert.IsTrue (!navigator.MoveToPrevious (), "#10");
116                         Assert.IsTrue (navigator.MoveToParent (), "#11");
117                         Assert.AreEqual ("foo", navigator.Name, "#12");
118                         navigator.MoveToRoot ();
119                         Assert.AreEqual (XPathNodeType.Root, navigator.NodeType, "#13");
120                         Assert.IsTrue (!navigator.MoveToParent (), "#14");
121                         Assert.AreEqual (XPathNodeType.Root, navigator.NodeType, "#15");
122                         Assert.IsTrue (navigator.MoveToFirstChild (), "#16");
123                         Assert.AreEqual ("foo", navigator.Name, "#17");
124                         Assert.IsTrue (navigator.MoveToFirst (), "#18");
125                         Assert.AreEqual ("foo", navigator.Name, "#19");
126                         Assert.IsTrue (navigator.MoveToFirstChild (), "#20");
127                         Assert.AreEqual ("bar", navigator.Name, "#21");
128                         Assert.IsTrue (navigator.MoveToNext (), "#22");
129                         Assert.AreEqual ("baz", navigator.Name, "#23");
130                         Assert.IsTrue (navigator.MoveToFirst (), "#24");
131                         Assert.AreEqual ("bar", navigator.Name, "#25");
132                 }
133
134                 [Test]
135                 public void MoveToAndIsSamePosition ()
136                 {
137                         XmlDocument document1 = new XmlDocument ();
138                         document1.LoadXml ("<foo><bar /></foo>");
139                         XPathNavigator navigator1a = document1.DocumentElement.CreateNavigator ();
140                         XPathNavigator navigator1b = document1.DocumentElement.CreateNavigator ();
141
142                         XmlDocument document2 = new XmlDocument ();
143                         document2.LoadXml ("<foo><bar /></foo>");
144                         XPathNavigator navigator2 = document2.DocumentElement.CreateNavigator ();
145
146                         Assert.AreEqual ("foo", navigator1a.Name, "#1");
147                         Assert.IsTrue (navigator1a.MoveToFirstChild (), "#2");
148                         Assert.AreEqual ("bar", navigator1a.Name, "#3");
149
150                         Assert.IsTrue (!navigator1b.IsSamePosition (navigator1a), "#4");
151                         Assert.AreEqual ("foo", navigator1b.Name, "#5");
152                         Assert.IsTrue (navigator1b.MoveTo (navigator1a), "#6");
153                         Assert.IsTrue (navigator1b.IsSamePosition (navigator1a), "#7");
154                         Assert.AreEqual ("bar", navigator1b.Name, "#8");
155
156                         Assert.IsTrue (!navigator2.IsSamePosition (navigator1a), "#9");
157                         Assert.AreEqual ("foo", navigator2.Name, "#10");
158                         Assert.IsTrue (!navigator2.MoveTo (navigator1a), "#11");
159                         Assert.AreEqual ("foo", navigator2.Name, "#12");
160                 }
161
162                 [Test]
163                 public void AttributeNavigation ()
164                 {
165                         document.LoadXml ("<foo bar='baz' quux='quuux' />");
166                         navigator = document.DocumentElement.CreateNavigator ();
167
168                         Assert.AreEqual (XPathNodeType.Element, navigator.NodeType, "#1");
169                         Assert.AreEqual ("foo", navigator.Name, "#2");
170                         Assert.IsTrue (navigator.MoveToFirstAttribute (), "#3");
171                         Assert.AreEqual (XPathNodeType.Attribute, navigator.NodeType, "#4");
172                         Assert.AreEqual ("bar", navigator.Name, "#5");
173                         Assert.AreEqual ("baz", navigator.Value, "#6");
174                         Assert.IsTrue (navigator.MoveToNextAttribute (), "#7");
175                         Assert.AreEqual (XPathNodeType.Attribute, navigator.NodeType, "#8");
176                         Assert.AreEqual ("quux", navigator.Name, "#9");
177                         Assert.AreEqual ("quuux", navigator.Value, "#10");
178                 }
179
180                 [Test]
181                 public void ElementAndRootValues()
182                 {
183                         document.LoadXml ("<foo><bar>baz</bar><quux>quuux</quux></foo>");
184                         navigator = document.DocumentElement.CreateNavigator ();
185
186                         Assert.AreEqual (XPathNodeType.Element, navigator.NodeType, "#1");
187                         Assert.AreEqual ("foo", navigator.Name, "#2");
188                         //Assert.AreEqual ("bazquuux", navigator.Value, "#3");
189
190                         navigator.MoveToRoot ();
191                         //Assert.AreEqual ("bazquuux", navigator.Value, "#4");
192                 }
193
194                 [Test]
195                 public void DocumentWithXmlDeclaration ()
196                 {
197                         document.LoadXml ("<?xml version=\"1.0\" standalone=\"yes\"?><Root><foo>bar</foo></Root>");
198                         navigator = document.CreateNavigator ();
199
200                         navigator.MoveToRoot ();
201                         navigator.MoveToFirstChild ();
202                         Assert.AreEqual (XPathNodeType.Element, navigator.NodeType, "#1");
203                         Assert.AreEqual ("Root", navigator.Name, "#2");
204                 }
205
206                 [Test]
207                 public void DocumentWithProcessingInstruction ()
208                 {
209                         document.LoadXml ("<?xml-stylesheet href='foo.xsl' type='text/xsl' ?><foo />");
210                         navigator = document.CreateNavigator ();
211
212                         Assert.IsTrue (navigator.MoveToFirstChild ());
213                         Assert.AreEqual (XPathNodeType.ProcessingInstruction, navigator.NodeType, "#1");
214                         Assert.AreEqual ("xml-stylesheet", navigator.Name, "#2");
215
216                         XPathNodeIterator iter = navigator.SelectChildren (XPathNodeType.Element);
217                         Assert.AreEqual (0, iter.Count, "#3");
218                 }
219
220                 [Test]
221                 public void SelectFromOrphan ()
222                 {
223                         // SelectSingleNode () from node without parent.
224                         XmlDocument doc = new XmlDocument ();
225                         doc.LoadXml ("<foo><include id='original' /></foo>");
226
227                         XmlNode node = doc.CreateElement ("child");
228                         node.InnerXml = "<include id='new' />";
229
230                         XmlNode new_include = node.SelectSingleNode ("//include");
231                         Assert.AreEqual ("<include id=\"new\" />", new_include.OuterXml, "#1");
232
233                         // In this case 'node2' has parent 'node'
234                         doc = new XmlDocument ();
235                         doc.LoadXml ("<foo><include id='original' /></foo>");
236
237                         node = doc.CreateElement ("child");
238                         XmlNode node2 = doc.CreateElement ("grandchild");
239                         node.AppendChild (node2);
240                         node2.InnerXml = "<include id='new' />";
241
242                         new_include = node2.SelectSingleNode ("/");
243                         Assert.AreEqual ("<child><grandchild><include id=\"new\" /></grandchild></child>",
244                                 new_include.OuterXml, "#2");
245                 }
246
247                 [Test]
248                 public void XPathDocumentMoveToId ()
249                 {
250                         string dtd = "<!DOCTYPE root [<!ELEMENT root EMPTY><!ATTLIST root id ID #REQUIRED>]>";
251                         string xml = dtd + "<root id='aaa'/>";
252                         StringReader sr = new StringReader (xml);
253                         XPathNavigator nav = new XPathDocument (sr).CreateNavigator ();
254                         Assert.IsTrue (nav.MoveToId ("aaa"), "ctor() from TextReader");
255
256                         XmlValidatingReader xvr = new XmlValidatingReader (xml, XmlNodeType.Document, null);
257                         nav = new XPathDocument (xvr).CreateNavigator ();
258                         Assert.IsTrue (nav.MoveToId ("aaa"), "ctor() from XmlValidatingReader");
259
260                         // FIXME: it seems to result in different in .NET 2.0.
261                 }
262
263                 [Test]
264                 public void SignificantWhitespaceConstruction ()
265                 {
266                         string xml = @"<root>
267         <child xml:space='preserve'>    <!-- -->   </child>
268         <child xml:space='preserve'>    </child>
269 </root>";
270                         XPathNavigator nav = new XPathDocument (
271                                 new XmlTextReader (xml, XmlNodeType.Document, null),
272                                 XmlSpace.Preserve).CreateNavigator ();
273                         nav.MoveToFirstChild ();
274                         nav.MoveToFirstChild ();
275                         Assert.AreEqual (XPathNodeType.Whitespace, nav.NodeType, "#1");
276                         nav.MoveToNext ();
277                         nav.MoveToFirstChild ();
278                         Assert.AreEqual (XPathNodeType.SignificantWhitespace,
279                                 nav.NodeType, "#2");
280                 }
281
282                 [Test]
283                 public void VariableReference ()
284                 {
285                         XPathDocument xpd = new XPathDocument (
286                                 new StringReader ("<root>sample text</root>"));
287                         XPathNavigator nav = xpd.CreateNavigator ();
288
289                         XPathExpression expr = nav.Compile ("foo(string(.),$idx)");
290                         XsltArgumentList args = new XsltArgumentList ();
291                         args.AddParam ("idx", "", 5);
292                         MyContext ctx = new MyContext (nav.NameTable as NameTable, args);
293                         ctx.AddNamespace ("x", "urn:foo");
294
295                         expr.SetContext (ctx);
296
297                         XPathNodeIterator iter = nav.Select ("/root");
298                         iter.MoveNext ();
299                         Assert.AreEqual ("e", iter.Current.Evaluate (expr), "#1");
300                 }
301
302                 class MyContext : XsltContext
303                 {
304                         XsltArgumentList args;
305
306                         public MyContext (NameTable nt, XsltArgumentList args)
307                                 : base (nt)
308                         {
309                                 this.args = args;
310                         }
311
312                         public override IXsltContextFunction ResolveFunction (
313                                 string prefix, string name, XPathResultType [] argtypes)
314                         {
315                                 if (name == "foo")
316                                         return new MyFunction (argtypes);
317                                 return null;
318                         }
319
320                         public override IXsltContextVariable ResolveVariable (string prefix, string name)
321                         {
322                                 return new MyVariable (name);
323                         }
324
325                         public override bool PreserveWhitespace (XPathNavigator nav)
326                         {
327                                 return false;
328                         }
329
330                         public override int CompareDocument (string uri1, string uri2)
331                         {
332                                 return String.CompareOrdinal (uri1, uri2);
333                         }
334
335                         public override bool Whitespace {
336                                 get { return false; }
337                         }
338
339                         public object GetParam (string name, string ns)
340                         {
341                                 return args.GetParam (name, ns);
342                         }
343                 }
344
345                 public class MyFunction : IXsltContextFunction
346                 {
347                         XPathResultType [] argtypes;
348
349                         public MyFunction (XPathResultType [] argtypes)
350                         {
351                                 this.argtypes = argtypes;
352                         }
353
354                         public XPathResultType [] ArgTypes {
355                                 get { return argtypes; }
356                         }
357
358                         public int Maxargs {
359                                 get { return 2; }
360                         }
361
362                         public int Minargs {
363                                 get { return 2; }
364                         }
365
366                         public XPathResultType ReturnType {
367                                 get { return XPathResultType.String; }
368                         }
369
370                         public object Invoke (XsltContext xsltContext,
371                                 object [] args, XPathNavigator instanceContext)
372                         {
373                                 return ((string) args [0]) [(int) (double) args [1]].ToString ();
374                         }
375                 }
376
377                 public class MyVariable : IXsltContextVariable
378                 {
379                         string name;
380
381                         public MyVariable (string name)
382                         {
383                                 this.name = name;
384                         }
385
386                         public object Evaluate (XsltContext ctx)
387                         {
388                                 return ((MyContext) ctx).GetParam (name, String.Empty);
389                         }
390
391                         public bool IsLocal {
392                                 get { return false; }
393                         }
394
395                         public bool IsParam {
396                                 get { return false; }
397                         }
398
399                         public XPathResultType VariableType {
400                                 get { return XPathResultType.Any; }
401                         }
402                 }
403
404                 [Test]
405                 public void TextMatchesWhitespace ()
406                 {
407                         string xml = "<root><ws>   </ws><sws xml:space='preserve'> </sws></root>";
408                         XmlDocument doc = new XmlDocument ();
409                         doc.PreserveWhitespace = true;
410                         doc.LoadXml (xml);
411                         XPathNavigator nav = doc.CreateNavigator ();
412                         nav.MoveToFirstChild (); // root
413                         nav.MoveToFirstChild (); // ws
414                         nav.MoveToFirstChild (); // '   '
415                         Assert.AreEqual (true, nav.Matches ("text()"), "#1");
416                         nav.MoveToParent ();
417                         nav.MoveToNext (); // sws
418                         nav.MoveToFirstChild (); // ' '
419                         Assert.AreEqual (true, nav.Matches ("text()"), "#2");
420                 }
421
422                 [Test]
423                 public void Bug456103 ()
424                 {
425                         XmlDocument doc = new XmlDocument ();
426                         doc.LoadXml ("<root><X/></root>");
427
428                         XPathNavigator nav = doc.DocumentElement.CreateNavigator ();
429                         // ".//*" does not reproduce the bug.
430                         var i = nav.Select ("descendant::*");
431
432                         // without this call to get_Count() the bug does not reproduce.
433                         Assert.AreEqual (1, i.Count, "#1");
434
435                         Assert.IsTrue (i.MoveNext (), "#2");
436                 }
437
438                 [Test]
439                 public void ValueAsBoolean ()
440                 {
441                         string xml = "<root>1</root>";
442                         XmlDocument doc = new XmlDocument ();
443                         doc.LoadXml (xml);
444                         XPathNavigator nav = doc.CreateNavigator ();
445                         nav.MoveToFirstChild ();
446                         Assert.AreEqual (true, nav.ValueAsBoolean, "#1");
447                         nav.MoveToFirstChild ();
448                         Assert.AreEqual (true, nav.ValueAsBoolean, "#2");
449                 }
450
451                 [Test]
452                 [ExpectedException (typeof (FormatException))]
453                 public void ValueAsBooleanFail ()
454                 {
455                         string xml = "<root>1.0</root>";
456                         XmlDocument doc = new XmlDocument ();
457                         doc.LoadXml (xml);
458                         XPathNavigator nav = doc.CreateNavigator ();
459                         nav.MoveToFirstChild ();
460                         bool i = nav.ValueAsBoolean;
461                 }
462
463                 [Test]
464                 public void ValueAsDateTime ()
465                 {
466                         DateTime time = new DateTime (2005, 12, 13);
467                         string xml = "<root>2005-12-13</root>";
468                         XmlDocument doc = new XmlDocument ();
469                         doc.LoadXml (xml);
470                         XPathNavigator nav = doc.CreateNavigator ();
471                         nav.MoveToFirstChild ();
472                         Assert.AreEqual (time, nav.ValueAsDateTime, "#1");
473                         nav.MoveToFirstChild ();
474                         Assert.AreEqual (time, nav.ValueAsDateTime, "#2");
475                 }
476
477                 [Test]
478                 [ExpectedException (typeof (FormatException))]
479                 public void ValueAsDateTimeFail ()
480                 {
481                         string xml = "<root>dating time</root>";
482                         XmlDocument doc = new XmlDocument ();
483                         doc.LoadXml (xml);
484                         XPathNavigator nav = doc.CreateNavigator ();
485                         nav.MoveToFirstChild ();
486                         DateTime time = nav.ValueAsDateTime;
487                 }
488
489                 [Test]
490                 public void ValueAsDouble ()
491                 {
492                         string xml = "<root>3.14159265359</root>";
493                         XmlDocument doc = new XmlDocument ();
494                         doc.LoadXml (xml);
495                         XPathNavigator nav = doc.CreateNavigator ();
496                         nav.MoveToFirstChild ();
497                         Assert.AreEqual (3.14159265359, nav.ValueAsDouble, "#1");
498                         nav.MoveToFirstChild ();
499                         Assert.AreEqual (3.14159265359, nav.ValueAsDouble, "#2");
500                 }
501
502                 [Test]
503                 [ExpectedException (typeof (FormatException))]
504                 public void ValueAsDoubleFail ()
505                 {
506                         string xml = "<root>Double Dealer</root>";
507                         XmlDocument doc = new XmlDocument ();
508                         doc.LoadXml (xml);
509                         XPathNavigator nav = doc.CreateNavigator ();
510                         nav.MoveToFirstChild ();
511                         Double dealer = nav.ValueAsDouble;
512                 }
513
514                 [Test]
515                 public void ValueAsInt ()
516                 {
517                         string xml = "<root>1</root>";
518                         XmlDocument doc = new XmlDocument ();
519                         doc.LoadXml (xml);
520                         XPathNavigator nav = doc.CreateNavigator ();
521                         nav.MoveToFirstChild ();
522                         Assert.AreEqual (1, nav.ValueAsInt, "#1");
523                         nav.MoveToFirstChild ();
524                         Assert.AreEqual (1, nav.ValueAsInt, "#2");
525                 }
526
527                 [Test]
528                 // Here, it seems to be using XQueryConvert (whatever was called)
529                 [ExpectedException (typeof (FormatException))]
530                 public void ValueAsIntFail ()
531                 {
532                         string xml = "<root>1.0</root>";
533                         XmlDocument doc = new XmlDocument ();
534                         doc.LoadXml (xml);
535                         XPathNavigator nav = doc.CreateNavigator ();
536                         nav.MoveToFirstChild ();
537                         int i = nav.ValueAsInt;
538                 }
539
540                 [Test]
541                 public void ValueAsLong ()
542                 {
543                         string xml = "<root>10000000000000000</root>";
544                         XmlDocument doc = new XmlDocument ();
545                         doc.LoadXml (xml);
546                         XPathNavigator nav = doc.CreateNavigator ();
547                         nav.MoveToFirstChild ();
548                         Assert.AreEqual (10000000000000000, nav.ValueAsLong, "#1");
549                         nav.MoveToFirstChild ();
550                         Assert.AreEqual (10000000000000000, nav.ValueAsLong, "#2");
551                 }
552
553                 [Test]
554                 // Here, it seems to be using XQueryConvert (whatever was called)
555                 [ExpectedException (typeof (FormatException))]
556                 public void ValueAsLongFail ()
557                 {
558                         string xml = "<root>0x10000000000000000</root>";
559                         XmlDocument doc = new XmlDocument ();
560                         doc.LoadXml (xml);
561                         XPathNavigator nav = doc.CreateNavigator ();
562                         nav.MoveToFirstChild ();
563                         long l = nav.ValueAsLong;
564                 }
565
566                 [Test] // bug #79874
567                 public void InnerXmlText ()
568                 {
569                         StringReader sr = new StringReader ("<Abc><Foo>Hello</Foo></Abc>");
570                         XPathDocument doc = new XPathDocument (sr);
571                         XPathNavigator nav = doc.CreateNavigator ();
572                         XPathNodeIterator iter = nav.Select ("/Abc/Foo");
573                         iter.MoveNext ();
574                         Assert.AreEqual ("Hello", iter.Current.InnerXml, "#1");
575                         Assert.AreEqual ("<Foo>Hello</Foo>", iter.Current.OuterXml, "#2");
576                         iter = nav.Select ("/Abc/Foo/text()");
577                         iter.MoveNext ();
578                         Assert.AreEqual (String.Empty, iter.Current.InnerXml, "#3");
579                         Assert.AreEqual ("Hello", iter.Current.OuterXml, "#4");
580                 }
581
582                 [Test] // bug #79875
583                 public void InnerXmlAttribute ()
584                 {
585                         StringReader sr = new StringReader ("<Abc><Foo attr='val1'/></Abc>");
586                         XPathDocument doc = new XPathDocument (sr);
587                         XPathNavigator nav = doc.CreateNavigator ();
588
589                         XPathNodeIterator iter = nav.Select ("/Abc/Foo/@attr");
590                         iter.MoveNext ();
591                         Assert.AreEqual ("val1", iter.Current.InnerXml, "#1");
592                 }
593
594                 string AlterNewLine (string s)
595                 {
596                         return s.Replace ("\r\n", Environment.NewLine);
597                 }
598
599                 [Test]
600                 public void InnerXmlTextEscape ()
601                 {
602                         StringReader sr = new StringReader ("<Abc><Foo>Hello&lt;\r\nInnerXml</Foo></Abc>");
603                         XPathDocument doc = new XPathDocument (sr);
604                         XPathNavigator nav = doc.CreateNavigator ();
605                         XPathNodeIterator iter = nav.Select ("/Abc/Foo");
606                         iter.MoveNext ();
607                         Assert.AreEqual (AlterNewLine ("Hello&lt;\r\nInnerXml"), iter.Current.InnerXml, "#1");
608                         Assert.AreEqual (AlterNewLine ("<Foo>Hello&lt;\r\nInnerXml</Foo>"), iter.Current.OuterXml, "#2");
609                         iter = nav.Select ("/Abc/Foo/text()");
610                         iter.MoveNext ();
611                         Assert.AreEqual (String.Empty, iter.Current.InnerXml, "#3");
612                         Assert.AreEqual (AlterNewLine ("Hello&lt;\r\nInnerXml"), iter.Current.OuterXml, "#4");
613                 }
614
615                 [Test]
616                 [Category ("NotDotNet")] // .NET bug; it should escape value
617                 [Ignore ("Bug in Microsoft reference source")]
618                 public void InnerXmlAttributeEscape ()
619                 {
620                         StringReader sr = new StringReader ("<Abc><Foo attr='val&quot;1&#13;&#10;&gt;'/></Abc>");
621                         XPathDocument doc = new XPathDocument (sr);
622                         XPathNavigator nav = doc.CreateNavigator ();
623
624                         XPathNodeIterator iter = nav.Select ("/Abc/Foo/@attr");
625                         iter.MoveNext ();
626                         Assert.AreEqual ("val&quot;1&#10;&gt;", iter.Current.InnerXml, "#1");
627                 }
628
629                 [Test]
630                 public void WriterAttributePrefix ()
631                 {
632                         XmlDocument doc = new XmlDocument ();
633                         XmlWriter w = doc.CreateNavigator ().AppendChild ();
634                         w.WriteStartElement ("foo");
635                         w.WriteAttributeString ("xmlns", "x", "http://www.w3.org/2000/xmlns/", "urn:foo");
636                         Assert.AreEqual ("x", w.LookupPrefix ("urn:foo"), "#0");
637                         w.WriteStartElement (null, "bar", "urn:foo");
638                         w.WriteAttributeString (null, "ext", "urn:foo", "bah");
639                         w.WriteEndElement ();
640                         w.WriteEndElement ();
641                         w.Close ();
642                         Assert.AreEqual ("x", doc.FirstChild.FirstChild.Prefix, "#1");
643                         Assert.AreEqual ("x", doc.FirstChild.FirstChild.Attributes [0].Prefix, "#2");
644                 }
645
646                 [Test]
647                 public void ValueAs ()
648                 {
649                         string xml = "<root>1</root>";
650                         XPathNavigator nav = new XPathDocument (XmlReader.Create (new StringReader (xml))).CreateNavigator ();
651                         nav.MoveToFirstChild ();
652                         nav.MoveToFirstChild ();
653                         Assert.AreEqual ("1", nav.ValueAs (typeof (string), null), "#1");
654                         Assert.AreEqual (1, nav.ValueAs (typeof (int), null), "#2");
655                 }
656
657                 [Test]
658                 public void MoveToFollowingNodeTypeAll ()
659                 {
660                         XmlDocument doc = new XmlDocument ();
661                         doc.LoadXml ("<root><child/><child2/></root>");
662                         XPathNavigator nav = doc.CreateNavigator ();
663                         Assert.IsTrue (nav.MoveToFollowing (XPathNodeType.All), "#1");
664                         Assert.IsTrue (nav.MoveToFollowing (XPathNodeType.All), "#2");
665                         Assert.AreEqual ("child", nav.LocalName, "#3");
666                         Assert.IsTrue (nav.MoveToNext (XPathNodeType.All), "#4");
667                         Assert.AreEqual ("child2", nav.LocalName, "#5");
668                 }
669
670                 [Test] // bug #324606.
671                 public void XPathDocumentFromSubtreeNodes ()
672                 {
673                         string xml = "<root><child1><nest1><nest2>hello!</nest2></nest1></child1><child2/><child3/></root>";
674                         XmlReader r = new XmlTextReader (new StringReader (xml));
675                         while (r.Read ()) {
676                                 if (r.Name == "child1")
677                                         break;
678                         }
679                         XPathDocument d = new XPathDocument (r);
680                         XPathNavigator n = d.CreateNavigator ();
681                         string result = @"<child1>
682   <nest1>
683     <nest2>hello!</nest2>
684   </nest1>
685 </child1>
686 <child2 />
687 <child3 />";
688                         Assert.AreEqual (result, n.OuterXml.Replace ("\r\n", "\n"), "#1");
689                 }
690
691                 [Test] // bug #376191
692                 public void InnerXmlOnRoot ()
693                 {
694                         XmlDocument document = new XmlDocument ();
695                         document.LoadXml (@"<test>
696                         <node>z</node>
697                         <node>a</node>
698                         <node>b</node>
699                         <node>q</node>
700                         </test>");
701                         XPathNavigator navigator = document.CreateNavigator();
702                         Assert.AreEqual (navigator.OuterXml, navigator.InnerXml, "#1");
703                 }
704
705                 [Test] // bug #515136
706                 public void SelectChildrenEmpty ()
707                 {
708                         string s = "<root> <foo> </foo> </root>";
709                         XPathDocument doc = new XPathDocument (new StringReader (s));
710                         XPathNavigator nav = doc.CreateNavigator ();
711                         XPathNodeIterator it = nav.SelectChildren (String.Empty, String.Empty);
712                         foreach (XPathNavigator xpn in it)
713                                 return;
714                         Assert.Fail ("no selection");
715                 }
716         }
717 }