59a5c752aa4603cd041fbcf18c3f72828668a836
[mono.git] / mcs / class / System.XML / System.Xml / XmlNode.cs
1 //
2 // System.Xml.XmlNode
3 //
4 // Author:
5 //   Kral Ferch <kral_ferch@hotmail.com>
6 //
7 // (C) 2002 Kral Ferch
8 //
9
10 using System;
11 using System.Collections;
12 using System.IO;
13 using System.Text;
14 using System.Xml.XPath;
15
16 namespace System.Xml
17 {
18         public abstract class XmlNode : ICloneable, IEnumerable, IXPathNavigable
19         {
20                 #region Fields
21
22                 XmlDocument ownerDocument;
23                 XmlNode parentNode;
24
25                 #endregion
26
27                 #region Constructors
28
29                 internal XmlNode (XmlDocument ownerDocument)
30                 {
31                         this.ownerDocument = ownerDocument;
32                 }
33
34                 #endregion
35
36                 #region Properties
37
38                 public virtual XmlAttributeCollection Attributes
39                 {
40                         get { return null; }
41                 }
42
43                 public virtual string BaseURI
44                 {
45                         get { return ParentNode.BaseURI; }
46                 }
47
48                 public virtual XmlNodeList ChildNodes {
49                         get {
50                                 return new XmlNodeListChildren(this);
51                         }
52                 }
53
54                 public virtual XmlNode FirstChild {
55                         get {
56                                 if (LastChild != null) {
57                                         return LastLinkedChild.NextLinkedSibling;
58                                 }
59                                 else {
60                                         return null;
61                                 }
62                         }
63                 }
64
65                 public virtual bool HasChildNodes {
66                         get { return LastChild != null; }
67                 }
68
69                 [MonoTODO]
70                 public virtual string InnerText {
71                         get {
72                                 StringBuilder builder = new StringBuilder ();
73                                 AppendChildValues (this, builder);
74                                 return builder.ToString ();
75                         }
76
77                         set { throw new NotImplementedException (); }
78                 }
79
80                 private void AppendChildValues(XmlNode parent, StringBuilder builder)
81                 {
82                         XmlNode node = parent.FirstChild;
83
84                         while (node != null) {
85                                 builder.Append (node.Value);
86                                 AppendChildValues (node, builder);
87                                 node = node.NextSibling;
88                         }
89                 }
90
91                 [MonoTODO("Setter.")]
92                 public virtual string InnerXml {
93                         get {
94                                 StringWriter sw = new StringWriter ();
95                                 XmlTextWriter xtw = new XmlTextWriter (sw);
96
97                                 WriteContentTo(xtw);
98
99                                 return sw.GetStringBuilder().ToString();
100                         }
101
102                         set { throw new NotImplementedException (); }
103                 }
104
105                 public virtual bool IsReadOnly {
106                         get { return false; }
107                 }
108
109                 [System.Runtime.CompilerServices.IndexerName("Item")]
110                 public virtual XmlElement this [string name] {
111                         get { 
112                                 foreach (XmlNode node in ChildNodes) {
113                                         if ((node.NodeType == XmlNodeType.Element) &&
114                                             (node.Name == name)) {
115                                                 return (XmlElement) node;
116                                         }
117                                 }
118
119                                 return null;
120                         }
121                 }
122
123                 [System.Runtime.CompilerServices.IndexerName("Item")]
124                 public virtual XmlElement this [string localname, string ns] {
125                         get { 
126                                 foreach (XmlNode node in ChildNodes) {
127                                         if ((node.NodeType == XmlNodeType.Element) &&
128                                             (node.LocalName == localname) && 
129                                             (node.NamespaceURI == ns)) {
130                                                 return (XmlElement) node;
131                                         }
132                                 }
133
134                                 return null;
135                         }
136                 }
137
138                 public virtual XmlNode LastChild {
139                         get { return LastLinkedChild; }
140                 }
141
142                 internal virtual XmlLinkedNode LastLinkedChild {
143                         get { return null; }
144                         set { }
145                 }
146
147                 public abstract string LocalName { get; }
148
149                 public abstract string Name     { get; }
150
151                 public virtual string NamespaceURI {
152                         get { return String.Empty; }
153                 }
154
155                 public virtual XmlNode NextSibling {
156                         get { return null; }
157                 }
158
159                 public abstract XmlNodeType NodeType { get;     }
160
161                 public virtual string OuterXml {
162                         get {
163                                 StringWriter sw = new StringWriter ();
164                                 XmlTextWriter xtw = new XmlTextWriter (sw);
165
166                                 WriteTo(xtw);
167
168                                 return sw.GetStringBuilder().ToString();
169                         }
170                 }
171
172                 public virtual XmlDocument OwnerDocument {
173                         get { return ownerDocument; }
174                 }
175
176                 public virtual XmlNode ParentNode {
177                         get { return parentNode; }
178                 }
179
180                 public virtual string Prefix {
181                         get { return String.Empty; }
182                         set {}
183                 }
184
185                 public virtual XmlNode PreviousSibling {
186                         get { return null; }
187                 }
188
189                 public virtual string Value {
190                         get { return null; }
191                         set { throw new InvalidOperationException ("This node does not have a value"); }
192                 }
193
194                 #endregion
195
196                 #region Methods
197
198                 public virtual XmlNode AppendChild (XmlNode newChild)
199                 {
200                         if (NodeType == XmlNodeType.Document
201                             || NodeType == XmlNodeType.Element
202                             || NodeType == XmlNodeType.Attribute) {
203                                 XmlLinkedNode newLinkedChild = (XmlLinkedNode) newChild;
204                                 XmlLinkedNode lastLinkedChild = LastLinkedChild;
205
206                                 newLinkedChild.parentNode = this;
207                                 
208                                 if (lastLinkedChild != null) {
209                                         newLinkedChild.NextLinkedSibling = lastLinkedChild.NextLinkedSibling;
210                                         lastLinkedChild.NextLinkedSibling = newLinkedChild;
211                                 } else
212                                         newLinkedChild.NextLinkedSibling = newLinkedChild;
213                                 
214                                 LastLinkedChild = newLinkedChild;
215
216                                 return newChild;
217                         } else
218                                 throw new InvalidOperationException();
219                 }
220
221                 [MonoTODO]
222                 public virtual XmlNode Clone ()
223                 {
224                         throw new NotImplementedException ();
225                 }
226
227                 public abstract XmlNode CloneNode (bool deep);
228
229                 [MonoTODO]
230                 public virtual XPathNavigator CreateNavigator ()
231                 {
232                         return new XmlDocumentNavigator(this);
233                 }
234
235                 public IEnumerator GetEnumerator ()
236                 {
237                         return new XmlNodeListChildren(this).GetEnumerator();
238                 }
239
240                 [MonoTODO]
241                 public virtual string GetNamespaceOfPrefix (string prefix)
242                 {
243                         throw new NotImplementedException ();
244                 }
245
246                 [MonoTODO]
247                 public virtual string GetPrefixOfNamespace (string namespaceURI)
248                 {
249                         throw new NotImplementedException ();
250                 }
251
252                 object ICloneable.Clone ()
253                 {
254                         return Clone ();
255                 }
256
257                 IEnumerator IEnumerable.GetEnumerator ()
258                 {
259                         return GetEnumerator ();
260                 }
261
262                 [MonoTODO]
263                 public virtual XmlNode InsertAfter (XmlNode newChild, XmlNode refChild)
264                 {
265                         throw new NotImplementedException ();
266                 }
267
268                 [MonoTODO]
269                 public virtual XmlNode InsertBefore (XmlNode newChild, XmlNode refChild)
270                 {
271                         throw new NotImplementedException ();
272                 }
273
274                 [MonoTODO]
275                 public virtual void Normalize ()
276                 {
277                         throw new NotImplementedException ();
278                 }
279
280                 [MonoTODO]
281                 public virtual XmlNode PrependChild (XmlNode newChild)
282                 {
283                         throw new NotImplementedException ();
284                 }
285
286                 public virtual void RemoveAll ()
287                 {
288                         LastLinkedChild = null;
289                 }
290
291                 public virtual XmlNode RemoveChild (XmlNode oldChild)
292                 {
293                         if (NodeType == XmlNodeType.Document || NodeType == XmlNodeType.Element || NodeType == XmlNodeType.Attribute) 
294                         {
295                                 if (IsReadOnly)
296                                         throw new ArgumentException();
297
298                                 if (Object.ReferenceEquals(LastLinkedChild, LastLinkedChild.NextLinkedSibling) && Object.ReferenceEquals(LastLinkedChild, oldChild))
299                                         LastLinkedChild = null;
300                                 else {
301                                         XmlLinkedNode oldLinkedChild = (XmlLinkedNode)oldChild;
302                                         XmlLinkedNode beforeLinkedChild = LastLinkedChild;
303                                         
304                                         while (!Object.ReferenceEquals(beforeLinkedChild.NextLinkedSibling, LastLinkedChild) && !Object.ReferenceEquals(beforeLinkedChild.NextLinkedSibling, oldLinkedChild))
305                                                 beforeLinkedChild = beforeLinkedChild.NextLinkedSibling;
306
307                                         if (!Object.ReferenceEquals(beforeLinkedChild.NextLinkedSibling, oldLinkedChild))
308                                                 throw new ArgumentException();
309
310                                         beforeLinkedChild.NextLinkedSibling = oldLinkedChild.NextLinkedSibling;
311                                         oldLinkedChild.NextLinkedSibling = null;
312                                  }
313
314                                 return oldChild;
315                         } 
316                         else
317                                 throw new ArgumentException();
318                 }
319
320                 [MonoTODO]
321                 public virtual XmlNode ReplaceChild (XmlNode newChild, XmlNode oldChild)
322                 {
323                         throw new NotImplementedException ();
324                 }
325
326                 public XmlNodeList SelectNodes (string xpath)
327                 {
328                         return SelectNodes (xpath, null);
329                 }
330
331                 [MonoTODO]
332                 public XmlNodeList SelectNodes (string xpath, XmlNamespaceManager nsmgr)
333                 {
334                         XPathNavigator nav = CreateNavigator ();
335                         XPathExpression expr = nav.Compile (xpath);
336                         if (nsmgr != null)
337                                 expr.SetContext (nsmgr);
338                         XPathNodeIterator iter = nav.Select (expr);
339                         ArrayList rgNodes = new ArrayList ();
340                         while (iter.MoveNext ())
341                         {
342                                 rgNodes.Add (((XmlDocumentNavigator) iter.Current).Node);
343                         }
344                         return new XmlNodeArrayList (rgNodes);
345                 }
346
347                 public XmlNode SelectSingleNode (string xpath)
348                 {
349                         return SelectSingleNode (xpath, null);
350                 }
351
352                 [MonoTODO]
353                 public XmlNode SelectSingleNode (string xpath, XmlNamespaceManager nsmgr)
354                 {
355                         XPathNavigator nav = CreateNavigator ();
356                         XPathExpression expr = nav.Compile (xpath);
357                         if (nsmgr != null)
358                                 expr.SetContext (nsmgr);
359                         XPathNodeIterator iter = nav.Select (expr);
360                         if (!iter.MoveNext ())
361                                 return null;
362                         return ((XmlDocumentNavigator) iter.Current).Node;
363                 }
364
365                 internal void SetParentNode (XmlNode parent)
366                 {
367                         parentNode = parent;
368                 }
369
370                 [MonoTODO]
371                 public virtual bool Supports (string feature, string version)
372                 {
373                         throw new NotImplementedException ();
374                 }
375
376                 public abstract void WriteContentTo (XmlWriter w);
377
378                 public abstract void WriteTo (XmlWriter w);
379
380                 #endregion
381         }
382 }