New test.
[mono.git] / mcs / class / System.XML / Test / System.Xml.XPath / XPathNavigatorTests.cs
index 43e7b483ea7f3fc35d4a9f3e9cf04d8a914cf751..70527943fbea6e3214a87b7f5b9fdaa008ae5c61 100644 (file)
 //
 
 using System;
+using System.IO;
 using System.Xml;
 using System.Xml.XPath;
+using System.Xml.Xsl;
 
 using NUnit.Framework;
 
@@ -85,6 +87,14 @@ namespace MonoTests.System.Xml
                        Assert (!navigator.IsEmptyElement);
                }
 
+               [Test]
+               public void PropertiesOnNamespace ()
+               {
+                       document.LoadXml ("<root xmlns='urn:foo' />");\r
+                       navigator = document.DocumentElement.Attributes [0].CreateNavigator ();\r
+                       AssertEquals (XPathNodeType.Namespace, navigator.NodeType);
+               }
+
                [Test]
                public void Navigation ()
                {
@@ -182,7 +192,7 @@ namespace MonoTests.System.Xml
                [Test]
                public void DocumentWithXmlDeclaration ()
                {
-                       document.LoadXml ("<?xml version=\"1.0\" standalone=\"yes\"?>\"<Root><foo>bar</foo></Root>");
+                       document.LoadXml ("<?xml version=\"1.0\" standalone=\"yes\"?><Root><foo>bar</foo></Root>");
                        navigator = document.CreateNavigator ();
 
                        navigator.MoveToRoot ();
@@ -190,5 +200,398 @@ namespace MonoTests.System.Xml
                        AssertEquals (XPathNodeType.Element, navigator.NodeType);
                        AssertEquals ("Root", navigator.Name);
                }
+
+               [Test]
+               public void DocumentWithProcessingInstruction ()
+               {
+                       document.LoadXml ("<?xml-stylesheet href='foo.xsl' type='text/xsl' ?><foo />");
+                       navigator = document.CreateNavigator ();
+
+                       Assert (navigator.MoveToFirstChild ());
+                       AssertEquals (XPathNodeType.ProcessingInstruction, navigator.NodeType);
+                       AssertEquals ("xml-stylesheet", navigator.Name);
+
+                       XPathNodeIterator iter = navigator.SelectChildren (XPathNodeType.Element);
+                       AssertEquals (0, iter.Count);
+               }
+
+               [Test]
+               public void SelectFromOrphan ()
+               {
+                       // SelectSingleNode () from node without parent.
+                       XmlDocument doc = new XmlDocument ();
+                       doc.LoadXml ("<foo><include id='original' /></foo>");
+
+                       XmlNode node = doc.CreateElement ("child");
+                       node.InnerXml = "<include id='new' />";
+
+                       XmlNode new_include = node.SelectSingleNode ("//include");
+                       AssertEquals ("<include id=\"new\" />", new_include.OuterXml);
+
+                       // In this case 'node2' has parent 'node'
+                       doc = new XmlDocument ();
+                       doc.LoadXml ("<foo><include id='original' /></foo>");
+
+                       node = doc.CreateElement ("child");
+                       XmlNode node2 = doc.CreateElement ("grandchild");
+                       node.AppendChild (node2);
+                       node2.InnerXml = "<include id='new' />";
+
+                       new_include = node2.SelectSingleNode ("/");
+                       AssertEquals ("<child><grandchild><include id=\"new\" /></grandchild></child>",
+                               new_include.OuterXml);
+               }
+
+               [Test]
+               public void XPathDocumentMoveToId ()
+               {
+                       string dtd = "<!DOCTYPE root [<!ELEMENT root EMPTY><!ATTLIST root id ID #REQUIRED>]>";\r
+                       string xml = dtd + "<root id='aaa'/>";\r
+                       StringReader sr = new StringReader (xml);\r
+                       XPathNavigator nav = new XPathDocument (sr).CreateNavigator ();\r
+                       Assert ("ctor() from TextReader", nav.MoveToId ("aaa"));\r
+
+                       XmlValidatingReader xvr = new XmlValidatingReader (xml, XmlNodeType.Document, null);\r
+                       nav = new XPathDocument (xvr).CreateNavigator ();\r
+                       Assert ("ctor() from XmlValidatingReader", nav.MoveToId ("aaa"));\r
+
+                       // FIXME: it seems to result in different in .NET 2.0.
+#if NET_2_0
+#else
+                       // When it is XmlTextReader, XPathDocument fails.
+                       XmlTextReader xtr = new XmlTextReader (xml, XmlNodeType.Document, null);\r
+                       nav = new XPathDocument (xtr).CreateNavigator ();\r
+                       Assert ("ctor() from XmlTextReader", !nav.MoveToId ("aaa"));\r
+                       xtr.Close ();\r
+#endif
+               }
+
+               [Test]
+               public void SignificantWhitespaceConstruction ()
+               {
+                       string xml = @"<root>
+        <child xml:space='preserve'>    <!-- -->   </child>
+        <child xml:space='preserve'>    </child>
+</root>";
+                       XPathNavigator nav = new XPathDocument (
+                               new XmlTextReader (xml, XmlNodeType.Document, null),
+                               XmlSpace.Preserve).CreateNavigator ();
+                       nav.MoveToFirstChild ();
+                       nav.MoveToFirstChild ();
+                       AssertEquals ("#1", XPathNodeType.Whitespace, nav.NodeType);
+                       nav.MoveToNext ();
+                       nav.MoveToFirstChild ();
+                       AssertEquals ("#2", XPathNodeType.SignificantWhitespace,
+                               nav.NodeType);
+               }
+
+               [Test]
+               public void VariableReference ()
+               {
+                       XPathDocument xpd = new XPathDocument (
+                               new StringReader ("<root>sample text</root>"));
+                       XPathNavigator nav = xpd.CreateNavigator ();
+
+                       XPathExpression expr = nav.Compile ("foo(string(.),$idx)");
+                       XsltArgumentList args = new XsltArgumentList ();
+                       args.AddParam ("idx", "", 5);
+                       MyContext ctx = new MyContext (nav.NameTable as NameTable, args);
+                       ctx.AddNamespace ("x", "urn:foo");
+
+                       expr.SetContext (ctx);
+
+                       XPathNodeIterator iter = nav.Select ("/root");
+                       iter.MoveNext ();
+                       AssertEquals ("e", iter.Current.Evaluate (expr));
+               }
+
+               class MyContext : XsltContext
+               {
+                       XsltArgumentList args;
+
+                       public MyContext (NameTable nt, XsltArgumentList args)
+                               : base (nt)
+                       {
+                               this.args = args;
+                       }
+
+                       public override IXsltContextFunction ResolveFunction (
+                               string prefix, string name, XPathResultType [] argtypes)
+                       {
+                               if (name == "foo")
+                                       return new MyFunction (argtypes);
+                               return null;
+                       }
+
+                       public override IXsltContextVariable ResolveVariable (string prefix, string name)
+                       {
+                               return new MyVariable (name);
+                       }
+
+                       public override bool PreserveWhitespace (XPathNavigator nav)
+                       {
+                               return false;
+                       }
+
+                       public override int CompareDocument (string uri1, string uri2)
+                       {
+                               return String.CompareOrdinal (uri1, uri2);
+                       }
+
+                       public override bool Whitespace {
+                               get { return false; }
+                       }
+
+                       public object GetParam (string name, string ns)
+                       {
+                               return args.GetParam (name, ns);
+                       }
+               }
+
+               public class MyFunction : IXsltContextFunction
+               {
+                       XPathResultType [] argtypes;
+
+                       public MyFunction (XPathResultType [] argtypes)
+                       {
+                               this.argtypes = argtypes;
+                       }
+
+                       public XPathResultType [] ArgTypes {
+                               get { return argtypes; }
+                       }
+
+                       public int Maxargs {
+                               get { return 2; }
+                       }
+
+                       public int Minargs {
+                               get { return 2; }
+                       }
+
+                       public XPathResultType ReturnType {
+                               get { return XPathResultType.String; }
+                       }
+
+                       public object Invoke (XsltContext xsltContext,
+                               object [] args, XPathNavigator instanceContext)
+                       {
+                               return ((string) args [0]) [(int) (double) args [1]].ToString ();
+                       }
+               }
+
+               public class MyVariable : IXsltContextVariable
+               {
+                       string name;
+
+                       public MyVariable (string name)
+                       {
+                               this.name = name;
+                       }
+
+                       public object Evaluate (XsltContext ctx)
+                       {
+                               return ((MyContext) ctx).GetParam (name, String.Empty);
+                       }
+
+                       public bool IsLocal {
+                               get { return false; }
+                       }
+
+                       public bool IsParam {
+                               get { return false; }
+                       }
+
+                       public XPathResultType VariableType {
+                               get { return XPathResultType.Any; }
+                       }
+               }
+
+#if NET_2_0
+               [Test]
+               public void ValueAsBoolean ()
+               {
+                       string xml = "<root>1</root>";
+                       XmlDocument doc = new XmlDocument ();
+                       doc.LoadXml (xml);
+                       XPathNavigator nav = doc.CreateNavigator ();
+                       nav.MoveToFirstChild ();
+                       AssertEquals ("#1", true, nav.ValueAsBoolean);
+                       nav.MoveToFirstChild ();
+                       AssertEquals ("#2", true, nav.ValueAsBoolean);
+               }
+
+               [Test]
+               [ExpectedException (typeof (FormatException))]
+               public void ValueAsBooleanFail ()
+               {
+                       string xml = "<root>1.0</root>";
+                       XmlDocument doc = new XmlDocument ();
+                       doc.LoadXml (xml);
+                       XPathNavigator nav = doc.CreateNavigator ();
+                       nav.MoveToFirstChild ();
+                       bool i = nav.ValueAsBoolean;
+               }
+
+               [Test]
+               public void ValueAsDateTime ()
+               {
+                       DateTime time = new DateTime (2005, 12, 13);
+                       string xml = "<root>2005-12-13</root>";
+                       XmlDocument doc = new XmlDocument ();
+                       doc.LoadXml (xml);
+                       XPathNavigator nav = doc.CreateNavigator ();
+                       nav.MoveToFirstChild ();
+                       AssertEquals ("#1", time, nav.ValueAsDateTime);
+                       nav.MoveToFirstChild ();
+                       AssertEquals ("#2", time, nav.ValueAsDateTime);
+               }
+
+               [Test]
+               [ExpectedException (typeof (FormatException))]
+               public void ValueAsDateTimeFail ()
+               {
+                       string xml = "<root>dating time</root>";
+                       XmlDocument doc = new XmlDocument ();
+                       doc.LoadXml (xml);
+                       XPathNavigator nav = doc.CreateNavigator ();
+                       nav.MoveToFirstChild ();
+                       DateTime time = nav.ValueAsDateTime;
+               }
+
+               [Test]
+               public void ValueAsDouble ()
+               {
+                       string xml = "<root>3.14159265359</root>";
+                       XmlDocument doc = new XmlDocument ();
+                       doc.LoadXml (xml);
+                       XPathNavigator nav = doc.CreateNavigator ();
+                       nav.MoveToFirstChild ();
+                       AssertEquals ("#1", 3.14159265359, nav.ValueAsDouble);
+                       nav.MoveToFirstChild ();
+                       AssertEquals ("#2", 3.14159265359, nav.ValueAsDouble);
+               }
+
+               [Test]
+               [ExpectedException (typeof (FormatException))]
+               public void ValueAsDoubleFail ()
+               {
+                       string xml = "<root>Double Dealer</root>";
+                       XmlDocument doc = new XmlDocument ();
+                       doc.LoadXml (xml);
+                       XPathNavigator nav = doc.CreateNavigator ();
+                       nav.MoveToFirstChild ();
+                       Double dealer = nav.ValueAsDouble;
+               }
+
+               [Test]
+               public void ValueAsInt ()
+               {
+                       string xml = "<root>1</root>";
+                       XmlDocument doc = new XmlDocument ();
+                       doc.LoadXml (xml);
+                       XPathNavigator nav = doc.CreateNavigator ();
+                       nav.MoveToFirstChild ();
+                       AssertEquals ("#1", 1, nav.ValueAsInt);
+                       nav.MoveToFirstChild ();
+                       AssertEquals ("#2", 1, nav.ValueAsInt);
+               }
+
+               [Test]
+               // Here, it seems to be using XQueryConvert (whatever was called)
+               [ExpectedException (typeof (FormatException))]
+               public void ValueAsIntFail ()
+               {
+                       string xml = "<root>1.0</root>";
+                       XmlDocument doc = new XmlDocument ();
+                       doc.LoadXml (xml);
+                       XPathNavigator nav = doc.CreateNavigator ();
+                       nav.MoveToFirstChild ();
+                       int i = nav.ValueAsInt;
+               }
+
+               [Test]
+               public void ValueAsLong ()
+               {
+                       string xml = "<root>10000000000000000</root>";
+                       XmlDocument doc = new XmlDocument ();
+                       doc.LoadXml (xml);
+                       XPathNavigator nav = doc.CreateNavigator ();
+                       nav.MoveToFirstChild ();
+                       AssertEquals ("#1", 10000000000000000, nav.ValueAsLong);
+                       nav.MoveToFirstChild ();
+                       AssertEquals ("#2", 10000000000000000, nav.ValueAsLong);
+               }
+
+               [Test]
+               // Here, it seems to be using XQueryConvert (whatever was called)
+               [ExpectedException (typeof (FormatException))]
+               public void ValueAsLongFail ()
+               {
+                       string xml = "<root>0x10000000000000000</root>";
+                       XmlDocument doc = new XmlDocument ();
+                       doc.LoadXml (xml);
+                       XPathNavigator nav = doc.CreateNavigator ();
+                       nav.MoveToFirstChild ();
+                       long l = nav.ValueAsLong;
+               }
+
+               [Test] // bug #79874
+               public void InnerXmlText ()
+               {
+                       StringReader sr = new StringReader ("<Abc><Foo>Hello</Foo></Abc>");
+                       XPathDocument doc = new XPathDocument (sr);
+                       XPathNavigator nav = doc.CreateNavigator ();
+                       XPathNodeIterator iter = nav.Select ("/Abc/Foo");
+                       iter.MoveNext ();
+                       AssertEquals ("#1", "Hello", iter.Current.InnerXml);
+                       AssertEquals ("#2", "<Foo>Hello</Foo>", iter.Current.OuterXml);
+                       iter = nav.Select ("/Abc/Foo/text()");
+                       iter.MoveNext ();
+                       AssertEquals ("#3", String.Empty, iter.Current.InnerXml);
+                       AssertEquals ("#4", "Hello", iter.Current.OuterXml);
+               }
+
+               [Test] // bug #79875
+               public void InnerXmlAttribute ()
+               {
+                       StringReader sr = new StringReader ("<Abc><Foo attr='val1'/></Abc>");
+                       XPathDocument doc = new XPathDocument (sr);
+                       XPathNavigator nav = doc.CreateNavigator ();
+
+                       XPathNodeIterator iter = nav.Select ("/Abc/Foo/@attr");
+                       iter.MoveNext ();
+                       AssertEquals ("val1", iter.Current.InnerXml);
+               }
+
+               [Test]
+               public void InnerXmlTextEscape ()
+               {
+                       StringReader sr = new StringReader ("<Abc><Foo>Hello&lt;\r\nInnerXml</Foo></Abc>");
+                       XPathDocument doc = new XPathDocument (sr);
+                       XPathNavigator nav = doc.CreateNavigator ();
+                       XPathNodeIterator iter = nav.Select ("/Abc/Foo");
+                       iter.MoveNext ();
+                       AssertEquals ("#1", "Hello&lt;\r\nInnerXml", iter.Current.InnerXml);
+                       AssertEquals ("#2", "<Foo>Hello&lt;\r\nInnerXml</Foo>", iter.Current.OuterXml);
+                       iter = nav.Select ("/Abc/Foo/text()");
+                       iter.MoveNext ();
+                       AssertEquals ("#3", String.Empty, iter.Current.InnerXml);
+                       AssertEquals ("#4", "Hello&lt;\r\nInnerXml", iter.Current.OuterXml);
+               }
+
+               [Test]
+               [Category ("NotDotNet")] // .NET bug; it should escape value
+               public void InnerXmlAttributeEscape ()
+               {
+                       StringReader sr = new StringReader ("<Abc><Foo attr='val&quot;1&#13;&#10;&gt;'/></Abc>");
+                       XPathDocument doc = new XPathDocument (sr);
+                       XPathNavigator nav = doc.CreateNavigator ();
+
+                       XPathNodeIterator iter = nav.Select ("/Abc/Foo/@attr");
+                       iter.MoveNext ();
+                       AssertEquals ("val&quot;1&#10;&gt;", iter.Current.InnerXml);
+               }
+#endif
        }
 }