* The Depth property was not implemented correctly and the Read method did not
[mono.git] / mcs / class / System.XML / System.Xml / XmlNode.cs
index bfe9a942761d5bfb809c86eecf380a373edcb663..d4d39a77aef518963f4a3e34284010eeb8e3f7b9 100644 (file)
@@ -1,5 +1,5 @@
 //
-// System.Xml.XmlProcessingInstruction
+// System.Xml.XmlNode
 //
 // Author:
 //   Kral Ferch <kral_ferch@hotmail.com>
@@ -9,18 +9,24 @@
 
 using System;
 using System.Collections;
+using System.IO;
+using System.Text;
 using System.Xml.XPath;
 
 namespace System.Xml
 {
        public abstract class XmlNode : ICloneable, IEnumerable, IXPathNavigable
        {
+               #region Fields
+
                XmlDocument ownerDocument;
                XmlNode parentNode;
 
+               #endregion
+
                #region Constructors
 
-               protected internal XmlNode(XmlDocument ownerDocument)
+               internal XmlNode (XmlDocument ownerDocument)
                {
                        this.ownerDocument = ownerDocument;
                }
@@ -34,20 +40,18 @@ namespace System.Xml
                        get { return null; }
                }
 
-               [MonoTODO]
                public virtual string BaseURI
                {
-                       get { throw new NotImplementedException (); }
+                       get { return ParentNode.BaseURI; }
                }
 
-               [MonoTODO]
-               public virtual XmlNodeList ChildNodes
-               {
-                       get { throw new NotImplementedException (); }
+               public virtual XmlNodeList ChildNodes {
+                       get {
+                               return new XmlNodeListChildren(this);
+                       }
                }
 
-               public virtual XmlNode FirstChild
-               {
+               public virtual XmlNode FirstChild {
                        get {
                                if (LastChild != null) {
                                        return LastLinkedChild.NextLinkedSibling;
@@ -58,116 +62,134 @@ namespace System.Xml
                        }
                }
 
-               public virtual bool HasChildNodes
-               {
+               public virtual bool HasChildNodes {
                        get { return LastChild != null; }
                }
 
                [MonoTODO]
-               public virtual string InnerText
-               {
-                       get { throw new NotImplementedException (); }
+               public virtual string InnerText {
+                       get {
+                               StringBuilder builder = new StringBuilder ();
+                               AppendChildValues (this, builder);
+                               return builder.ToString ();
+                       }
+
                        set { throw new NotImplementedException (); }
                }
 
-               [MonoTODO]
-               public virtual string InnerXml
+               private void AppendChildValues (XmlNode parent, StringBuilder builder)
                {
-                       get { throw new NotImplementedException (); }
+                       XmlNode node = parent.FirstChild;
+
+                       while (node != null) {
+                               if (node.NodeType == XmlNodeType.Text)
+                                       builder.Append (node.Value);
+                               AppendChildValues (node, builder);
+                               node = node.NextSibling;
+                       }
+               }
+
+               [MonoTODO("Setter.")]
+               public virtual string InnerXml {
+                       get {
+                               StringWriter sw = new StringWriter ();
+                               XmlTextWriter xtw = new XmlTextWriter (sw);
+
+                               WriteContentTo(xtw);
+
+                               return sw.GetStringBuilder().ToString();
+                       }
+
                        set { throw new NotImplementedException (); }
                }
 
-               [MonoTODO]
-               public virtual bool IsReadOnly
-               {
-                       get { throw new NotImplementedException (); }
+               public virtual bool IsReadOnly {
+                       get { return false; }
                }
 
-               [MonoTODO]
-               public virtual XmlElement this[string name]
-               {
-                       get { throw new NotImplementedException (); }
+               [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;
+                                       }
+                               }
+
+                               return null;
+                       }
                }
 
-               [MonoTODO]
-               public virtual XmlElement this[string localname, string ns]
-               {
-                       get { throw new NotImplementedException (); }
+               [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;
+                                       }
+                               }
+
+                               return null;
+                       }
                }
 
-               public virtual XmlNode LastChild
-               {
+               public virtual XmlNode LastChild {
                        get { return LastLinkedChild; }
                }
 
-               internal virtual XmlLinkedNode LastLinkedChild
-               {
+               internal virtual XmlLinkedNode LastLinkedChild {
                        get { return null; }
                        set { }
                }
 
-               [MonoTODO]
-               public abstract string LocalName
-               {
-                       get;
-               }
+               public abstract string LocalName { get; }
 
-               [MonoTODO]
-               public abstract string Name
-               {
-                       get;
-               }
+               public abstract string Name     { get; }
 
-               [MonoTODO]
-               public virtual string NamespaceURI
-               {
-                       get { throw new NotImplementedException (); }
+               public virtual string NamespaceURI {
+                       get { return String.Empty; }
                }
 
-               public virtual XmlNode NextSibling
-               {
+               public virtual XmlNode NextSibling {
                        get { return null; }
                }
 
-               [MonoTODO]
-               public abstract XmlNodeType NodeType
-               {
-                       get;
-               }
+               public abstract XmlNodeType NodeType { get;     }
 
-               [MonoTODO]
-               public virtual string OuterXml
-               {
-                       get { throw new NotImplementedException (); }
+               public virtual string OuterXml {
+                       get {
+                               StringWriter sw = new StringWriter ();
+                               XmlTextWriter xtw = new XmlTextWriter (sw);
+
+                               WriteTo(xtw);
+
+                               return sw.GetStringBuilder().ToString();
+                       }
                }
 
-               public virtual XmlDocument OwnerDocument
-               {
+               public virtual XmlDocument OwnerDocument {
                        get { return ownerDocument; }
                }
 
-               public virtual XmlNode ParentNode
-               {
+               public virtual XmlNode ParentNode {
                        get { return parentNode; }
                }
 
-               [MonoTODO]
-               public virtual string Prefix
-               {
-                       get { throw new NotImplementedException (); }
-                       set { throw new NotImplementedException (); }
+               public virtual string Prefix {
+                       get { return String.Empty; }
+                       set {}
                }
 
-               public virtual XmlNode PreviousSibling
-               {
+               public virtual XmlNode PreviousSibling {
                        get { return null; }
                }
 
-               [MonoTODO]
-               public virtual string Value
-               {
-                       get { throw new NotImplementedException (); }
-                       set { throw new NotImplementedException (); }
+               public virtual string Value {
+                       get { return null; }
+                       set { throw new InvalidOperationException ("This node does not have a value"); }
                }
 
                #endregion
@@ -176,13 +198,33 @@ namespace System.Xml
 
                public virtual XmlNode AppendChild (XmlNode newChild)
                {
-                       if ((NodeType == XmlNodeType.Document) || (NodeType == XmlNodeType.Element)) {
-                               LastLinkedChild = (XmlLinkedNode) newChild;
-                               return LastChild;
-                       }
-                       else {
+                       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();
-                       }
                }
 
                [MonoTODO]
@@ -196,13 +238,12 @@ namespace System.Xml
                [MonoTODO]
                public XPathNavigator CreateNavigator ()
                {
-                       throw new NotImplementedException ();
+                       return new XmlDocumentNavigator(this);
                }
 
-               [MonoTODO]
                public IEnumerator GetEnumerator ()
                {
-                       throw new NotImplementedException ();
+                       return new XmlNodeListChildren(this).GetEnumerator();
                }
 
                [MonoTODO]
@@ -253,13 +294,44 @@ namespace System.Xml
 
                public virtual void RemoveAll ()
                {
+                       XmlDocument ownerDoc = (NodeType == XmlNodeType.Document) ? (XmlDocument)this : OwnerDocument;
+
+                       ownerDoc.onNodeRemoving (this, this.ParentNode);
                        LastLinkedChild = null;
+                       ownerDoc.onNodeRemoved (this, this.ParentNode);
                }
 
-               [MonoTODO]
                public virtual XmlNode RemoveChild (XmlNode oldChild)
                {
-                       throw new NotImplementedException ();
+                       OwnerDocument.onNodeRemoving (oldChild, oldChild.ParentNode);
+
+                       if (NodeType == XmlNodeType.Document || NodeType == XmlNodeType.Element || NodeType == XmlNodeType.Attribute) 
+                       {
+                               if (IsReadOnly)
+                                       throw new ArgumentException();
+
+                               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 (!Object.ReferenceEquals(beforeLinkedChild.NextLinkedSibling, oldLinkedChild))
+                                               throw new ArgumentException();
+
+                                       beforeLinkedChild.NextLinkedSibling = oldLinkedChild.NextLinkedSibling;
+                                       oldLinkedChild.NextLinkedSibling = null;
+                                }
+
+                               OwnerDocument.onNodeRemoved (oldChild, oldChild.ParentNode);
+
+                               return oldChild;
+                       } 
+                       else
+                               throw new ArgumentException();
                }
 
                [MonoTODO]
@@ -268,28 +340,43 @@ namespace System.Xml
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO]
-               public virtual XmlNodeList SelectNodes (string xpath)
+               public XmlNodeList SelectNodes (string xpath)
                {
-                       throw new NotImplementedException ();
+                       return SelectNodes (xpath, null);
                }
 
                [MonoTODO]
-               public virtual XmlNodeList SelectNodes (string xpath, XmlNamespaceManager nsmgr)
+               public XmlNodeList SelectNodes (string xpath, XmlNamespaceManager nsmgr)
                {
-                       throw new NotImplementedException ();
+                       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 ())
+                       {
+                               rgNodes.Add (((XmlDocumentNavigator) iter.Current).Node);
+                       }
+                       return new XmlNodeArrayList (rgNodes);
                }
 
-               [MonoTODO]
-               public virtual XmlNode SelectSingleNode (string xpath)
+               public XmlNode SelectSingleNode (string xpath)
                {
-                       throw new NotImplementedException ();
+                       return SelectSingleNode (xpath, null);
                }
 
                [MonoTODO]
-               public virtual XmlNode SelectSingleNode (string xpath, XmlNamespaceManager nsmgr)
+               public XmlNode SelectSingleNode (string xpath, XmlNamespaceManager 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;
                }
 
                internal void SetParentNode (XmlNode parent)
@@ -303,10 +390,8 @@ namespace System.Xml
                        throw new NotImplementedException ();
                }
 
-               [MonoTODO]
                public abstract void WriteContentTo (XmlWriter w);
 
-               [MonoTODO]
                public abstract void WriteTo (XmlWriter w);
 
                #endregion