* The Depth property was not implemented correctly and the Read method did not
[mono.git] / mcs / class / System.XML / System.Xml / XmlNode.cs
index eac9b6d1f343a81756c37843652c8190cd7d2944..d4d39a77aef518963f4a3e34284010eeb8e3f7b9 100644 (file)
-// -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
 //
 // System.Xml.XmlNode
 //
 // Author:
-//   Daniel Weber (daniel-weber@austin.rr.com)
+//   Kral Ferch <kral_ferch@hotmail.com>
+//
+// (C) 2002 Kral Ferch
 //
-// (C) 2001 Daniel Weber
 
 using System;
 using System.Collections;
+using System.IO;
+using System.Text;
 using System.Xml.XPath;
 
-namespace System.Xml 
+namespace System.Xml
 {
-       public abstract class XmlNode : ICloneable, IEnumerable, IXPathNavigable 
+       public abstract class XmlNode : ICloneable, IEnumerable, IXPathNavigable
        {
-               //======= Private data members ==============================================
-               private XmlNodeListAsArrayList _childNodes;
-               protected XmlDocument FOwnerDocument;
-               protected XmlNode _parent;
-
-               // Names of node
-               // for <foo:bar xmlns:foo="http://www.foobar.com/schema/foobar">... </foo:bar>
-               //      qualified name: foo:bar
-               //      namespaceURI = "http://www.foobar.com/schema/foobar"
-               //  localName = bar
-               //      prefix = foo
-               // Note that namespaces can be nested (child namespace != parent namespace)
-               // namespaces are optional
-               protected string Fname;
-               protected string FnamespaceURI;
-               protected string Fprefix;
-               protected string FlocalName;
-
-               // baseURI holds the location from which the document was loaded
-               // If the node was created from a document at c:\tmp.xml, then that's what will be here
-               protected string FbaseURI;
-
-               // value of the node (overriden in classes that do something different)
-               //      default behavior is just to store it
-               protected string Fvalue;
-               
-               //=====================================================================
-               // ============ Properties ============================================
-               //=====================================================================
-               /// <summary>
-               /// Get the XmlAttributeCollection representing the attributes
-               ///   on the node type.  Returns null if the node type is not XmlElement.
-               /// </summary>
-               public virtual XmlAttributeCollection Attributes 
+               #region Fields
+
+               XmlDocument ownerDocument;
+               XmlNode parentNode;
+
+               #endregion
+
+               #region Constructors
+
+               internal XmlNode (XmlDocument ownerDocument)
                {
-                       get 
-                       {
-                               return null;
-                       }
+                       this.ownerDocument = ownerDocument;
                }
-               /// <summary>
-               ///  Return the base Uniform Resource Indicator (URI) used to resolve
-               ///  this node, or String.Empty.
-               /// </summary>
-               public virtual string BaseURI 
-               {
-                       get 
-                       {
-                               return FbaseURI;
-                       }
 
+               #endregion
+
+               #region Properties
+
+               public virtual XmlAttributeCollection Attributes
+               {
+                       get { return null; }
                }
-               /// <summary>
-               /// Return all child nodes of this node.  If there are no children,
-               ///  return an empty XmlNodeList;
-               /// </summary>
-               public virtual XmlNodeList ChildNodes 
+
+               public virtual string BaseURI
                {
-                       get 
-                       {
-                               if (_childNodes == null)
-                                       _childNodes = new XmlNodeListAsArrayList();
+                       get { return ParentNode.BaseURI; }
+               }
 
-                               return _childNodes as XmlNodeList;
+               public virtual XmlNodeList ChildNodes {
+                       get {
+                               return new XmlNodeListChildren(this);
                        }
                }
-               
-               /// <summary>
-               /// Return first child node as XmlNode or null
-               /// if the node has no children
-               /// </summary>
-               public virtual XmlNode FirstChild 
-               {
-                       get
-                       {
-                               if (ChildNodes.Count == 0)
+
+               public virtual XmlNode FirstChild {
+                       get {
+                               if (LastChild != null) {
+                                       return LastLinkedChild.NextLinkedSibling;
+                               }
+                               else {
                                        return null;
-                               else
-                                       return ChildNodes[0];
+                               }
                        }
                }
 
-               /// <summary>
-               ///             Return true if the node has children
-               /// </summary>
-               public virtual bool HasChildNodes 
-               {
-                       get 
-                       {
-                               if (ChildNodes.Count == 0)
-                                       return true;
-                               else
-                                       return false;
-                       }
+               public virtual bool HasChildNodes {
+                       get { return LastChild != null; }
                }
 
-               /// <summary>
-               /// Get or Set the concatenated values of node and children
-               /// </summary>
-               public virtual string InnerText
-               {
-                       get
-                       {
-                               // TODO - implement set InnerText()
-                               throw new NotImplementedException();
+               [MonoTODO]
+               public virtual string InnerText {
+                       get {
+                               StringBuilder builder = new StringBuilder ();
+                               AppendChildValues (this, builder);
+                               return builder.ToString ();
                        }
 
-                       set 
-                       {
-                               // TODO - implement set InnerText()
-                               throw new NotImplementedException();
-                       }
+                       set { throw new NotImplementedException (); }
                }
 
-               /// <summary>
-               /// Get/Set the XML representing just the child nodes of this node
-               /// </summary>
-               public virtual string InnerXml
+               private void AppendChildValues (XmlNode parent, StringBuilder builder)
                {
-                       get
-                       {
-                               // TODO - implement set InnerXml()
-                               throw new NotImplementedException();
-                       }
+                       XmlNode node = parent.FirstChild;
 
-                       set 
-                       {
-                               // TODO - implement set InnerXml()
-                               throw new NotImplementedException();
+                       while (node != null) {
+                               if (node.NodeType == XmlNodeType.Text)
+                                       builder.Append (node.Value);
+                               AppendChildValues (node, builder);
+                               node = node.NextSibling;
                        }
                }
 
-               /// <summary>
-               /// Property Get - true if node is read-only
-               /// </summary>
-               public virtual bool IsReadOnly
-               {
-                       get
-                       {
-                               return OwnerDocument.IsReadOnly;
-                       }
-               }
+               [MonoTODO("Setter.")]
+               public virtual string InnerXml {
+                       get {
+                               StringWriter sw = new StringWriter ();
+                               XmlTextWriter xtw = new XmlTextWriter (sw);
 
-               /// <summary>
-               /// Return the child element named [string].  Returns XmlElement
-               /// Indexer for XmlNode class.
-               /// </summary>
-               [System.Runtime.CompilerServices.IndexerNameAttribute("Item")]
-               public virtual XmlElement this [String index]
-               {
-                       get 
-                       {
-                               // TODO - implement XmlNode.Item(string)
-                               throw new NotImplementedException();
-                       }
-               }
+                               WriteContentTo(xtw);
 
-               /// <summary>
-               /// Get the last child node, or null if there are no nodes
-               /// </summary>
-               public virtual XmlNode LastChild
-               {
-                       get
-                       {
-                if (_childNodes.Count == 0)
-                                return null;
-                               else
-                                return _childNodes.Item(_childNodes.Count - 1);
+                               return sw.GetStringBuilder().ToString();
                        }
 
+                       set { throw new NotImplementedException (); }
                }
 
-               /// <summary>
-               /// Returns the local name of the node with qualifiers removed
-               /// LocalName of ns:elementName = "elementName"
-               /// </summary>
-               public abstract string LocalName {get;}
+               public virtual bool IsReadOnly {
+                       get { return false; }
+               }
 
-               /// <summary>
-               /// Get the qualified node name
-               /// derived classes must implement as behavior varies
-               /// by tag type.
-               /// </summary>
-               public abstract string Name { get; }
+               [System.Runtime.CompilerServices.IndexerName("Item")]
+               public virtual XmlElement this [string name] {
+                       get { 
+                               foreach (XmlNode node in ChildNodes) {
+                                       if ((node.NodeType == XmlNodeType.Element) &&
+                                           (node.Name == name)) {
+                                               return (XmlElement) node;
+                                       }
+                               }
 
-               /// <summary>
-               /// Get the namespace URI or String.Empty if none
-               /// </summary>
-               public virtual string NamespaceURI
-               {
-                       get
-                       {
-                               // TODO - implement Namespace URI, or determine abstractness
-                               throw new NotImplementedException("XmlNode.NamespaceURI not implemented");
+                               return null;
                        }
                }
 
-               /// <summary>
-               /// Get the node immediatelly following this node, or null
-               /// </summary>
-               public virtual XmlNode NextSibling 
-               {
-                       get
-                       {
-                               
-                               if (_parent != null)
-                               {
-                                       XmlNodeListAsArrayList children = _parent.ChildNodes as XmlNodeListAsArrayList;
-                                       int ourIndex = children.data.IndexOf(this);
-                                       return children[ourIndex + 1];
+               [System.Runtime.CompilerServices.IndexerName("Item")]
+               public virtual XmlElement this [string localname, string ns] {
+                       get { 
+                               foreach (XmlNode node in ChildNodes) {
+                                       if ((node.NodeType == XmlNodeType.Element) &&
+                                           (node.LocalName == localname) && 
+                                           (node.NamespaceURI == ns)) {
+                                               return (XmlElement) node;
+                                       }
                                }
-                               else
-                                       return null;
+
+                               return null;
                        }
                }
 
-               public virtual XmlNodeType NodeType 
-               {
-                       get
-                       {
-                               return XmlNodeType.None;
-                       }
+               public virtual XmlNode LastChild {
+                       get { return LastLinkedChild; }
                }
 
-               /// <summary>
-               /// Return the string representing this node and all it's children
-               /// </summary>
-               public virtual string OuterXml
-               {
-                       get
-                       {
-                               // TODO - implement OuterXml {get;}
-                               throw new NotImplementedException();
-                       }
+               internal virtual XmlLinkedNode LastLinkedChild {
+                       get { return null; }
+                       set { }
                }
 
-               /// <summary>
-               /// Return owning document.
-               /// If this nodeType is a document, return null
-               /// </summary>
-               public virtual XmlDocument OwnerDocument
-               {
-                       get
-                       {
-                               return FOwnerDocument;
-                       }
+               public abstract string LocalName { get; }
+
+               public abstract string Name     { get; }
+
+               public virtual string NamespaceURI {
+                       get { return String.Empty; }
                }
 
-               /// <summary>
-               /// Returns the parent node, or null
-               /// Return value depends on superclass node type
-               /// </summary>
-               public virtual XmlNode ParentNode
-               {
-                       get
-                       {
-                               return _parent;
-                       }
+               public virtual XmlNode NextSibling {
+                       get { return null; }
                }
-               
-               /// <summary>
-               /// set/get the namespace prefix for this node, or 
-               /// string.empty if it does not exist
-               /// </summary>
-               public virtual string Prefix 
-               {
-                       get
-                       {
-                               return Fprefix;
-                       }
-                       
-                       set
-                       {
-                               // TODO - validation on XmlNode.Prefix {set;}? (no)
-                               Fprefix = value;
+
+               public abstract XmlNodeType NodeType { get;     }
+
+               public virtual string OuterXml {
+                       get {
+                               StringWriter sw = new StringWriter ();
+                               XmlTextWriter xtw = new XmlTextWriter (sw);
+
+                               WriteTo(xtw);
+
+                               return sw.GetStringBuilder().ToString();
                        }
                }
 
-               /// <summary>
-               /// The preceding XmlNode or null
-               /// </summary>
+               public virtual XmlDocument OwnerDocument {
+                       get { return ownerDocument; }
+               }
+
+               public virtual XmlNode ParentNode {
+                       get { return parentNode; }
+               }
+
+               public virtual string Prefix {
+                       get { return String.Empty; }
+                       set {}
+               }
+
                public virtual XmlNode PreviousSibling {
-                       get
-                       {
-                               if (_parent != null)
-                               {
-                                       XmlNodeListAsArrayList children = _parent.ChildNodes as XmlNodeListAsArrayList;
-                                       int ourIndex = children.data.IndexOf(this);
-                                       return children[ourIndex - 1];
-                               }
-                               else
-                                       return null;
-                       }
+                       get { return null; }
                }
 
-               /// <summary>
-               /// Get/Set the value for this node
-               /// </summary>
-               public virtual string Value 
-               {
-                       get
-                       {
-                               return Fvalue;
-                       }
-                       
-                       set
-                       {
-                               Fvalue = value;
-                       }
+               public virtual string Value {
+                       get { return null; }
+                       set { throw new InvalidOperationException ("This node does not have a value"); }
                }
 
-               //=====================================================================
-               //======= Methods =====================================================
-               //=====================================================================
-               /// <summary>
-               /// Appends the specified node to the end of the child node list
-               /// </summary>
-               /// <param name="newChild"></param>
-               /// <returns></returns>
+               #endregion
+
+               #region Methods
+
                public virtual XmlNode AppendChild (XmlNode newChild)
                {
-                       _childNodes.Add(newChild);
-                       return newChild;
+                       XmlDocument ownerDoc = (NodeType == XmlNodeType.Document) ? (XmlDocument)this : OwnerDocument;
+
+                       ownerDoc.onNodeInserting (newChild, this);
+
+                       if (NodeType == XmlNodeType.Document || NodeType == XmlNodeType.Element || NodeType == XmlNodeType.Attribute) {
+                               
+                               if (newChild.OwnerDocument != ownerDoc)
+                                       throw new ArgumentException ("Can't append a node created by another document.");
+
+                               XmlLinkedNode newLinkedChild = (XmlLinkedNode) newChild;
+                               XmlLinkedNode lastLinkedChild = LastLinkedChild;
+
+                               newLinkedChild.parentNode = this;
+                               
+                               if (lastLinkedChild != null) {
+                                       newLinkedChild.NextLinkedSibling = lastLinkedChild.NextLinkedSibling;
+                                       lastLinkedChild.NextLinkedSibling = newLinkedChild;
+                               } else
+                                       newLinkedChild.NextLinkedSibling = newLinkedChild;
+                               
+                               LastLinkedChild = newLinkedChild;
+
+                               ownerDoc.onNodeInserted (newChild, newChild.ParentNode);
+
+                               return newChild;
+                       } else
+                               throw new InvalidOperationException();
                }
 
-               /// <summary>
-               /// Return a clone of this node
-               /// </summary>
-               /// <returns></returns>
-               public virtual object Clone()
+               [MonoTODO]
+               public virtual XmlNode Clone ()
                {
-                       // TODO - implement XmlNode.Clone() as object
-                       throw new NotImplementedException("object XmlNode.Clone() not implmented");
-               }
-
-               /// <summary>
-               /// Return a clone of the node
-               /// </summary>
-               /// <param name="deep">Make copy of all children</param>
-               /// <returns>Cloned node</returns>
-               public abstract XmlNode CloneNode( bool deep);
-
-               /// <summary>
-               /// Return an XPathNavigator for navigating this node
-               /// </summary>
-               /// <returns></returns>
-               public System.Xml.XPath.XPathNavigator CreateNavigator()
+                       throw new NotImplementedException ();
+               }
+
+               public abstract XmlNode CloneNode (bool deep);
+
+               [MonoTODO]
+               public XPathNavigator CreateNavigator ()
                {
-                       // TODO - implement CreateNavigator()
-                       throw new NotImplementedException();
+                       return new XmlDocumentNavigator(this);
                }
 
-               /// <summary>
-               /// Provide support for "for each" 
-               /// </summary>
-               /// <returns></returns>
-               public IEnumerator GetEnumerator()
+               public IEnumerator GetEnumerator ()
                {
-                       return _childNodes.data.GetEnumerator();
+                       return new XmlNodeListChildren(this).GetEnumerator();
                }
 
-               /// <summary>
-               /// Look up the closest namespace for this node that is in scope for the given prefix
-               /// </summary>
-               /// <param name="prefix"></param>
-               /// <returns>Namespace URI</returns>
-               public virtual string GetNamespaceOfPrefix(string prefix)
+               [MonoTODO]
+               public virtual string GetNamespaceOfPrefix (string prefix)
                {
-                       // TODO - implement GetNamespaceOfPrefix()
-                       throw new NotImplementedException();
+                       throw new NotImplementedException ();
                }
 
-               /// <summary>
-               /// Get the closest xmlns declaration for the given namespace URI that is in scope.
-               /// Returns the prefix defined in that declaration.
-               /// </summary>
-               /// <param name="namespaceURI"></param>
-               /// <returns></returns>
-               public virtual string GetPrefixOfNamespace(string namespaceURI)
+               [MonoTODO]
+               public virtual string GetPrefixOfNamespace (string namespaceURI)
                {
-                       // TODO - implement GetPrefixOfNamespace
-                       throw new NotImplementedException();
-               }
-               
-               /// <summary>
-               /// Insert newChild directly after the reference node.
-               /// If refChild is null, newChild is inserted at the beginning of childnodes.
-               /// If newChild is a document fragment, all nodes are inserted after refChild.
-               /// If newChild is already in the tree, it is first removed.
-               /// </summary>
-               /// <exception cref="ArgumentException">NewChild was created from differant document.
-               /// RefChild not a child of this node or null.
-               /// Node is read-only</exception>
-               /// <exception cref="InvalidOperationException">Node is of type that does not have children
-               /// Node to insert is an ancestor of this node.</exception>
-               /// <param name="newChild">Child node to insert.</param>
-               /// <param name="refChild">Reference node to insert after</param>
-               /// <returns>Removed node, or null if no node removed.</returns>
-               public virtual XmlNode InsertAfter(XmlNode newChild, XmlNode refChild)
+                       throw new NotImplementedException ();
+               }
+
+               object ICloneable.Clone ()
                {
-                       // Checks parent not ancestor, arguments valid, etc.  Throws exception on error
-                       InsertionCheck(newChild, refChild);
-
-                       // Scan the node list, looking for refChild and seeing if newChild is in the list
-                       // Note that if refNode is null (prepend), we don't want to do the .Equals(null)
-                       XmlNode retval = null;
-                       int refNodeIndex = -1;
-                       
-                       for (int i = 0; i < _childNodes.Count; i++)
-                       {
-                               XmlNode e = _childNodes.data[i] as XmlNode;
-                               if (e.Equals(newChild))
-                               {
-                                       retval = e;
-                                       FOwnerDocument.onNodeRemoving(newChild, newChild.ParentNode);
-                                       _childNodes.data.RemoveAt(i);
-                                       newChild.setParent(null);
-                                       FOwnerDocument.onNodeRemoved(newChild, null);
-                                       break;
-               
-                               }
+                       return Clone ();
+               }
 
-                               if ( (refChild != null ) & ( e.Equals(refChild) ) )
-                               {
-                                       refNodeIndex = i;
+               IEnumerator IEnumerable.GetEnumerator ()
+               {
+                       return GetEnumerator ();
+               }
 
-                                       if (retval != null)
-                                               break;
-                               }
-                       }
+               [MonoTODO]
+               public virtual XmlNode InsertAfter (XmlNode newChild, XmlNode refChild)
+               {
+                       throw new NotImplementedException ();
+               }
 
-                       if ( ( refNodeIndex == -1 ) & (refChild != null) )
-                               throw new ArgumentException("Reference node not found (and not null) in call to XmlNode.InsertAfter()");
+               [MonoTODO]
+               public virtual XmlNode InsertBefore (XmlNode newChild, XmlNode refChild)
+               {
+                       throw new NotImplementedException ();
+               }
 
-                       FOwnerDocument.onNodeInserting(newChild, this);
+               [MonoTODO]
+               public virtual void Normalize ()
+               {
+                       throw new NotImplementedException ();
+               }
 
-                       if (refChild == null)
-                               refNodeIndex = 0;
-                       else
-                               refNodeIndex++;                 // insert after reference...
+               [MonoTODO]
+               public virtual XmlNode PrependChild (XmlNode newChild)
+               {
+                       throw new NotImplementedException ();
+               }
 
-                       if (newChild.NodeType == XmlNodeType.DocumentFragment)
-                       {
-                               // Insert all children, starting from refNodeIndex (0,1,2...n)
-                               for (int i = 0; i < newChild.ChildNodes.Count; i++)
-                               {
-                                       XmlNode e = newChild.ChildNodes[i] as XmlNode;
-                                       FOwnerDocument.onNodeInserting(e, this);
-                                       _childNodes.data.Insert(refNodeIndex, newChild.ChildNodes[i]);
-                                       e.setParent(this);
-                                       FOwnerDocument.onNodeInserted(newChild, this);
-                                       refNodeIndex ++;
-                               }
-                       }
-                       else
-                       {
-                               FOwnerDocument.onNodeInserting(newChild, this);
-                               _childNodes.data.Insert(refNodeIndex, newChild);
-                               newChild.setParent(this);
-                               FOwnerDocument.onNodeInserted(newChild, this);
-                       }
+               public virtual void RemoveAll ()
+               {
+                       XmlDocument ownerDoc = (NodeType == XmlNodeType.Document) ? (XmlDocument)this : OwnerDocument;
+
+                       ownerDoc.onNodeRemoving (this, this.ParentNode);
+                       LastLinkedChild = null;
+                       ownerDoc.onNodeRemoved (this, this.ParentNode);
+               }
 
-                       return retval;
-               }
-               
-               /// <summary>
-               /// Insert newChild directly before the reference node.
-               /// If refChild is null, newChild is inserted at the end of childnodes.
-               /// If newChild is a document fragment, all nodes are inserted before refChild.
-               /// If newChild is already in the tree, it is first removed.
-               /// </summary>
-               /// <exception cref="ArgumentException">NewChild was created from different document.
-               /// RefChild not a child of this node, or is null.
-               /// Node is read-only</exception>
-               /// <exception cref="InvalidOperationException">Node is of type that does not have children.
-               /// Node to insert is an ancestor of this node.</exception>
-               /// <param name="newChild">Child node to insert.</param>
-               /// <param name="refChild">Reference node to insert after</param>
-               /// <returns>Removed node, or null if no node removed.</returns>
-               public virtual XmlNode InsertBefore(XmlNode newChild, XmlNode refChild)
+               public virtual XmlNode RemoveChild (XmlNode oldChild)
                {
-                       // Checks parent not ancestor, arguments valid, etc.  Throws exception on error
-                       InsertionCheck(newChild, refChild);
-
-                       // Scan the node list, looking for refChild and seeing if newChild is in the list
-                       XmlNode retval = null;
-                       int refNodeIndex = -1;
-                       
-                       for (int i = 0; i < _childNodes.Count; i++)
+                       OwnerDocument.onNodeRemoving (oldChild, oldChild.ParentNode);
+
+                       if (NodeType == XmlNodeType.Document || NodeType == XmlNodeType.Element || NodeType == XmlNodeType.Attribute) 
                        {
-                               XmlNode e = _childNodes.data[i] as XmlNode;
-                               if (e.Equals(newChild))
-                               {
-                                       retval = e;
-                                       FOwnerDocument.onNodeRemoving(newChild, newChild.ParentNode);
-                                       _childNodes.data.RemoveAt(i);
-                                       newChild.setParent(null);
-                                       FOwnerDocument.onNodeRemoved(newChild, null);
-                                       break;
-                               }
+                               if (IsReadOnly)
+                                       throw new ArgumentException();
 
-                               if ( (refChild != null ) & ( e.Equals(refChild) ) )
-                               {
-                                       refNodeIndex = i;
+                               if (Object.ReferenceEquals(LastLinkedChild, LastLinkedChild.NextLinkedSibling) && Object.ReferenceEquals(LastLinkedChild, oldChild))
+                                       LastLinkedChild = null;
+                               else {
+                                       XmlLinkedNode oldLinkedChild = (XmlLinkedNode)oldChild;
+                                       XmlLinkedNode beforeLinkedChild = LastLinkedChild;
+                                       
+                                       while (!Object.ReferenceEquals(beforeLinkedChild.NextLinkedSibling, LastLinkedChild) && !Object.ReferenceEquals(beforeLinkedChild.NextLinkedSibling, oldLinkedChild))
+                                               beforeLinkedChild = beforeLinkedChild.NextLinkedSibling;
 
-                                       if (retval != null)
-                                               break;
-                               }
-                       }
+                                       if (!Object.ReferenceEquals(beforeLinkedChild.NextLinkedSibling, oldLinkedChild))
+                                               throw new ArgumentException();
 
-                       if ( ( refNodeIndex == -1 ) & (refChild != null) )
-                               throw new ArgumentException("Reference node not found (and not null) in call to XmlNode.InsertAfter()");
+                                       beforeLinkedChild.NextLinkedSibling = oldLinkedChild.NextLinkedSibling;
+                                       oldLinkedChild.NextLinkedSibling = null;
+                                }
 
-                       if (refChild == null)
-                               refNodeIndex = _childNodes.Count;
+                               OwnerDocument.onNodeRemoved (oldChild, oldChild.ParentNode);
 
-                       if (newChild.NodeType == XmlNodeType.DocumentFragment)
-                       {
-                               // Insert all children, starting from refNodeIndex (0,1,2...n)
-                               for (int i = 0; i < newChild.ChildNodes.Count; i++)
-                               {
-                                       XmlNode e = newChild.ChildNodes[i] as XmlNode;
-                                       FOwnerDocument.onNodeInserting(e, this);
-                                       _childNodes.data.Insert(refNodeIndex, newChild.ChildNodes[i]);
-                                       e.setParent(this);
-                                       FOwnerDocument.onNodeInserted(newChild, this);
-                                       refNodeIndex ++;
-                               }
-                       }
+                               return oldChild;
+                       } 
                        else
-                       {
-                               newChild.OwnerDocument.onNodeInserting(newChild, this);
-                               _childNodes.data.Insert(refNodeIndex, newChild);
-                               newChild.setParent(this);
-                               newChild.OwnerDocument.onNodeInserted(newChild, this);
-                       }
-
-                       return retval;
+                               throw new ArgumentException();
                }
 
-               /// <summary>
-               /// Put all nodes under this node in "normal" form
-               /// Whatever that means...
-               /// </summary>
-               public virtual void Normalize()
+               [MonoTODO]
+               public virtual XmlNode ReplaceChild (XmlNode newChild, XmlNode oldChild)
                {
-                       // TODO - Implement Normalize()
-                       throw new NotImplementedException();
+                       throw new NotImplementedException ();
                }
 
-               /// <summary>
-               /// Add the specified child to the beginning of the child node list
-               /// </summary>
-               /// <param name="newChild">Node to add</param>
-               /// <returns>The node added</returns>
-               public virtual XmlNode PrependChild(XmlNode newChild)
+               public XmlNodeList SelectNodes (string xpath)
                {
-                       return InsertAfter(newChild, null);
+                       return SelectNodes (xpath, null);
                }
 
-               /// <summary>
-               /// Remove all children and attributes
-               /// </summary>
-               public virtual void RemoveAll()
+               [MonoTODO]
+               public XmlNodeList SelectNodes (string xpath, XmlNamespaceManager nsmgr)
                {
-                       if (_childNodes == null)
-                               return;
-                       else
+                       XPathNavigator nav = CreateNavigator ();
+                       XPathExpression expr = nav.Compile (xpath);
+                       if (nsmgr != null)
+                               expr.SetContext (nsmgr);
+                       XPathNodeIterator iter = nav.Select (expr);
+                       ArrayList rgNodes = new ArrayList ();
+                       while (iter.MoveNext ())
                        {
-                               // Remove in order, 0..n
-                               while (_childNodes.Count > 0)
-                               {
-                                       XmlNode e = _childNodes[0];
-                                       FOwnerDocument.onNodeRemoving(e, this);
-                                       e.setParent(null);
-                                       _childNodes.data.RemoveAt(0);
-                                       FOwnerDocument.onNodeRemoved(e, null);
-                               }
+                               rgNodes.Add (((XmlDocumentNavigator) iter.Current).Node);
                        }
+                       return new XmlNodeArrayList (rgNodes);
                }
 
-               /// <summary>
-               /// Remove specified child node
-               /// </summary>
-               /// <param name="oldChild"></param>
-               /// <returns>Removed node</returns>
-               public virtual XmlNode RemoveChild(XmlNode oldChild)
+               public XmlNode SelectSingleNode (string xpath)
                {
-                       // TODO - implement RemoveChild(oldChild)
-                       throw new NotImplementedException();
+                       return SelectSingleNode (xpath, null);
                }
 
-               /// <summary>
-               /// Select a list of nodes matching the xpath
-               /// </summary>
-               /// <param name="xpath"></param>
-               /// <returns>matching nodes</returns>
-               public XmlNodeList SelectNodes( string xpath)
+               [MonoTODO]
+               public XmlNode SelectSingleNode (string xpath, XmlNamespaceManager nsmgr)
                {
-                       // TODO - imlement SelectNodes(xpath)
-                       throw new NotImplementedException();
-               }
-
-               /// <summary>
-               /// Select a list of nodes matching the xpath.  Any prefixes are resolved
-               /// using the passed namespace manager
-               /// </summary>
-               /// <param name="xpath"></param>
-               /// <param name="nsmgr"></param>
-               /// <returns></returns>
-               public XmlNodeList SelectNodes(string xpath, XmlNamespaceManager nsmgr)
-               {
-                       // TODO - implement SelectNodes(xpath, nsmgr)
-                       throw new NotImplementedException();
+                       XPathNavigator nav = CreateNavigator ();
+                       XPathExpression expr = nav.Compile (xpath);
+                       if (nsmgr != null)
+                               expr.SetContext (nsmgr);
+                       XPathNodeIterator iter = nav.Select (expr);
+                       if (!iter.MoveNext ())
+                               return null;
+                       return ((XmlDocumentNavigator) iter.Current).Node;
                }
 
-               /// <summary>
-               /// Selects the first node that matches xpath
-               /// </summary>
-               /// <param name="?"></param>
-               /// <returns></returns>
-               public XmlNode SelectSingleNode(string xpatch)
+               internal void SetParentNode (XmlNode parent)
                {
-                       // TODO - implement SelectSingeNode(xpath)
-                       throw new NotImplementedException();
-               }
-
-               /// <summary>
-               /// Returns the first node that matches xpath
-               /// Uses the passed namespace manager to resolve namespace URI's
-               /// </summary>
-               /// <param name="xpath"></param>
-               /// <param name="nsmgr"></param>
-               /// <returns></returns>
-               public XmlNode SelectSingleNode(string xpath, XmlNamespaceManager nsmgr)
-               {
-                       // Implement SelectSingleNode(xpath, nsmgr)
-                       throw new NotImplementedException();
+                       parentNode = parent;
                }
 
-               /// <summary>
-               /// Tests if the DOM implementation supports the passed feature
-               /// </summary>
-               /// <param name="feature"></param>
-               /// <param name="version"></param>
-               /// <returns></returns>
-               public virtual bool Supports(string feature, string version)
+               [MonoTODO]
+               public virtual bool Supports (string feature, string version)
                {
-                       //TODO - implement Supports(feature, version)
-                       throw new NotImplementedException();
+                       throw new NotImplementedException ();
                }
 
-               /// <summary>
-               /// Returns a string representation of the current node and it's children
-               /// </summary>
-               /// <returns></returns>
-               public override string ToString()
-               {
-                       // TODO - implement ToString()
-                       throw new NotImplementedException();
-               }
-
-               /// <summary>
-               /// Saves all children of the current node to the passed writer
-               /// </summary>
-               /// <param name="w"></param>
-               public abstract void WriteContentTo(XmlWriter w);
-               
-               /// <summary>
-               /// Saves the current node to writer w
-               /// </summary>
-               /// <param name="w"></param>
-               public abstract void WriteTo(XmlWriter w);
-
-               //======= Internal methods    ===============================================
-               /// <summary>
-               /// accessor {set;} for parentNode only visible internally.
-               /// </summary>
-               /// <param name="newParent">new parent node.</param>
-               internal void setParent( XmlNode newParent)
-               {
-                       _parent = newParent;
-               }
-               
-               //======= Protected methods    ==============================================
-
-               //======= Private Methods ===================================================
-               /// <summary>
-               /// Helper function to perform checks required before insrting a node.
-               /// Throws applicable exceptions on error.
-               /// </summary>
-               /// <param name="newChild"></param>
-               /// <param name="refChild"></param>
-               private void InsertionCheck( XmlNode newChild, XmlNode refChild)
-               {
-                       if (newChild == null)
-                               throw new ArgumentNullException("Null newNode passed to InsertAfter()");
-
-                       if (newChild.Equals(this))
-                               throw new ArgumentException("Cannot insert node onto itself");
-
-                       if (NodeType != XmlNodeType.Document && !FOwnerDocument.Equals( newChild.OwnerDocument) )
-                               throw new ArgumentException("Reference node has different owner document than this node");
-               
-                       XmlDocument ownerDocument = newChild.OwnerDocument;
-
-                       if (ownerDocument.IsReadOnly )
-                               throw new ArgumentException("Operation not supported - tree is read-only");
-
-                       //Check that insert node is not in our path to the root
-                       XmlNode curParent = _parent;
-                       while ( (curParent != null) & (! ownerDocument.Equals(curParent) ))
-                       {
-                               if (curParent.Equals(newChild) )
-                                       throw new ArgumentException("Cannot insert ancestor a node");
-                               curParent = curParent.ParentNode;
-                       }
-               }
-
-               // Constructors
-               //===========================================================================
-               //When we're first created, we won't know parent, etc.
-               internal XmlNode( XmlDocument aOwnerDoc )
-               {
-                       // Don't create childnodes object, since not all derived classes have children
-                       FOwnerDocument = aOwnerDoc;
-               }
+               public abstract void WriteContentTo (XmlWriter w);
 
-       }       // XmlNode
-}      // using namespace System.Xml
+               public abstract void WriteTo (XmlWriter w);
 
-               
+               #endregion
+       }
+}