// Authors:
// Jason Diamond <jason@injektilo.org>
// Martin Willemoes Hansen <mwh@sysrq.dk>
+// Atsushi Enomoto <atsushi@ximian.com>
//
// (C) 2002 Jason Diamond
// (C) 2003 Martin Willemoes Hansen
+// (C) 2004-2006 Novell, Inc.
//
using System;
+using System.IO;
using System.Xml;
using System.Xml.XPath;
+using System.Xml.Xsl;
using NUnit.Framework;
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 ()
{
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; }
+ }
+ }
+
+ [Test]
+ public void TextMatchesWhitespace ()
+ {
+ string xml = "<root><ws> </ws><sws xml:space='preserve'> </sws></root>";
+ XmlDocument doc = new XmlDocument ();
+ doc.PreserveWhitespace = true;
+ doc.LoadXml (xml);
+ XPathNavigator nav = doc.CreateNavigator ();
+ nav.MoveToFirstChild (); // root
+ nav.MoveToFirstChild (); // ws
+ nav.MoveToFirstChild (); // ' '
+ AssertEquals ("#1", true, nav.Matches ("text()"));
+ nav.MoveToParent ();
+ nav.MoveToNext (); // sws
+ nav.MoveToFirstChild (); // ' '
+ AssertEquals ("#2", true, nav.Matches ("text()"));
+ }
+
+#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<\r\nInnerXml</Foo></Abc>");
+ XPathDocument doc = new XPathDocument (sr);
+ XPathNavigator nav = doc.CreateNavigator ();
+ XPathNodeIterator iter = nav.Select ("/Abc/Foo");
+ iter.MoveNext ();
+ AssertEquals ("#1", "Hello<\r\nInnerXml", iter.Current.InnerXml);
+ AssertEquals ("#2", "<Foo>Hello<\r\nInnerXml</Foo>", iter.Current.OuterXml);
+ iter = nav.Select ("/Abc/Foo/text()");
+ iter.MoveNext ();
+ AssertEquals ("#3", String.Empty, iter.Current.InnerXml);
+ AssertEquals ("#4", "Hello<\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"1 >'/></Abc>");
+ XPathDocument doc = new XPathDocument (sr);
+ XPathNavigator nav = doc.CreateNavigator ();
+
+ XPathNodeIterator iter = nav.Select ("/Abc/Foo/@attr");
+ iter.MoveNext ();
+ AssertEquals ("val"1 >", iter.Current.InnerXml);
+ }
+
+ [Test]
+ public void WriterAttributePrefix ()
+ {
+ XmlDocument doc = new XmlDocument ();
+ XmlWriter w = doc.CreateNavigator ().AppendChild ();
+ w.WriteStartElement ("foo");
+ w.WriteAttributeString ("xmlns", "x", "http://www.w3.org/2000/xmlns/", "urn:foo");
+ AssertEquals ("#0", "x", w.LookupPrefix ("urn:foo"));
+ w.WriteStartElement (null, "bar", "urn:foo");
+ w.WriteAttributeString (null, "ext", "urn:foo", "bah");
+ w.WriteEndElement ();
+ w.WriteEndElement ();
+ w.Close ();
+ AssertEquals ("#1", "x", doc.FirstChild.FirstChild.Prefix);
+ AssertEquals ("#2", "x", doc.FirstChild.FirstChild.Attributes [0].Prefix);
+ }
+
+ [Test]
+ public void ValueAs ()
+ {
+ string xml = "<root>1</root>";
+ XPathNavigator nav = new XPathDocument (XmlReader.Create (new StringReader (xml))).CreateNavigator ();
+ nav.MoveToFirstChild ();
+ nav.MoveToFirstChild ();
+ AssertEquals ("1", nav.ValueAs (typeof (string), null));
+ AssertEquals (1, nav.ValueAs (typeof (int), null));
+ }
+
+ [Test]
+ public void MoveToFollowingNodeTypeAll ()
+ {
+ XmlDocument doc = new XmlDocument ();
+ doc.LoadXml ("<root><child/><child2/></root>");
+ XPathNavigator nav = doc.CreateNavigator ();
+ Assert ("#1", nav.MoveToFollowing (XPathNodeType.All));
+ Assert ("#2", nav.MoveToFollowing (XPathNodeType.All));
+ AssertEquals ("#3", "child", nav.LocalName);
+ Assert ("#4", nav.MoveToNext (XPathNodeType.All));
+ AssertEquals ("#5", "child2", nav.LocalName);
+ }
+
+ [Test] // bug #324606.
+ public void XPathDocumentFromSubtreeNodes ()
+ {
+ string xml = "<root><child1><nest1><nest2>hello!</nest2></nest1></child1><child2/><child3/></root>";
+ XmlReader r = new XmlTextReader (new StringReader (xml));
+ while (r.Read ()) {
+ if (r.Name == "child1")
+ break;
+ }
+ XPathDocument d = new XPathDocument (r);
+ XPathNavigator n = d.CreateNavigator ();
+ string result = @"<child1>
+ <nest1>
+ <nest2>hello!</nest2>
+ </nest1>
+</child1>
+<child2 />
+<child3 />";
+ AssertEquals (result, n.OuterXml.Replace ("\r\n", "\n"));
+ }
+
+ [Test] // bug #376191
+ public void InnerXmlOnRoot ()
+ {
+ XmlDocument document = new XmlDocument ();
+ document.LoadXml (@"<test>
+ <node>z</node>
+ <node>a</node>
+ <node>b</node>
+ <node>q</node>
+ </test>");
+ XPathNavigator navigator = document.CreateNavigator();
+ AssertEquals (navigator.OuterXml, navigator.InnerXml);
+ }
+#endif
}
}