2002-12-21 Atsushi Enomoto <ginga@kit.hi-ho.ne.jp>
[mono.git] / mcs / class / System.XML / System.Xml / XmlElement.cs
1 //
2 // System.Xml.XmlElement
3 //
4 // Author:
5 //   Jason Diamond (jason@injektilo.org)
6 //   Atsushi Enomoto (ginga@kit.hi-ho.ne.jp)
7 //
8 // (C) 2002 Jason Diamond  http://injektilo.org/
9 // (C) 2002 Atsushi Enomoto
10 //
11
12 using System;
13 using System.Collections;
14 using System.Xml.XPath;
15 using System.IO;
16 using System.Text;
17
18 namespace System.Xml
19 {
20         public class XmlElement : XmlLinkedNode
21         {
22                 #region Fields
23
24                 private XmlAttributeCollection attributes;
25                 private string localName;
26                 private string namespaceURI;
27                 private string prefix;
28                 private bool isEmpty;
29
30                 #endregion
31
32                 #region Constructor
33
34                 protected internal XmlElement (
35                         string prefix, 
36                         string localName, 
37                         string namespaceURI, 
38                         XmlDocument doc) : base (doc)
39                 {
40                         this.prefix = prefix;
41                         this.localName = localName;
42                         this.namespaceURI = namespaceURI;
43
44                         attributes = new XmlAttributeCollection (this);
45
46                         // TODO: Adds default attributes
47                         if(doc.DocumentType != null)
48                         {
49                         }
50                 }
51
52                 #endregion
53
54                 #region Properties
55
56                 public override XmlAttributeCollection Attributes {
57                         get { return attributes; }
58                 }
59
60                 public virtual bool HasAttributes {
61                         get { return attributes.Count > 0; }
62                 }
63
64                 public override string InnerText {
65                         get {
66                                 return base.InnerText;
67                         }
68                         set {
69                                 foreach(XmlNode n in ChildNodes)
70                                 {
71                                         this.RemoveChild(n);
72                                 }
73                                 // creates new Text node
74                                 AppendChild(OwnerDocument.CreateTextNode(value));
75                         }
76                 }
77
78                 [MonoTODO ("Setter is immature")]
79                 public override string InnerXml {
80                         get {
81                                 // Not sure why this is an override.  Passing through for now.
82                                 return base.InnerXml;
83                         }
84                         set {
85                                 foreach(XmlNode n in ChildNodes)
86                                 {
87                                         this.RemoveChild(n);
88                                 }                 
89
90                                 // I hope there are any well-performance logic...
91                                 XmlNameTable nt = this.OwnerDocument.NameTable;
92                                 XmlNamespaceManager nsmgr = this.ConstructNamespaceManager ();
93                                 XmlParserContext ctx = new XmlParserContext (nt, nsmgr, XmlLang, this.XmlSpace);
94                                 XmlTextReader xmlReader = OwnerDocument.ReusableReader;
95                                 xmlReader.SetReaderContext (String.Empty, ctx);
96                                 xmlReader.SetReaderFragment (new StringReader (value), XmlNodeType.Element);
97                                 this.ConstructDOM (xmlReader, this);
98                         }
99                 }
100
101                 public bool IsEmpty {
102                         get { return isEmpty; }
103
104                         set {
105                                 if(value) {
106                                         RemoveAll();
107                                 }
108                                 isEmpty = value;
109                         }
110                 }
111
112                 public override string LocalName {
113                         get { return localName; }
114                 }
115
116                 public override string Name {
117                         get { 
118                                 return prefix != String.Empty ? prefix + ":" + localName : localName; 
119                         }
120                 }
121
122                 public override string NamespaceURI {
123                         get { return namespaceURI; }
124                 }
125
126                 [MonoTODO]
127                 public override XmlNode NextSibling {
128                         get { 
129                                 return base.NextSibling; 
130                         }
131                 }
132
133                 public override XmlNodeType NodeType {
134                         get { 
135                                 return XmlNodeType.Element; 
136                         }
137                 }
138
139                 internal override XPathNodeType XPathNodeType {
140                         get {
141                                 return XPathNodeType.Element;
142                         }
143                 }
144
145                 [MonoTODO]
146                 public override XmlDocument OwnerDocument {
147                         get { 
148                                 return base.OwnerDocument; 
149                         }
150                 }
151
152                 public override string Prefix {
153                         get { return prefix; }
154                         set { prefix = value; }
155                 }
156
157                 #endregion
158
159                 #region Methods
160                 
161                 [MonoTODO]
162                 public override XmlNode CloneNode (bool deep)
163                 {
164                         XmlNode node =  new XmlElement (prefix, localName, namespaceURI,
165                                                         OwnerDocument);
166
167                         for (int i = 0; i < node.Attributes.Count; i++)
168                                 node.AppendChild (node.Attributes [i].CloneNode (false));
169                         
170                         if (deep) {
171                                 while ((node != null) && (node.HasChildNodes)) {                                        
172                                         AppendChild (node.NextSibling.CloneNode (true));
173                                         node = node.NextSibling;
174                                 }
175                         } // shallow cloning
176                                 
177                         //
178                         // Reminder: Also look into Default attributes.
179                         //
180                         return node;
181                 }
182
183                 [MonoTODO]
184                 public virtual string GetAttribute (string name)
185                 {
186                         XmlNode attributeNode = Attributes.GetNamedItem (name);
187                         return attributeNode != null ? attributeNode.Value : String.Empty;
188                 }
189
190                 [MonoTODO]
191                 public virtual string GetAttribute (string localName, string namespaceURI)
192                 {
193                         XmlNode attributeNode = Attributes.GetNamedItem (localName, namespaceURI);
194                         return attributeNode != null ? attributeNode.Value : String.Empty;
195                 }
196
197                 [MonoTODO]
198                 public virtual XmlAttribute GetAttributeNode (string name)
199                 {
200                         XmlNode attributeNode = Attributes.GetNamedItem (name);
201                         return attributeNode != null ? attributeNode as XmlAttribute : null;
202                 }
203
204                 [MonoTODO]
205                 public virtual XmlAttribute GetAttributeNode (string localName, string namespaceURI)
206                 {
207                         XmlNode attributeNode = Attributes.GetNamedItem (localName, namespaceURI);
208                         return attributeNode != null ? attributeNode as XmlAttribute : null;
209                 }
210
211                 public virtual XmlNodeList GetElementsByTagName (string name)
212                 {
213                         ArrayList nodeArrayList = new ArrayList ();
214                         this.searchNodesRecursively (this, name, nodeArrayList);
215                         return new XmlNodeArrayList (nodeArrayList);
216                 }
217
218                 private void searchNodesRecursively (XmlNode argNode, string argName, 
219                         ArrayList argArrayList)
220                 {
221                         XmlNodeList xmlNodeList = argNode.ChildNodes;
222                         foreach (XmlNode node in xmlNodeList){
223                                 if (node.Name.Equals (argName))
224                                         argArrayList.Add (node);
225                                 else    
226                                         this.searchNodesRecursively (node, argName, argArrayList);
227                         }
228                 }
229
230                 private void searchNodesRecursively (XmlNode argNode, string argName, string argNamespaceURI, 
231                         ArrayList argArrayList)
232                 {
233                         XmlNodeList xmlNodeList = argNode.ChildNodes;
234                         foreach (XmlNode node in xmlNodeList)
235                         {
236                                 if (node.LocalName.Equals (argName) && node.NamespaceURI.Equals (argNamespaceURI))
237                                         argArrayList.Add (node);
238                                 else    
239                                         this.searchNodesRecursively (node, argName, argNamespaceURI, argArrayList);
240                         }
241                 }
242
243                 public virtual XmlNodeList GetElementsByTagName (string localName, string namespaceURI)
244                 {
245                         ArrayList nodeArrayList = new ArrayList ();
246                         this.searchNodesRecursively (this, localName, namespaceURI, nodeArrayList);
247                         return new XmlNodeArrayList (nodeArrayList);
248                 }
249
250                 [MonoTODO]
251                 public virtual bool HasAttribute (string name)
252                 {
253                         XmlNode attributeNode = Attributes.GetNamedItem (name);
254                         return attributeNode != null;
255                 }
256
257                 [MonoTODO]
258                 public virtual bool HasAttribute (string localName, string namespaceURI)
259                 {
260                         XmlNode attributeNode = Attributes.GetNamedItem (localName, namespaceURI);
261                         return attributeNode != null;
262                 }
263
264                 [MonoTODO ("confirm not removing default attributes [when DTD feature was implemented.")]
265                 public override void RemoveAll ()
266                 {
267                         // Remove the child nodes.
268                         base.RemoveAll ();
269
270                         // Remove all attributes.
271                         attributes.RemoveAll ();
272                 }
273
274                 [MonoTODO ("confirm not removing default attributes [when DTD feature was implemented.")]
275                 public virtual void RemoveAllAttributes ()
276                 {
277                         attributes.RemoveAll ();
278                 }
279
280                 [MonoTODO ("confirm not resetting default attributes [when DTD feature was implemented.")]
281                 public virtual void RemoveAttribute (string name)
282                 {
283                         attributes.Remove((XmlAttribute)attributes.GetNamedItem(name));
284                 }
285
286                 [MonoTODO ("confirm not resetting default attributes [when DTD feature was implemented.")]
287                 public virtual void RemoveAttribute (string localName, string namespaceURI)
288                 {
289                         attributes.Remove((XmlAttribute)attributes.GetNamedItem(localName, namespaceURI));
290                 }
291
292                 [MonoTODO ("confirm not resetting default attributes [when DTD feature was implemented.")]
293                 public virtual XmlNode RemoveAttributeAt (int i)
294                 {
295                         return attributes.Remove(attributes[i]);
296                 }
297
298                 [MonoTODO ("confirm not resetting default attributes [when DTD feature was implemented.")]
299                 public virtual XmlAttribute RemoveAttributeNode (XmlAttribute oldAttr)
300                 {
301                         return attributes.Remove(oldAttr);
302                 }
303
304                 [MonoTODO ("confirm not resetting default attributes [when DTD feature was implemented.")]
305                 public virtual XmlAttribute RemoveAttributeNode (string localName, string namespaceURI)
306                 {
307                         return attributes.Remove(attributes[localName, namespaceURI]);
308                 }
309
310                 [MonoTODO]
311                 public virtual void SetAttribute (string name, string value)
312                 {
313                         XmlAttribute attribute = OwnerDocument.CreateAttribute (name);
314                         attribute.SetOwnerElement(this);
315                         attribute.Value = value;
316                         Attributes.SetNamedItem (attribute);
317                 }
318
319 //              [MonoTODO]
320                 public virtual string SetAttribute (string localName, string namespaceURI, string value)
321                 {
322                         XmlAttribute attr = attributes[localName, namespaceURI];
323                         if(attr == null)
324                         {
325                                 attr = OwnerDocument.CreateAttribute(localName, namespaceURI);
326                                 attr.Value = value;
327                                 attributes.SetNamedItem(attr);
328                         }
329                         else
330                                 attr.Value = value;
331                         return attr.Value;
332                 }
333
334 //              [MonoTODO]
335                 public virtual XmlAttribute SetAttributeNode (XmlAttribute newAttr)
336                 {
337                         newAttr.SetOwnerElement(this);
338                         XmlNode oldAttr = Attributes.SetNamedItem(newAttr);
339                         return oldAttr != null ? oldAttr as XmlAttribute : null;
340                 }
341
342                 public virtual XmlAttribute SetAttributeNode (string localName, string namespaceURI)
343                 {
344                         XmlDocument xmlDoc = this.OwnerDocument;
345                         XmlAttribute xmlAttribute = new XmlAttribute (String.Empty, localName, namespaceURI, xmlDoc);
346                         return this.attributes.Append (xmlAttribute);
347                 }
348
349                 public override void WriteContentTo (XmlWriter w)
350                 {
351                         foreach(XmlNode childNode in ChildNodes)
352                                 childNode.WriteTo(w);
353                 }
354
355                 [MonoTODO("indenting feature is incomplete.")]
356                 public override void WriteTo (XmlWriter w)
357                 {
358                         w.WriteStartElement(Prefix, LocalName, NamespaceURI);
359
360                         // write namespace declarations(if not exist)
361                         if(Prefix != null && Prefix != String.Empty && w.LookupPrefix(Prefix) != NamespaceURI)
362                                 w.WriteAttributeString("xmlns", Prefix, "http://www.w3.org/2000/xmlns/", NamespaceURI);
363
364                         foreach(XmlNode attributeNode in Attributes)
365                         {
366                                 attributeNode.WriteTo(w);
367                                 // write namespace declarations(if not exist)
368                                 if(attributeNode.Prefix != null && attributeNode.Prefix != String.Empty &&
369                                    w.LookupPrefix(attributeNode.Prefix) != attributeNode.NamespaceURI &&
370                                    attributeNode.Prefix != "xmlns")
371                                         w.WriteAttributeString("xmlns", attributeNode.Prefix, "http://www.w3.org/2000/xmlns/", attributeNode.NamespaceURI);
372                         }
373
374                         WriteContentTo(w);
375
376                         w.WriteEndElement();
377                 }
378
379                 #endregion
380         }
381 }