2 // MonoTests.System.Xml.XPathNavigatorTests
5 // Jason Diamond <jason@injektilo.org>
6 // Martin Willemoes Hansen <mwh@sysrq.dk>
8 // (C) 2002 Jason Diamond
9 // (C) 2003 Martin Willemoes Hansen
15 using System.Xml.XPath;
18 using NUnit.Framework;
20 namespace MonoTests.System.Xml
23 public class XPathNavigatorTests : Assertion
26 XPathNavigator navigator;
29 public void GetReady ()
31 document = new XmlDocument ();
35 public void CreateNavigator ()
37 document.LoadXml ("<foo />");
38 navigator = document.CreateNavigator ();
39 AssertNotNull (navigator);
43 public void PropertiesOnDocument ()
45 document.LoadXml ("<foo:bar xmlns:foo='#foo' />");
46 navigator = document.CreateNavigator ();
48 AssertEquals (XPathNodeType.Root, navigator.NodeType);
49 AssertEquals (String.Empty, navigator.Name);
50 AssertEquals (String.Empty, navigator.LocalName);
51 AssertEquals (String.Empty, navigator.NamespaceURI);
52 AssertEquals (String.Empty, navigator.Prefix);
53 Assert (!navigator.HasAttributes);
54 Assert (navigator.HasChildren);
55 Assert (!navigator.IsEmptyElement);
59 public void PropertiesOnElement ()
61 document.LoadXml ("<foo:bar xmlns:foo='#foo' />");
62 navigator = document.DocumentElement.CreateNavigator ();
64 AssertEquals (XPathNodeType.Element, navigator.NodeType);
65 AssertEquals ("foo:bar", navigator.Name);
66 AssertEquals ("bar", navigator.LocalName);
67 AssertEquals ("#foo", navigator.NamespaceURI);
68 AssertEquals ("foo", navigator.Prefix);
69 Assert (!navigator.HasAttributes);
70 Assert (!navigator.HasChildren);
71 Assert (navigator.IsEmptyElement);
75 public void PropertiesOnAttribute ()
77 document.LoadXml ("<foo bar:baz='quux' xmlns:bar='#bar' />");
78 navigator = document.DocumentElement.GetAttributeNode("baz", "#bar").CreateNavigator ();
80 AssertEquals (XPathNodeType.Attribute, navigator.NodeType);
81 AssertEquals ("bar:baz", navigator.Name);
82 AssertEquals ("baz", navigator.LocalName);
83 AssertEquals ("#bar", navigator.NamespaceURI);
84 AssertEquals ("bar", navigator.Prefix);
85 Assert (!navigator.HasAttributes);
86 Assert (!navigator.HasChildren);
87 Assert (!navigator.IsEmptyElement);
91 public void PropertiesOnNamespace ()
93 document.LoadXml ("<root xmlns='urn:foo' />");
\r
94 navigator = document.DocumentElement.Attributes [0].CreateNavigator ();
\r
95 AssertEquals (XPathNodeType.Namespace, navigator.NodeType);
99 public void Navigation ()
101 document.LoadXml ("<foo><bar /><baz /></foo>");
102 navigator = document.DocumentElement.CreateNavigator ();
104 AssertEquals ("foo", navigator.Name);
105 Assert (navigator.MoveToFirstChild ());
106 AssertEquals ("bar", navigator.Name);
107 Assert (navigator.MoveToNext ());
108 AssertEquals ("baz", navigator.Name);
109 Assert (!navigator.MoveToNext ());
110 AssertEquals ("baz", navigator.Name);
111 Assert (navigator.MoveToPrevious ());
112 AssertEquals ("bar", navigator.Name);
113 Assert (!navigator.MoveToPrevious ());
114 Assert (navigator.MoveToParent ());
115 AssertEquals ("foo", navigator.Name);
116 navigator.MoveToRoot ();
117 AssertEquals (XPathNodeType.Root, navigator.NodeType);
118 Assert (!navigator.MoveToParent ());
119 AssertEquals (XPathNodeType.Root, navigator.NodeType);
120 Assert (navigator.MoveToFirstChild ());
121 AssertEquals ("foo", navigator.Name);
122 Assert (navigator.MoveToFirst ());
123 AssertEquals ("foo", navigator.Name);
124 Assert (navigator.MoveToFirstChild ());
125 AssertEquals ("bar", navigator.Name);
126 Assert (navigator.MoveToNext ());
127 AssertEquals ("baz", navigator.Name);
128 Assert (navigator.MoveToFirst ());
129 AssertEquals ("bar", navigator.Name);
133 public void MoveToAndIsSamePosition ()
135 XmlDocument document1 = new XmlDocument ();
136 document1.LoadXml ("<foo><bar /></foo>");
137 XPathNavigator navigator1a = document1.DocumentElement.CreateNavigator ();
138 XPathNavigator navigator1b = document1.DocumentElement.CreateNavigator ();
140 XmlDocument document2 = new XmlDocument ();
141 document2.LoadXml ("<foo><bar /></foo>");
142 XPathNavigator navigator2 = document2.DocumentElement.CreateNavigator ();
144 AssertEquals ("foo", navigator1a.Name);
145 Assert (navigator1a.MoveToFirstChild ());
146 AssertEquals ("bar", navigator1a.Name);
148 Assert (!navigator1b.IsSamePosition (navigator1a));
149 AssertEquals ("foo", navigator1b.Name);
150 Assert (navigator1b.MoveTo (navigator1a));
151 Assert (navigator1b.IsSamePosition (navigator1a));
152 AssertEquals ("bar", navigator1b.Name);
154 Assert (!navigator2.IsSamePosition (navigator1a));
155 AssertEquals ("foo", navigator2.Name);
156 Assert (!navigator2.MoveTo (navigator1a));
157 AssertEquals ("foo", navigator2.Name);
161 public void AttributeNavigation ()
163 document.LoadXml ("<foo bar='baz' quux='quuux' />");
164 navigator = document.DocumentElement.CreateNavigator ();
166 AssertEquals (XPathNodeType.Element, navigator.NodeType);
167 AssertEquals ("foo", navigator.Name);
168 Assert (navigator.MoveToFirstAttribute ());
169 AssertEquals (XPathNodeType.Attribute, navigator.NodeType);
170 AssertEquals ("bar", navigator.Name);
171 AssertEquals ("baz", navigator.Value);
172 Assert (navigator.MoveToNextAttribute ());
173 AssertEquals (XPathNodeType.Attribute, navigator.NodeType);
174 AssertEquals ("quux", navigator.Name);
175 AssertEquals ("quuux", navigator.Value);
179 public void ElementAndRootValues()
181 document.LoadXml ("<foo><bar>baz</bar><quux>quuux</quux></foo>");
182 navigator = document.DocumentElement.CreateNavigator ();
184 AssertEquals (XPathNodeType.Element, navigator.NodeType);
185 AssertEquals ("foo", navigator.Name);
186 //AssertEquals ("bazquuux", navigator.Value);
188 navigator.MoveToRoot ();
189 //AssertEquals ("bazquuux", navigator.Value);
193 public void DocumentWithXmlDeclaration ()
195 document.LoadXml ("<?xml version=\"1.0\" standalone=\"yes\"?><Root><foo>bar</foo></Root>");
196 navigator = document.CreateNavigator ();
198 navigator.MoveToRoot ();
199 navigator.MoveToFirstChild ();
200 AssertEquals (XPathNodeType.Element, navigator.NodeType);
201 AssertEquals ("Root", navigator.Name);
205 public void DocumentWithProcessingInstruction ()
207 document.LoadXml ("<?xml-stylesheet href='foo.xsl' type='text/xsl' ?><foo />");
208 navigator = document.CreateNavigator ();
210 Assert (navigator.MoveToFirstChild ());
211 AssertEquals (XPathNodeType.ProcessingInstruction, navigator.NodeType);
212 AssertEquals ("xml-stylesheet", navigator.Name);
214 XPathNodeIterator iter = navigator.SelectChildren (XPathNodeType.Element);
215 AssertEquals (0, iter.Count);
219 public void SelectFromOrphan ()
221 // SelectSingleNode () from node without parent.
222 XmlDocument doc = new XmlDocument ();
223 doc.LoadXml ("<foo><include id='original' /></foo>");
225 XmlNode node = doc.CreateElement ("child");
226 node.InnerXml = "<include id='new' />";
228 XmlNode new_include = node.SelectSingleNode ("//include");
229 AssertEquals ("<include id=\"new\" />", new_include.OuterXml);
231 // In this case 'node2' has parent 'node'
232 doc = new XmlDocument ();
233 doc.LoadXml ("<foo><include id='original' /></foo>");
235 node = doc.CreateElement ("child");
236 XmlNode node2 = doc.CreateElement ("grandchild");
237 node.AppendChild (node2);
238 node2.InnerXml = "<include id='new' />";
240 new_include = node2.SelectSingleNode ("/");
241 AssertEquals ("<child><grandchild><include id=\"new\" /></grandchild></child>",
242 new_include.OuterXml);
246 public void XPathDocumentMoveToId ()
248 string dtd = "<!DOCTYPE root [<!ELEMENT root EMPTY><!ATTLIST root id ID #REQUIRED>]>";
\r
249 string xml = dtd + "<root id='aaa'/>";
\r
250 StringReader sr = new StringReader (xml);
\r
251 XPathNavigator nav = new XPathDocument (sr).CreateNavigator ();
\r
252 Assert ("ctor() from TextReader", nav.MoveToId ("aaa"));
\r
254 XmlValidatingReader xvr = new XmlValidatingReader (xml, XmlNodeType.Document, null);
\r
255 nav = new XPathDocument (xvr).CreateNavigator ();
\r
256 Assert ("ctor() from XmlValidatingReader", nav.MoveToId ("aaa"));
\r
258 // FIXME: it seems to result in different in .NET 2.0.
261 // When it is XmlTextReader, XPathDocument fails.
262 XmlTextReader xtr = new XmlTextReader (xml, XmlNodeType.Document, null);
\r
263 nav = new XPathDocument (xtr).CreateNavigator ();
\r
264 Assert ("ctor() from XmlTextReader", !nav.MoveToId ("aaa"));
\r
270 public void SignificantWhitespaceConstruction ()
272 string xml = @"<root>
273 <child xml:space='preserve'> <!-- --> </child>
274 <child xml:space='preserve'> </child>
276 XPathNavigator nav = new XPathDocument (
277 new XmlTextReader (xml, XmlNodeType.Document, null),
278 XmlSpace.Preserve).CreateNavigator ();
279 nav.MoveToFirstChild ();
280 nav.MoveToFirstChild ();
281 AssertEquals ("#1", XPathNodeType.Whitespace, nav.NodeType);
283 nav.MoveToFirstChild ();
284 AssertEquals ("#2", XPathNodeType.SignificantWhitespace,
289 public void VariableReference ()
291 XPathDocument xpd = new XPathDocument (
292 new StringReader ("<root>sample text</root>"));
293 XPathNavigator nav = xpd.CreateNavigator ();
295 XPathExpression expr = nav.Compile ("foo(string(.),$idx)");
296 XsltArgumentList args = new XsltArgumentList ();
297 args.AddParam ("idx", "", 5);
298 MyContext ctx = new MyContext (nav.NameTable as NameTable, args);
299 ctx.AddNamespace ("x", "urn:foo");
301 expr.SetContext (ctx);
303 XPathNodeIterator iter = nav.Select ("/root");
305 AssertEquals ("e", iter.Current.Evaluate (expr));
308 class MyContext : XsltContext
310 XsltArgumentList args;
312 public MyContext (NameTable nt, XsltArgumentList args)
318 public override IXsltContextFunction ResolveFunction (
319 string prefix, string name, XPathResultType [] argtypes)
322 return new MyFunction (argtypes);
326 public override IXsltContextVariable ResolveVariable (string prefix, string name)
328 return new MyVariable (name);
331 public override bool PreserveWhitespace (XPathNavigator nav)
336 public override int CompareDocument (string uri1, string uri2)
338 return String.CompareOrdinal (uri1, uri2);
341 public override bool Whitespace {
342 get { return false; }
345 public object GetParam (string name, string ns)
347 return args.GetParam (name, ns);
351 public class MyFunction : IXsltContextFunction
353 XPathResultType [] argtypes;
355 public MyFunction (XPathResultType [] argtypes)
357 this.argtypes = argtypes;
360 public XPathResultType [] ArgTypes {
361 get { return argtypes; }
372 public XPathResultType ReturnType {
373 get { return XPathResultType.String; }
376 public object Invoke (XsltContext xsltContext,
377 object [] args, XPathNavigator instanceContext)
379 return ((string) args [0]) [(int) (double) args [1]].ToString ();
383 public class MyVariable : IXsltContextVariable
387 public MyVariable (string name)
392 public object Evaluate (XsltContext ctx)
394 return ((MyContext) ctx).GetParam (name, String.Empty);
397 public bool IsLocal {
398 get { return false; }
401 public bool IsParam {
402 get { return false; }
405 public XPathResultType VariableType {
406 get { return XPathResultType.Any; }
412 public void ValueAsBoolean ()
414 string xml = "<root>1</root>";
415 XmlDocument doc = new XmlDocument ();
417 XPathNavigator nav = doc.CreateNavigator ();
418 nav.MoveToFirstChild ();
419 AssertEquals ("#1", true, nav.ValueAsBoolean);
420 nav.MoveToFirstChild ();
421 AssertEquals ("#2", true, nav.ValueAsBoolean);
425 [ExpectedException (typeof (FormatException))]
426 public void ValueAsBooleanFail ()
428 string xml = "<root>1.0</root>";
429 XmlDocument doc = new XmlDocument ();
431 XPathNavigator nav = doc.CreateNavigator ();
432 nav.MoveToFirstChild ();
433 bool i = nav.ValueAsBoolean;
437 public void ValueAsDateTime ()
439 DateTime time = new DateTime (2005, 12, 13);
440 string xml = "<root>2005-12-13</root>";
441 XmlDocument doc = new XmlDocument ();
443 XPathNavigator nav = doc.CreateNavigator ();
444 nav.MoveToFirstChild ();
445 AssertEquals ("#1", time, nav.ValueAsDateTime);
446 nav.MoveToFirstChild ();
447 AssertEquals ("#2", time, nav.ValueAsDateTime);
451 [ExpectedException (typeof (FormatException))]
452 public void ValueAsDateTimeFail ()
454 string xml = "<root>dating time</root>";
455 XmlDocument doc = new XmlDocument ();
457 XPathNavigator nav = doc.CreateNavigator ();
458 nav.MoveToFirstChild ();
459 DateTime time = nav.ValueAsDateTime;
463 public void ValueAsDouble ()
465 string xml = "<root>3.14159265359</root>";
466 XmlDocument doc = new XmlDocument ();
468 XPathNavigator nav = doc.CreateNavigator ();
469 nav.MoveToFirstChild ();
470 AssertEquals ("#1", 3.14159265359, nav.ValueAsDouble);
471 nav.MoveToFirstChild ();
472 AssertEquals ("#2", 3.14159265359, nav.ValueAsDouble);
476 [ExpectedException (typeof (FormatException))]
477 public void ValueAsDoubleFail ()
479 string xml = "<root>Double Dealer</root>";
480 XmlDocument doc = new XmlDocument ();
482 XPathNavigator nav = doc.CreateNavigator ();
483 nav.MoveToFirstChild ();
484 Double dealer = nav.ValueAsDouble;
488 public void ValueAsInt ()
490 string xml = "<root>1</root>";
491 XmlDocument doc = new XmlDocument ();
493 XPathNavigator nav = doc.CreateNavigator ();
494 nav.MoveToFirstChild ();
495 AssertEquals ("#1", 1, nav.ValueAsInt);
496 nav.MoveToFirstChild ();
497 AssertEquals ("#2", 1, nav.ValueAsInt);
501 // Here, it seems to be using XQueryConvert (whatever was called)
502 [ExpectedException (typeof (FormatException))]
503 public void ValueAsIntFail ()
505 string xml = "<root>1.0</root>";
506 XmlDocument doc = new XmlDocument ();
508 XPathNavigator nav = doc.CreateNavigator ();
509 nav.MoveToFirstChild ();
510 int i = nav.ValueAsInt;
514 public void ValueAsLong ()
516 string xml = "<root>10000000000000000</root>";
517 XmlDocument doc = new XmlDocument ();
519 XPathNavigator nav = doc.CreateNavigator ();
520 nav.MoveToFirstChild ();
521 AssertEquals ("#1", 10000000000000000, nav.ValueAsLong);
522 nav.MoveToFirstChild ();
523 AssertEquals ("#2", 10000000000000000, nav.ValueAsLong);
527 // Here, it seems to be using XQueryConvert (whatever was called)
528 [ExpectedException (typeof (FormatException))]
529 public void ValueAsLongFail ()
531 string xml = "<root>0x10000000000000000</root>";
532 XmlDocument doc = new XmlDocument ();
534 XPathNavigator nav = doc.CreateNavigator ();
535 nav.MoveToFirstChild ();
536 long l = nav.ValueAsLong;
540 public void InnerXmlText ()
542 StringReader sr = new StringReader ("<Abc><Foo>Hello</Foo></Abc>");
543 XPathDocument doc = new XPathDocument (sr);
544 XPathNavigator nav = doc.CreateNavigator ();
545 XPathNodeIterator iter = nav.Select ("/Abc/Foo");
547 AssertEquals ("#1", "Hello", iter.Current.InnerXml);
548 AssertEquals ("#2", "<Foo>Hello</Foo>", iter.Current.OuterXml);
549 iter = nav.Select ("/Abc/Foo/text()");
551 AssertEquals ("#3", String.Empty, iter.Current.InnerXml);
552 AssertEquals ("#4", "Hello", iter.Current.OuterXml);
556 public void InnerXmlAttribute ()
558 StringReader sr = new StringReader ("<Abc><Foo attr='val1'/></Abc>");
559 XPathDocument doc = new XPathDocument (sr);
560 XPathNavigator nav = doc.CreateNavigator ();
562 XPathNodeIterator iter = nav.Select ("/Abc/Foo/@attr");
564 AssertEquals ("val1", iter.Current.InnerXml);
568 public void InnerXmlTextEscape ()
570 StringReader sr = new StringReader ("<Abc><Foo>Hello<\r\nInnerXml</Foo></Abc>");
571 XPathDocument doc = new XPathDocument (sr);
572 XPathNavigator nav = doc.CreateNavigator ();
573 XPathNodeIterator iter = nav.Select ("/Abc/Foo");
575 AssertEquals ("#1", "Hello<\r\nInnerXml", iter.Current.InnerXml);
576 AssertEquals ("#2", "<Foo>Hello<\r\nInnerXml</Foo>", iter.Current.OuterXml);
577 iter = nav.Select ("/Abc/Foo/text()");
579 AssertEquals ("#3", String.Empty, iter.Current.InnerXml);
580 AssertEquals ("#4", "Hello<\r\nInnerXml", iter.Current.OuterXml);
584 [Category ("NotDotNet")] // .NET bug; it should escape value
585 public void InnerXmlAttributeEscape ()
587 StringReader sr = new StringReader ("<Abc><Foo attr='val"1 >'/></Abc>");
588 XPathDocument doc = new XPathDocument (sr);
589 XPathNavigator nav = doc.CreateNavigator ();
591 XPathNodeIterator iter = nav.Select ("/Abc/Foo/@attr");
593 AssertEquals ("val"1 >", iter.Current.InnerXml);