2004-07-28 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / class / System.XML / System.Xml.XPath / XPathNavigator.cs
index 750757fce6c74f90c62d1ef92edd1d5f2ad5c527..2e72e136cc8741bf7531393198cb79db539c2a36 100644 (file)
@@ -3,16 +3,57 @@
 //
 // Author:
 //   Jason Diamond (jason@injektilo.org)
+//   Atsushi Enomoto (atsushi@ximian.com)
 //
 // (C) 2002 Jason Diamond  http://injektilo.org/
+// (C) 2004 Novell Inc.
+//
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+// 
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+// 
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
 using System;
+using System.Collections;
+using System.IO;
+using System.Xml;
+using System.Xml.Schema;
 using Mono.Xml.XPath;
+#if NET_2_0
+using MS.Internal.Xml;
+#endif
+
+#if NET_2_0
+using NSResolver = System.Xml.IXmlNamespaceResolver;
+#else
+using NSResolver = System.Xml.XmlNamespaceManager;
+#endif
 
 namespace System.Xml.XPath
 {
+#if NET_2_0
+       public abstract class XPathNavigator : XPathItem,
+               ICloneable, IXPathNavigable, IXmlNamespaceResolver
+#else
        public abstract class XPathNavigator : ICloneable
+#endif
        {
                #region Constructor
 
@@ -26,9 +67,19 @@ namespace System.Xml.XPath
 
                public abstract string BaseURI { get; }
 
+#if NET_2_0
+               public virtual bool HasAttributes {
+                       get { return Clone ().MoveToFirstAttribute (); }
+               }
+
+               public virtual bool HasChildren {
+                       get { return Clone ().MoveToFirstChild (); }
+               }
+#else
                public abstract bool HasAttributes { get; }
 
                public abstract bool HasChildren { get; }
+#endif
 
                public abstract bool IsEmptyElement { get; }
 
@@ -44,9 +95,40 @@ namespace System.Xml.XPath
 
                public abstract string Prefix { get; }
 
+#if NET_2_0
+               public virtual string XmlLang {
+                       get {
+                               XPathNavigator nav = Clone ();
+                               switch (nav.NodeType) {
+                               case XPathNodeType.Attribute:
+                               case XPathNodeType.Namespace:
+                                       nav.MoveToParent ();
+                                       break;
+                               }
+                               do {
+                                       if (nav.MoveToAttribute ("lang", "http://www.w3.org/XML/1998/namespace"))
+                                               return nav.Value;
+                               } while (nav.MoveToParent ());
+                               return String.Empty;
+                       }
+               }
+#else
                public abstract string Value { get; }
 
                public abstract string XmlLang { get; }
+#endif
+
+               int Depth
+               {
+                       get
+                       {
+                               int cLevels = 0;
+                               XPathNavigator nav = Clone ();
+                               while (nav.MoveToParent ())
+                                       cLevels ++;
+                               return cLevels;
+                       }
+               }
 
                #endregion
 
@@ -54,19 +136,100 @@ namespace System.Xml.XPath
 
                public abstract XPathNavigator Clone ();
 
-               [MonoTODO]
                public virtual XmlNodeOrder ComparePosition (XPathNavigator nav)
                {
-                       throw new NotImplementedException ();
+                       if (IsSamePosition (nav))
+                               return XmlNodeOrder.Same;
+
+                       XPathNavigator nav1 = Clone ();
+                       XPathNavigator nav2 = nav.Clone ();
+
+                       int nDepth1 = nav1.Depth;
+                       int nDepth2 = nav2.Depth;
+
+                       if (nDepth1 > nDepth2)
+                       {
+                               while (nDepth1 > nDepth2)
+                               {
+                                       if (!nav1.MoveToParent ())
+                                               break;
+                                       nDepth1 --;
+                               }
+                               if (nav1.IsSamePosition (nav2))
+                                       return XmlNodeOrder.After;
+                       }
+                       else if (nDepth1 < nDepth2)
+                       {
+                               while (nDepth1 < nDepth2)
+                               {
+                                       if (!nav2.MoveToParent ())
+                                               break;
+                                       nDepth2 --;
+                               }
+                               if (nav1.IsSamePosition (nav2))
+                                       return XmlNodeOrder.Before;
+                       }
+
+                       XPathNavigator parent1 = nav1.Clone ();
+                       XPathNavigator parent2 = nav2.Clone ();
+                       while (parent1.MoveToParent () && parent2.MoveToParent ())
+                       {
+                               if (parent1.IsSamePosition (parent2))
+                               {
+                                       // the ordering is namespace, attribute, children
+                                       // assume that nav1 is before nav2, find counter-example
+                                       if (nav1.NodeType == XPathNodeType.Namespace)
+                                       {
+                                               if (nav2.NodeType == XPathNodeType.Namespace)
+                                               {
+                                                       // match namespaces
+                                                       while (nav2.MoveToNextNamespace ())
+                                                               if (nav2.IsSamePosition (nav1))
+                                                                       return XmlNodeOrder.After;
+                                               }
+                                       }
+                                       else if (nav1.NodeType == XPathNodeType.Attribute)
+                                       {
+                                               if (nav2.NodeType == XPathNodeType.Namespace)
+                                                       return XmlNodeOrder.After;
+                                               else if (nav2.NodeType == XPathNodeType.Attribute)
+                                               {
+                                                       // match attributes
+                                                       while (nav2.MoveToNextAttribute ())
+                                                               if (nav2.IsSamePosition (nav1))
+                                                                       return XmlNodeOrder.After;
+                                               }
+                                       }
+                                       else
+                                       {
+                                               switch (nav2.NodeType) {
+                                               case XPathNodeType.Namespace:
+                                               case XPathNodeType.Attribute:
+                                                       return XmlNodeOrder.After;
+                                               }
+                                               // match children
+                                               while (nav2.MoveToNext ())
+                                                       if (nav2.IsSamePosition (nav1))
+                                                               return XmlNodeOrder.After;
+                                       }
+                                       return XmlNodeOrder.Before;
+                               }
+                               nav1.MoveToParent ();
+                               nav2.MoveToParent ();
+                       }
+                       return XmlNodeOrder.Unknown;
                }
 
                public virtual XPathExpression Compile (string xpath)
                {
-                       Tokenizer tokenizer = new Tokenizer (xpath);
                        XPathParser parser = new XPathParser ();
-                       Expression expr = (Expression) parser.yyparse (tokenizer);
-//                     Expression expr = (Expression) parser.yyparseDebug (tokenizer);
-                       return new CompiledExpression (expr);
+                       return new CompiledExpression (parser.Compile (xpath));
+               }
+               
+               internal virtual XPathExpression Compile (string xpath, System.Xml.Xsl.IStaticXsltContext ctx)
+               {
+                       XPathParser parser = new XPathParser (ctx);
+                       return new CompiledExpression (parser.Compile (xpath));
                }
 
                public virtual object Evaluate (string xpath)
@@ -81,14 +244,98 @@ namespace System.Xml.XPath
 
                public virtual object Evaluate (XPathExpression expr, XPathNodeIterator context)
                {
+                       return Evaluate (expr, context, null);
+               }
+               
+               internal virtual object Evaluate (XPathExpression expr, XPathNodeIterator context, NSResolver ctx)
+               {
+                       CompiledExpression cexpr = (CompiledExpression) expr;
+                       if (ctx == null)
+                               ctx = cexpr.NamespaceManager;
+                       
                        if (context == null)
-                               context = new NullIterator (this, new DefaultContext ());
-                       return ((CompiledExpression) expr).Evaluate ((BaseIterator) context);
+                               context = new NullIterator (this, ctx);
+                       BaseIterator iterContext = (BaseIterator) context;
+                       iterContext.NamespaceManager = ctx;
+                       return cexpr.Evaluate (iterContext);
                }
 
+               internal XPathNodeIterator EvaluateNodeSet (XPathExpression expr, XPathNodeIterator context, NSResolver ctx)
+               {
+                       CompiledExpression cexpr = (CompiledExpression) expr;
+                       if (ctx == null)
+                               ctx = cexpr.NamespaceManager;
+                       
+                       if (context == null)
+                               context = new NullIterator (this, cexpr.NamespaceManager);
+                       BaseIterator iterContext = (BaseIterator) context;
+                       iterContext.NamespaceManager = ctx;
+                       return cexpr.EvaluateNodeSet (iterContext);
+               }
+
+               internal string EvaluateString (XPathExpression expr, XPathNodeIterator context, NSResolver ctx)
+               {
+                       CompiledExpression cexpr = (CompiledExpression) expr;
+                       if (ctx == null)
+                               ctx = cexpr.NamespaceManager;
+                       
+                       if (context == null)
+                               context = new NullIterator (this, cexpr.NamespaceManager);
+                       BaseIterator iterContext = (BaseIterator) context;
+                       iterContext.NamespaceManager = ctx;
+                       return cexpr.EvaluateString (iterContext);
+               }
+
+               internal double EvaluateNumber (XPathExpression expr, XPathNodeIterator context, NSResolver ctx)
+               {
+                       CompiledExpression cexpr = (CompiledExpression) expr;
+                       if (ctx == null)
+                               ctx = cexpr.NamespaceManager;
+                       
+                       if (context == null)
+                               context = new NullIterator (this, cexpr.NamespaceManager);
+                       BaseIterator iterContext = (BaseIterator) context;
+                       iterContext.NamespaceManager = ctx;
+                       return cexpr.EvaluateNumber (iterContext);
+               }
+
+               internal bool EvaluateBoolean (XPathExpression expr, XPathNodeIterator context, NSResolver ctx)
+               {
+                       CompiledExpression cexpr = (CompiledExpression) expr;
+                       if (ctx == null)
+                               ctx = cexpr.NamespaceManager;
+                       
+                       if (context == null)
+                               context = new NullIterator (this, cexpr.NamespaceManager);
+                       BaseIterator iterContext = (BaseIterator) context;
+                       iterContext.NamespaceManager = ctx;
+                       return cexpr.EvaluateBoolean (iterContext);
+               }
+
+#if NET_2_0
+               public virtual string GetAttribute (string localName, string namespaceURI)
+               {
+                       XPathNavigator nav = Clone ();
+                       if (nav.MoveToAttribute (localName, namespaceURI))
+                               return nav.Value;
+                       else
+                               return String.Empty;
+               }
+
+               public virtual string GetNamespace (string name)
+               {
+                       XPathNavigator nav = Clone ();
+                       if (nav.MoveToNamespace (name))
+                               return nav.Value;
+                       else
+                               return String.Empty;
+               }
+
+#else
                public abstract string GetAttribute (string localName, string namespaceURI);
 
                public abstract string GetNamespace (string name);
+#endif
                
                object ICloneable.Clone ()
                {
@@ -118,13 +365,56 @@ namespace System.Xml.XPath
 
                public virtual bool Matches (XPathExpression expr)
                {
-                       XPathNodeIterator nodes = Select (expr);
+                       Expression e = ((CompiledExpression) expr).ExpressionNode;
+                       if (e is ExprRoot)
+                               return NodeType == XPathNodeType.Root;
+                       
+                       NodeTest nt = e as NodeTest;
+                       if (nt != null) {
+                               switch (nt.Axis.Axis) {
+                               case Axes.Child:
+                               case Axes.Attribute:
+                                       break;
+                               default:
+                                       throw new XPathException ("Only child and attribute pattern are allowed for a pattern.");
+                               }
+                               return nt.Match (((CompiledExpression)expr).NamespaceManager, this);
+                       }
+                       if (e is ExprFilter) {
+                               do {
+                                       e = ((ExprFilter) e).LeftHandSide;
+                               } while (e is ExprFilter);
+                               
+                               if (e is NodeTest && !((NodeTest) e).Match (((CompiledExpression) expr).NamespaceManager, this))
+                                       return false;
+                       }
+
+                       XPathResultType resultType = e.ReturnType;
+                       switch (resultType) {
+                       case XPathResultType.Any:
+                       case XPathResultType.NodeSet:
+                               break;
+                       default:
+                               return false;
+                       }
 
+                       switch (e.EvaluatedNodeType) {
+                       case XPathNodeType.Attribute:
+                       case XPathNodeType.Namespace:
+                               if (NodeType != e.EvaluatedNodeType)
+                                       return false;
+                               break;
+                       }
+
+                       XPathNodeIterator nodes;
+                       nodes = this.Select (expr);
                        while (nodes.MoveNext ()) {
                                if (IsSamePosition (nodes.Current))
                                        return true;
                        }
 
+                       // ancestors might select this node.
+
                        XPathNavigator navigator = Clone ();
 
                        while (navigator.MoveToParent ()) {
@@ -141,10 +431,57 @@ namespace System.Xml.XPath
 
                public abstract bool MoveTo (XPathNavigator other);
 
+#if NET_2_0
+               public virtual bool MoveToAttribute (string localName, string namespaceURI)
+               {
+                       if (MoveToFirstAttribute ()) {
+                               do {
+                                       if (LocalName == localName && NamespaceURI == namespaceURI)
+                                               return true;
+                               } while (MoveToNextAttribute ());
+                               MoveToParent ();
+                       }
+                       return false;
+               }
+
+               public virtual bool MoveToNamespace (string name)
+               {
+                       if (MoveToFirstNamespace ()) {
+                               do {
+                                       if (LocalName == name)
+                                               return true;
+                               } while (MoveToNextNamespace ());
+                               MoveToParent ();
+                       }
+                       return false;
+               }
+
+               public virtual bool MoveToFirst ()
+               {
+                       if (MoveToPrevious ()) {
+                               // It would be able to invoke MoveToPrevious() until the end, but this way would be much faster
+                               MoveToParent ();
+                               MoveToFirstChild ();
+                               return true;
+                       }
+                       return false;
+               }
+
+               public virtual void MoveToRoot ()
+               {
+                       while (MoveToParent ())
+                               ;
+               }
+#else
                public abstract bool MoveToAttribute (string localName, string namespaceURI);
 
+               public abstract bool MoveToNamespace (string name);
+
                public abstract bool MoveToFirst ();
 
+               public abstract void MoveToRoot ();
+#endif
+
                public abstract bool MoveToFirstAttribute ();
 
                public abstract bool MoveToFirstChild ();
@@ -158,8 +495,6 @@ namespace System.Xml.XPath
 
                public abstract bool MoveToId (string id);
 
-               public abstract bool MoveToNamespace (string name);
-
                public abstract bool MoveToNext ();
 
                public abstract bool MoveToNextAttribute ();
@@ -175,8 +510,6 @@ namespace System.Xml.XPath
 
                public abstract bool MoveToPrevious ();
 
-               public abstract void MoveToRoot ();
-
                public virtual XPathNodeIterator Select (string xpath)
                {
                        return Select (Compile (xpath));
@@ -184,71 +517,76 @@ namespace System.Xml.XPath
 
                public virtual XPathNodeIterator Select (XPathExpression expr)
                {
-                       BaseIterator iter = new NullIterator (this, new DefaultContext ());
-                       return ((CompiledExpression) expr).EvaluateNodeSet (iter);
+                       return Select (expr, null);
+               }
+               
+               internal virtual XPathNodeIterator Select (XPathExpression expr, NSResolver ctx)
+               {
+                       CompiledExpression cexpr = (CompiledExpression) expr;
+                       if (ctx == null)
+                               ctx = cexpr.NamespaceManager;
+                       
+                       BaseIterator iter = new NullIterator (this, ctx);
+                       return cexpr.EvaluateNodeSet (iter);
                }
 
                public virtual XPathNodeIterator SelectAncestors (XPathNodeType type, bool matchSelf)
                {
                        Axes axis = (matchSelf) ? Axes.AncestorOrSelf : Axes.Ancestor;
-                       NodeTest test = new NodeTypeTest (axis, type);
-                       return SelectTest (test);
+                       return SelectTest (new NodeTypeTest (axis, type));
                }
 
-               [MonoTODO]
                public virtual XPathNodeIterator SelectAncestors (string name, string namespaceURI, bool matchSelf)
                {
-                       if (namespaceURI != null && namespaceURI != "")
-                               throw new NotImplementedException ();
+                       if (name == null)
+                               throw new ArgumentNullException ("name");
+                       if (namespaceURI == null)
+                               throw new ArgumentNullException ("namespaceURI");
 
                        Axes axis = (matchSelf) ? Axes.AncestorOrSelf : Axes.Ancestor;
-                       QName qname = new QName ("", name);
-                       NodeTest test = new NodeNameTest (axis, qname);
-                       return SelectTest (test);
+                       XmlQualifiedName qname = new XmlQualifiedName (name, namespaceURI);
+                       return SelectTest (new NodeNameTest (axis, qname, true));
                }
 
                public virtual XPathNodeIterator SelectChildren (XPathNodeType type)
                {
-                       NodeTest test = new NodeTypeTest (Axes.Child, type);
-                       return SelectTest (test);
+                       return SelectTest (new NodeTypeTest (Axes.Child, type));
                }
 
-               [MonoTODO]
                public virtual XPathNodeIterator SelectChildren (string name, string namespaceURI)
                {
-                       if (namespaceURI != null && namespaceURI != "")
-                               throw new NotImplementedException ();
+                       if (name == null)
+                               throw new ArgumentNullException ("name");
+                       if (namespaceURI == null)
+                               throw new ArgumentNullException ("namespaceURI");
 
                        Axes axis = Axes.Child;
-                       QName qname = new QName ("", name);
-                       NodeTest test = new NodeNameTest (axis, qname);
-                       return SelectTest (test);
+                       XmlQualifiedName qname = new XmlQualifiedName (name, namespaceURI);
+                       return SelectTest (new NodeNameTest (axis, qname, true));
                }
 
                public virtual XPathNodeIterator SelectDescendants (XPathNodeType type, bool matchSelf)
                {
                        Axes axis = (matchSelf) ? Axes.DescendantOrSelf : Axes.Descendant;
-                       NodeTest test = new NodeTypeTest (axis, type);
-                       return SelectTest (test);
+                       return SelectTest (new NodeTypeTest (axis, type));
                }
 
-               [MonoTODO]
                public virtual XPathNodeIterator SelectDescendants (string name, string namespaceURI, bool matchSelf)
                {
-                       if (namespaceURI != null && namespaceURI != "")
-                               throw new NotImplementedException ();
+                       if (name == null)
+                               throw new ArgumentNullException ("name");
+                       if (namespaceURI == null)
+                               throw new ArgumentNullException ("namespaceURI");
+
 
                        Axes axis = (matchSelf) ? Axes.DescendantOrSelf : Axes.Descendant;
-                       QName qname = new QName ("", name);
-                       NodeTest test = new NodeNameTest (axis, qname);
-                       return SelectTest (test);
+                       XmlQualifiedName qname = new XmlQualifiedName (name, namespaceURI);
+                       return SelectTest (new NodeNameTest (axis, qname, true));
                }
 
                internal XPathNodeIterator SelectTest (NodeTest test)
                {
-                       Expression expr = new ExprStep (test, null);
-                       BaseIterator iter = new NullIterator (this, new DefaultContext ());
-                       return expr.EvaluateNodeSet (iter);
+                       return test.EvaluateNodeSet (new NullIterator (this));
                }
 
                public override string ToString ()
@@ -257,5 +595,284 @@ namespace System.Xml.XPath
                }
 
                #endregion
+
+#if NET_2_0
+
+               [MonoTODO]
+               public virtual bool CheckValidity (XmlSchemaSet schemas, ValidationEventHandler handler)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               [MonoTODO]
+               public virtual object CopyAsObject (Type targetType)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               public virtual XPathNavigator CreateNavigator ()
+               {
+                       return Clone ();
+               }
+
+               [MonoTODO]
+               public virtual object Evaluate (string xpath, IXmlNamespaceResolver nsResolver)
+               {
+                       return Evaluate (Compile (xpath), null, nsResolver);
+               }
+
+               [MonoTODO]
+               public virtual IDictionary GetNamespacesInScope (XmlNamespaceScope scope)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               public virtual string LookupNamespace (string prefix)
+               {
+                       return LookupNamespace (prefix, false);
+               }
+
+               public virtual string LookupNamespace (string prefix, bool atomizedNames)
+               {
+                       XPathNavigator nav = Clone ();
+                       if (nav.NodeType != XPathNodeType.Element)
+                               nav.MoveToParent ();
+                       if (nav.MoveToNamespace (prefix)) {
+                               if (atomizedNames)
+                                       return nav.NameTable.Add (nav.Value);
+                               else
+                                       return nav.Value;
+                       }
+                       return null;
+               }
+
+               public virtual string LookupPrefix (string namespaceUri)
+               {
+                       return LookupPrefix (namespaceUri, false);
+               }
+
+               [MonoTODO]
+               public virtual string LookupPrefix (string namespaceUri, bool atomizedNames)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               public virtual bool MoveToAttribute (string localName, string namespaceURI, bool atomizedNames)
+               {
+                       return MoveToAttribute (localName, namespaceURI);
+               }
+
+               private bool MoveTo (XPathNodeIterator iter)
+               {
+                       if (iter.MoveNext ()) {
+                               MoveTo (iter.Current);
+                               return true;
+                       }
+                       else
+                               return false;
+               }
+
+               public virtual bool MoveToChild (XPathNodeType type)
+               {
+                       return MoveTo (SelectChildren (type));
+               }
+
+               public virtual bool MoveToChild (string localName, string namespaceURI)
+               {
+                       return MoveTo (SelectChildren (localName, namespaceURI));
+               }
+
+               public virtual bool MoveToChild (string localName, string namespaceURI, bool atomizedNames)
+               {
+                       return MoveToChild (localName, namespaceURI);
+               }
+
+               public virtual bool MoveToDescendant (XPathNodeType type)
+               {
+                       return MoveTo (SelectDescendants (type, false));
+               }
+
+               public virtual bool MoveToDescendant (string localName, string namespaceURI)
+               {
+                       return MoveTo (SelectDescendants (localName, namespaceURI, false));
+               }
+
+               public virtual bool MoveToDescendant (string localName, string namespaceURI, bool atomizedNames)
+               {
+                       return MoveToDescendant (localName, namespaceURI);
+               }
+
+               public virtual bool MoveToNext (string localName, string namespaceURI)
+               {
+                       XPathNavigator nav = Clone ();
+                       while (nav.MoveToNext ()) {
+                               if (nav.LocalName == localName &&
+                                       nav.NamespaceURI == namespaceURI) {
+                                       MoveTo (nav);
+                                       return true;
+                               }
+                       }
+                       return false;
+               }
+
+               public virtual bool MoveToNext (string localName, string namespaceURI, bool atomizedNames)
+               {
+                       return MoveToNext (localName, namespaceURI);
+               }
+
+               public virtual bool MoveToNext (XPathNodeType type)
+               {
+                       XPathNavigator nav = Clone ();
+                       while (nav.MoveToNext ()) {
+                               if (nav.NodeType == type) {
+                                       MoveTo (nav);
+                                       return true;
+                               }
+                       }
+                       return false;
+               }
+
+               [MonoTODO]
+               public virtual XmlReader ReadSubtree ()
+               {
+                       throw new NotImplementedException ();
+               }
+
+               public virtual XPathNodeIterator Select (string xpath, IXmlNamespaceResolver nsResolver)
+               {
+                       return Select (Compile (xpath), nsResolver);
+               }
+
+               public virtual XPathNavigator SelectSingleNode (string xpath)
+               {
+                       return SelectSingleNode (xpath, null);
+               }
+
+               public virtual XPathNavigator SelectSingleNode (string xpath, IXmlNamespaceResolver nsResolver)
+               {
+                       XPathExpression expr = Compile (xpath);
+                       expr.SetContext (nsResolver);
+                       return SelectSingleNode (expr);
+               }
+
+               public XPathNavigator SelectSingleNode (XPathExpression expression)
+               {
+                       XPathNodeIterator iter = Select (expression);
+                       if (iter.MoveNext ())
+                               return iter.Current;
+                       else
+                               return null;
+               }
+
+               [MonoTODO]
+               public override object ValueAs (Type type, IXmlNamespaceResolver nsResolver)
+               {
+                       throw new NotImplementedException ();
+               }
+
+               [MonoTODO]
+               public virtual void WriteSubtree (XmlWriter writer)
+               {
+                       XmlReader st = ReadSubtree ();
+                       writer.WriteNode (st, false);
+               }
+
+               [MonoTODO]
+               public virtual string InnerXml {
+                       get { throw new NotImplementedException (); }
+               }
+
+               [MonoTODO]
+               public override bool IsNode {
+                       get { return true; }
+               }
+
+               [MonoTODO]
+               public virtual IKeyComparer NavigatorComparer {
+                       get { throw new NotImplementedException (); }
+               }
+
+               [MonoTODO]
+               public virtual string OuterXml {
+                       get {
+                               StringWriter sw = new StringWriter ();
+                               XmlTextWriter xtw = new XmlTextWriter (sw);
+                               WriteSubtree (xtw);
+                               xtw.Close ();
+                               return sw.ToString ();
+                       }
+               }
+
+               [MonoTODO]
+               public virtual IXmlSchemaInfo SchemaInfo {
+                       get { throw new NotImplementedException (); }
+               }
+
+               [MonoTODO]
+               public override object TypedValue {
+                       get { throw new NotImplementedException (); }
+               }
+
+               [MonoTODO]
+               public virtual object UnderlyingObject {
+                       get { throw new NotImplementedException (); }
+               }
+
+               [MonoTODO]
+               public override bool ValueAsBoolean {
+                       get { return XQueryConvert.StringToBoolean (Value); }
+               }
+
+               [MonoTODO]
+               public override DateTime ValueAsDateTime {
+                       get { return XmlConvert.ToDateTime (Value); }
+               }
+
+               [MonoTODO]
+               public override decimal ValueAsDecimal {
+                       get { return XQueryConvert.StringToDecimal (Value); }
+               }
+
+               [MonoTODO]
+               public override double ValueAsDouble {
+                       get { return XQueryConvert.StringToDouble (Value); }
+               }
+
+               [MonoTODO]
+               public override int ValueAsInt32 {
+                       get { return XQueryConvert.StringToInt (Value); }
+               }
+
+               [MonoTODO]
+               public override long ValueAsInt64 {
+                       get { return XQueryConvert.StringToInteger (Value); }
+               }
+
+               [MonoTODO]
+               public override ICollection ValueAsList {
+                       get { throw new NotImplementedException (); }
+               }
+
+               [MonoTODO]
+               public override float ValueAsSingle {
+                       get { return XQueryConvert.StringToFloat (Value); }
+               }
+
+               [MonoTODO]
+               public override Type ValueType {
+                       get { throw new NotImplementedException (); }
+               }
+
+               [MonoTODO]
+               public override XmlSchemaType XmlType {
+                       get { throw new NotImplementedException (); }
+               }
+
+               [MonoTODO]
+               protected XmlReader GetValidatingReader (XmlSchemaSet schemas, ValidationEventHandler handler, XmlSchemaType schemaType)
+               {
+                       throw new NotImplementedException ();
+               }
+#endif
        }
 }