2 // MonoTests.System.Xml.XPathNavigatorTests
5 // Jason Diamond <jason@injektilo.org>
6 // Martin Willemoes Hansen <mwh@sysrq.dk>
7 // Atsushi Enomoto <atsushi@ximian.com>
9 // (C) 2002 Jason Diamond
10 // (C) 2003 Martin Willemoes Hansen
11 // (C) 2004-2006 Novell, Inc.
17 using System.Xml.XPath;
20 using NUnit.Framework;
22 namespace MonoTests.System.Xml
25 public class XPathNavigatorTests : Assertion
28 XPathNavigator navigator;
31 public void GetReady ()
33 document = new XmlDocument ();
37 public void CreateNavigator ()
39 document.LoadXml ("<foo />");
40 navigator = document.CreateNavigator ();
41 AssertNotNull (navigator);
45 public void PropertiesOnDocument ()
47 document.LoadXml ("<foo:bar xmlns:foo='#foo' />");
48 navigator = document.CreateNavigator ();
50 AssertEquals (XPathNodeType.Root, navigator.NodeType);
51 AssertEquals (String.Empty, navigator.Name);
52 AssertEquals (String.Empty, navigator.LocalName);
53 AssertEquals (String.Empty, navigator.NamespaceURI);
54 AssertEquals (String.Empty, navigator.Prefix);
55 Assert (!navigator.HasAttributes);
56 Assert (navigator.HasChildren);
57 Assert (!navigator.IsEmptyElement);
61 public void PropertiesOnElement ()
63 document.LoadXml ("<foo:bar xmlns:foo='#foo' />");
64 navigator = document.DocumentElement.CreateNavigator ();
66 AssertEquals (XPathNodeType.Element, navigator.NodeType);
67 AssertEquals ("foo:bar", navigator.Name);
68 AssertEquals ("bar", navigator.LocalName);
69 AssertEquals ("#foo", navigator.NamespaceURI);
70 AssertEquals ("foo", navigator.Prefix);
71 Assert (!navigator.HasAttributes);
72 Assert (!navigator.HasChildren);
73 Assert (navigator.IsEmptyElement);
77 public void PropertiesOnAttribute ()
79 document.LoadXml ("<foo bar:baz='quux' xmlns:bar='#bar' />");
80 navigator = document.DocumentElement.GetAttributeNode("baz", "#bar").CreateNavigator ();
82 AssertEquals (XPathNodeType.Attribute, navigator.NodeType);
83 AssertEquals ("bar:baz", navigator.Name);
84 AssertEquals ("baz", navigator.LocalName);
85 AssertEquals ("#bar", navigator.NamespaceURI);
86 AssertEquals ("bar", navigator.Prefix);
87 Assert (!navigator.HasAttributes);
88 Assert (!navigator.HasChildren);
89 Assert (!navigator.IsEmptyElement);
93 public void PropertiesOnNamespace ()
95 document.LoadXml ("<root xmlns='urn:foo' />");
\r
96 navigator = document.DocumentElement.Attributes [0].CreateNavigator ();
\r
97 AssertEquals (XPathNodeType.Namespace, navigator.NodeType);
101 public void Navigation ()
103 document.LoadXml ("<foo><bar /><baz /></foo>");
104 navigator = document.DocumentElement.CreateNavigator ();
106 AssertEquals ("foo", navigator.Name);
107 Assert (navigator.MoveToFirstChild ());
108 AssertEquals ("bar", navigator.Name);
109 Assert (navigator.MoveToNext ());
110 AssertEquals ("baz", navigator.Name);
111 Assert (!navigator.MoveToNext ());
112 AssertEquals ("baz", navigator.Name);
113 Assert (navigator.MoveToPrevious ());
114 AssertEquals ("bar", navigator.Name);
115 Assert (!navigator.MoveToPrevious ());
116 Assert (navigator.MoveToParent ());
117 AssertEquals ("foo", navigator.Name);
118 navigator.MoveToRoot ();
119 AssertEquals (XPathNodeType.Root, navigator.NodeType);
120 Assert (!navigator.MoveToParent ());
121 AssertEquals (XPathNodeType.Root, navigator.NodeType);
122 Assert (navigator.MoveToFirstChild ());
123 AssertEquals ("foo", navigator.Name);
124 Assert (navigator.MoveToFirst ());
125 AssertEquals ("foo", navigator.Name);
126 Assert (navigator.MoveToFirstChild ());
127 AssertEquals ("bar", navigator.Name);
128 Assert (navigator.MoveToNext ());
129 AssertEquals ("baz", navigator.Name);
130 Assert (navigator.MoveToFirst ());
131 AssertEquals ("bar", navigator.Name);
135 public void MoveToAndIsSamePosition ()
137 XmlDocument document1 = new XmlDocument ();
138 document1.LoadXml ("<foo><bar /></foo>");
139 XPathNavigator navigator1a = document1.DocumentElement.CreateNavigator ();
140 XPathNavigator navigator1b = document1.DocumentElement.CreateNavigator ();
142 XmlDocument document2 = new XmlDocument ();
143 document2.LoadXml ("<foo><bar /></foo>");
144 XPathNavigator navigator2 = document2.DocumentElement.CreateNavigator ();
146 AssertEquals ("foo", navigator1a.Name);
147 Assert (navigator1a.MoveToFirstChild ());
148 AssertEquals ("bar", navigator1a.Name);
150 Assert (!navigator1b.IsSamePosition (navigator1a));
151 AssertEquals ("foo", navigator1b.Name);
152 Assert (navigator1b.MoveTo (navigator1a));
153 Assert (navigator1b.IsSamePosition (navigator1a));
154 AssertEquals ("bar", navigator1b.Name);
156 Assert (!navigator2.IsSamePosition (navigator1a));
157 AssertEquals ("foo", navigator2.Name);
158 Assert (!navigator2.MoveTo (navigator1a));
159 AssertEquals ("foo", navigator2.Name);
163 public void AttributeNavigation ()
165 document.LoadXml ("<foo bar='baz' quux='quuux' />");
166 navigator = document.DocumentElement.CreateNavigator ();
168 AssertEquals (XPathNodeType.Element, navigator.NodeType);
169 AssertEquals ("foo", navigator.Name);
170 Assert (navigator.MoveToFirstAttribute ());
171 AssertEquals (XPathNodeType.Attribute, navigator.NodeType);
172 AssertEquals ("bar", navigator.Name);
173 AssertEquals ("baz", navigator.Value);
174 Assert (navigator.MoveToNextAttribute ());
175 AssertEquals (XPathNodeType.Attribute, navigator.NodeType);
176 AssertEquals ("quux", navigator.Name);
177 AssertEquals ("quuux", navigator.Value);
181 public void ElementAndRootValues()
183 document.LoadXml ("<foo><bar>baz</bar><quux>quuux</quux></foo>");
184 navigator = document.DocumentElement.CreateNavigator ();
186 AssertEquals (XPathNodeType.Element, navigator.NodeType);
187 AssertEquals ("foo", navigator.Name);
188 //AssertEquals ("bazquuux", navigator.Value);
190 navigator.MoveToRoot ();
191 //AssertEquals ("bazquuux", navigator.Value);
195 public void DocumentWithXmlDeclaration ()
197 document.LoadXml ("<?xml version=\"1.0\" standalone=\"yes\"?><Root><foo>bar</foo></Root>");
198 navigator = document.CreateNavigator ();
200 navigator.MoveToRoot ();
201 navigator.MoveToFirstChild ();
202 AssertEquals (XPathNodeType.Element, navigator.NodeType);
203 AssertEquals ("Root", navigator.Name);
207 public void DocumentWithProcessingInstruction ()
209 document.LoadXml ("<?xml-stylesheet href='foo.xsl' type='text/xsl' ?><foo />");
210 navigator = document.CreateNavigator ();
212 Assert (navigator.MoveToFirstChild ());
213 AssertEquals (XPathNodeType.ProcessingInstruction, navigator.NodeType);
214 AssertEquals ("xml-stylesheet", navigator.Name);
216 XPathNodeIterator iter = navigator.SelectChildren (XPathNodeType.Element);
217 AssertEquals (0, iter.Count);
221 public void SelectFromOrphan ()
223 // SelectSingleNode () from node without parent.
224 XmlDocument doc = new XmlDocument ();
225 doc.LoadXml ("<foo><include id='original' /></foo>");
227 XmlNode node = doc.CreateElement ("child");
228 node.InnerXml = "<include id='new' />";
230 XmlNode new_include = node.SelectSingleNode ("//include");
231 AssertEquals ("<include id=\"new\" />", new_include.OuterXml);
233 // In this case 'node2' has parent 'node'
234 doc = new XmlDocument ();
235 doc.LoadXml ("<foo><include id='original' /></foo>");
237 node = doc.CreateElement ("child");
238 XmlNode node2 = doc.CreateElement ("grandchild");
239 node.AppendChild (node2);
240 node2.InnerXml = "<include id='new' />";
242 new_include = node2.SelectSingleNode ("/");
243 AssertEquals ("<child><grandchild><include id=\"new\" /></grandchild></child>",
244 new_include.OuterXml);
248 public void XPathDocumentMoveToId ()
250 string dtd = "<!DOCTYPE root [<!ELEMENT root EMPTY><!ATTLIST root id ID #REQUIRED>]>";
\r
251 string xml = dtd + "<root id='aaa'/>";
\r
252 StringReader sr = new StringReader (xml);
\r
253 XPathNavigator nav = new XPathDocument (sr).CreateNavigator ();
\r
254 Assert ("ctor() from TextReader", nav.MoveToId ("aaa"));
\r
256 XmlValidatingReader xvr = new XmlValidatingReader (xml, XmlNodeType.Document, null);
\r
257 nav = new XPathDocument (xvr).CreateNavigator ();
\r
258 Assert ("ctor() from XmlValidatingReader", nav.MoveToId ("aaa"));
\r
260 // FIXME: it seems to result in different in .NET 2.0.
263 // When it is XmlTextReader, XPathDocument fails.
264 XmlTextReader xtr = new XmlTextReader (xml, XmlNodeType.Document, null);
\r
265 nav = new XPathDocument (xtr).CreateNavigator ();
\r
266 Assert ("ctor() from XmlTextReader", !nav.MoveToId ("aaa"));
\r
272 public void SignificantWhitespaceConstruction ()
274 string xml = @"<root>
275 <child xml:space='preserve'> <!-- --> </child>
276 <child xml:space='preserve'> </child>
278 XPathNavigator nav = new XPathDocument (
279 new XmlTextReader (xml, XmlNodeType.Document, null),
280 XmlSpace.Preserve).CreateNavigator ();
281 nav.MoveToFirstChild ();
282 nav.MoveToFirstChild ();
283 AssertEquals ("#1", XPathNodeType.Whitespace, nav.NodeType);
285 nav.MoveToFirstChild ();
286 AssertEquals ("#2", XPathNodeType.SignificantWhitespace,
291 public void VariableReference ()
293 XPathDocument xpd = new XPathDocument (
294 new StringReader ("<root>sample text</root>"));
295 XPathNavigator nav = xpd.CreateNavigator ();
297 XPathExpression expr = nav.Compile ("foo(string(.),$idx)");
298 XsltArgumentList args = new XsltArgumentList ();
299 args.AddParam ("idx", "", 5);
300 MyContext ctx = new MyContext (nav.NameTable as NameTable, args);
301 ctx.AddNamespace ("x", "urn:foo");
303 expr.SetContext (ctx);
305 XPathNodeIterator iter = nav.Select ("/root");
307 AssertEquals ("e", iter.Current.Evaluate (expr));
310 class MyContext : XsltContext
312 XsltArgumentList args;
314 public MyContext (NameTable nt, XsltArgumentList args)
320 public override IXsltContextFunction ResolveFunction (
321 string prefix, string name, XPathResultType [] argtypes)
324 return new MyFunction (argtypes);
328 public override IXsltContextVariable ResolveVariable (string prefix, string name)
330 return new MyVariable (name);
333 public override bool PreserveWhitespace (XPathNavigator nav)
338 public override int CompareDocument (string uri1, string uri2)
340 return String.CompareOrdinal (uri1, uri2);
343 public override bool Whitespace {
344 get { return false; }
347 public object GetParam (string name, string ns)
349 return args.GetParam (name, ns);
353 public class MyFunction : IXsltContextFunction
355 XPathResultType [] argtypes;
357 public MyFunction (XPathResultType [] argtypes)
359 this.argtypes = argtypes;
362 public XPathResultType [] ArgTypes {
363 get { return argtypes; }
374 public XPathResultType ReturnType {
375 get { return XPathResultType.String; }
378 public object Invoke (XsltContext xsltContext,
379 object [] args, XPathNavigator instanceContext)
381 return ((string) args [0]) [(int) (double) args [1]].ToString ();
385 public class MyVariable : IXsltContextVariable
389 public MyVariable (string name)
394 public object Evaluate (XsltContext ctx)
396 return ((MyContext) ctx).GetParam (name, String.Empty);
399 public bool IsLocal {
400 get { return false; }
403 public bool IsParam {
404 get { return false; }
407 public XPathResultType VariableType {
408 get { return XPathResultType.Any; }
414 public void ValueAsBoolean ()
416 string xml = "<root>1</root>";
417 XmlDocument doc = new XmlDocument ();
419 XPathNavigator nav = doc.CreateNavigator ();
420 nav.MoveToFirstChild ();
421 AssertEquals ("#1", true, nav.ValueAsBoolean);
422 nav.MoveToFirstChild ();
423 AssertEquals ("#2", true, nav.ValueAsBoolean);
427 [ExpectedException (typeof (FormatException))]
428 public void ValueAsBooleanFail ()
430 string xml = "<root>1.0</root>";
431 XmlDocument doc = new XmlDocument ();
433 XPathNavigator nav = doc.CreateNavigator ();
434 nav.MoveToFirstChild ();
435 bool i = nav.ValueAsBoolean;
439 public void ValueAsDateTime ()
441 DateTime time = new DateTime (2005, 12, 13);
442 string xml = "<root>2005-12-13</root>";
443 XmlDocument doc = new XmlDocument ();
445 XPathNavigator nav = doc.CreateNavigator ();
446 nav.MoveToFirstChild ();
447 AssertEquals ("#1", time, nav.ValueAsDateTime);
448 nav.MoveToFirstChild ();
449 AssertEquals ("#2", time, nav.ValueAsDateTime);
453 [ExpectedException (typeof (FormatException))]
454 public void ValueAsDateTimeFail ()
456 string xml = "<root>dating time</root>";
457 XmlDocument doc = new XmlDocument ();
459 XPathNavigator nav = doc.CreateNavigator ();
460 nav.MoveToFirstChild ();
461 DateTime time = nav.ValueAsDateTime;
465 public void ValueAsDouble ()
467 string xml = "<root>3.14159265359</root>";
468 XmlDocument doc = new XmlDocument ();
470 XPathNavigator nav = doc.CreateNavigator ();
471 nav.MoveToFirstChild ();
472 AssertEquals ("#1", 3.14159265359, nav.ValueAsDouble);
473 nav.MoveToFirstChild ();
474 AssertEquals ("#2", 3.14159265359, nav.ValueAsDouble);
478 [ExpectedException (typeof (FormatException))]
479 public void ValueAsDoubleFail ()
481 string xml = "<root>Double Dealer</root>";
482 XmlDocument doc = new XmlDocument ();
484 XPathNavigator nav = doc.CreateNavigator ();
485 nav.MoveToFirstChild ();
486 Double dealer = nav.ValueAsDouble;
490 public void ValueAsInt ()
492 string xml = "<root>1</root>";
493 XmlDocument doc = new XmlDocument ();
495 XPathNavigator nav = doc.CreateNavigator ();
496 nav.MoveToFirstChild ();
497 AssertEquals ("#1", 1, nav.ValueAsInt);
498 nav.MoveToFirstChild ();
499 AssertEquals ("#2", 1, nav.ValueAsInt);
503 // Here, it seems to be using XQueryConvert (whatever was called)
504 [ExpectedException (typeof (FormatException))]
505 public void ValueAsIntFail ()
507 string xml = "<root>1.0</root>";
508 XmlDocument doc = new XmlDocument ();
510 XPathNavigator nav = doc.CreateNavigator ();
511 nav.MoveToFirstChild ();
512 int i = nav.ValueAsInt;
516 public void ValueAsLong ()
518 string xml = "<root>10000000000000000</root>";
519 XmlDocument doc = new XmlDocument ();
521 XPathNavigator nav = doc.CreateNavigator ();
522 nav.MoveToFirstChild ();
523 AssertEquals ("#1", 10000000000000000, nav.ValueAsLong);
524 nav.MoveToFirstChild ();
525 AssertEquals ("#2", 10000000000000000, nav.ValueAsLong);
529 // Here, it seems to be using XQueryConvert (whatever was called)
530 [ExpectedException (typeof (FormatException))]
531 public void ValueAsLongFail ()
533 string xml = "<root>0x10000000000000000</root>";
534 XmlDocument doc = new XmlDocument ();
536 XPathNavigator nav = doc.CreateNavigator ();
537 nav.MoveToFirstChild ();
538 long l = nav.ValueAsLong;
542 public void InnerXmlText ()
544 StringReader sr = new StringReader ("<Abc><Foo>Hello</Foo></Abc>");
545 XPathDocument doc = new XPathDocument (sr);
546 XPathNavigator nav = doc.CreateNavigator ();
547 XPathNodeIterator iter = nav.Select ("/Abc/Foo");
549 AssertEquals ("#1", "Hello", iter.Current.InnerXml);
550 AssertEquals ("#2", "<Foo>Hello</Foo>", iter.Current.OuterXml);
551 iter = nav.Select ("/Abc/Foo/text()");
553 AssertEquals ("#3", String.Empty, iter.Current.InnerXml);
554 AssertEquals ("#4", "Hello", iter.Current.OuterXml);
558 public void InnerXmlAttribute ()
560 StringReader sr = new StringReader ("<Abc><Foo attr='val1'/></Abc>");
561 XPathDocument doc = new XPathDocument (sr);
562 XPathNavigator nav = doc.CreateNavigator ();
564 XPathNodeIterator iter = nav.Select ("/Abc/Foo/@attr");
566 AssertEquals ("val1", iter.Current.InnerXml);
570 public void InnerXmlTextEscape ()
572 StringReader sr = new StringReader ("<Abc><Foo>Hello<\r\nInnerXml</Foo></Abc>");
573 XPathDocument doc = new XPathDocument (sr);
574 XPathNavigator nav = doc.CreateNavigator ();
575 XPathNodeIterator iter = nav.Select ("/Abc/Foo");
577 AssertEquals ("#1", "Hello<\r\nInnerXml", iter.Current.InnerXml);
578 AssertEquals ("#2", "<Foo>Hello<\r\nInnerXml</Foo>", iter.Current.OuterXml);
579 iter = nav.Select ("/Abc/Foo/text()");
581 AssertEquals ("#3", String.Empty, iter.Current.InnerXml);
582 AssertEquals ("#4", "Hello<\r\nInnerXml", iter.Current.OuterXml);
586 [Category ("NotDotNet")] // .NET bug; it should escape value
587 public void InnerXmlAttributeEscape ()
589 StringReader sr = new StringReader ("<Abc><Foo attr='val"1 >'/></Abc>");
590 XPathDocument doc = new XPathDocument (sr);
591 XPathNavigator nav = doc.CreateNavigator ();
593 XPathNodeIterator iter = nav.Select ("/Abc/Foo/@attr");
595 AssertEquals ("val"1 >", iter.Current.InnerXml);
599 public void WriterAttributePrefix ()
601 XmlDocument doc = new XmlDocument ();
602 XmlWriter w = doc.CreateNavigator ().AppendChild ();
603 w.WriteStartElement ("foo");
604 w.WriteAttributeString ("xmlns", "x", "http://www.w3.org/2000/xmlns/", "urn:foo");
605 AssertEquals ("#0", "x", w.LookupPrefix ("urn:foo"));
606 w.WriteStartElement (null, "bar", "urn:foo");
607 w.WriteAttributeString (null, "ext", "urn:foo", "bah");
608 w.WriteEndElement ();
609 w.WriteEndElement ();
611 AssertEquals ("#1", "x", doc.FirstChild.FirstChild.Prefix);
612 AssertEquals ("#2", "x", doc.FirstChild.FirstChild.Attributes [0].Prefix);