2002-12-24 Atsushi Enomoto <ginga@kit.hi-ho.ne.jp>
[mono.git] / mcs / class / System.XML / System.Xml / XmlAttribute.cs
1 //
2 // System.Xml.XmlAttribute
3 //
4 // Author:
5 //   Jason Diamond (jason@injektilo.org)
6 //
7 // (C) 2002 Jason Diamond  http://injektilo.org/
8 //
9
10 using System;
11 using System.Text;
12 using System.Xml.XPath;
13
14 namespace System.Xml
15 {
16         public class XmlAttribute : XmlNode
17         {
18                 #region Fields
19
20                 private XmlLinkedNode lastChild;
21                 private string localName;
22                 private string namespaceURI;
23                 private string prefix;
24                 internal bool isDefault;
25                 private XmlElement ownerElement;
26
27                 #endregion
28
29                 #region Constructor
30
31                 [MonoTODO("need to set namespaceURI if prefix is recognized built-in ones like xmlns")]
32                 protected internal XmlAttribute (
33                         string prefix, 
34                         string localName, 
35                         string namespaceURI, 
36                         XmlDocument doc) : base (doc)
37                 {
38                         // What to be recognized is: xml:space, xml:lang, xml:base, and
39                         // xmlns and xmlns:* (when XmlDocument.Namespaces = true only)
40                         this.prefix = prefix;
41                         this.localName = localName;
42                         this.namespaceURI = namespaceURI;
43                 }
44
45                 #endregion
46
47                 #region Properties
48
49                 public override string BaseURI {
50                         get {
51                                 return OwnerElement.BaseURI;
52                         }
53                 }
54
55                 public override string InnerText {
56                         get {
57                                 StringBuilder builder = new StringBuilder ();
58                                 AppendChildValues (this, builder);
59                                 return builder.ToString ();
60                         }
61
62                         set {
63                                 Value = value;
64                         }
65                 }
66
67                 private void AppendChildValues (XmlNode parent, StringBuilder builder)
68                 {
69                         XmlNode node = parent.FirstChild;
70                         
71                         while (node != null) {
72                                 builder.Append (node.Value);
73                                 AppendChildValues (node, builder);
74                                 node = node.NextSibling;
75                         }
76                 }
77                 
78                 [MonoTODO ("Setter is incomplete(XmlTextReader.ReadAttribute is incomplete;No resolution for xml:lang/space")]
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
85                         set {
86                                 XmlNamespaceManager nsmgr = ConstructNamespaceManager ();
87                                 XmlParserContext ctx = new XmlParserContext (OwnerDocument.NameTable, nsmgr, XmlLang, this.XmlSpace);
88                                 XmlTextReader xtr = OwnerDocument.ReusableReader;
89                                 xtr.SetReaderContext (BaseURI, ctx);
90                                 xtr.SetReaderFragment (new System.IO.StringReader ("'" + value.Replace ("'", "&apos;") + "'"), XmlNodeType.Attribute);
91
92                                 OwnerDocument.ReadAttributeNodeValue (xtr, this);
93                         }
94                 }
95
96                 public override string LocalName {
97                         get {
98                                 return localName;
99                         }
100                 }
101
102                 public override string Name {
103                         get { 
104                                 return prefix != String.Empty ? prefix + ":" + localName : localName; 
105                         }
106                 }
107
108                 public override string NamespaceURI {
109                         get {
110                                 return namespaceURI;
111                         }
112                 }
113
114                 public override XmlNodeType NodeType {
115                         get {
116                                 return XmlNodeType.Attribute;
117                         }
118                 }
119
120                 internal override XPathNodeType XPathNodeType {
121                         get {
122                                 return XPathNodeType.Attribute;
123                         }
124                 }
125
126                 public override XmlDocument OwnerDocument {
127                         get {
128                                 return base.OwnerDocument;
129                         }
130                 }
131
132                 public virtual XmlElement OwnerElement {
133                         get {
134                                 return ownerElement;
135                         }
136                 }
137
138                 public override XmlNode ParentNode {
139                         get {
140                                 // It always returns null (by specification).
141                                 return null;
142                         }
143                 }
144
145                 [MonoTODO("setter incomplete (name character check, format check, wrong prefix&nsURI)")]
146                 // We gotta do more in the set block here
147                 // We need to do the proper tests and throw
148                 // the correct Exceptions
149                 //
150                 // Wrong cases are: (1)check readonly, (2)check character validity,
151                 // (3)check format validity, (4)this is attribute and qualifiedName != "xmlns"
152                 // (5)when argument is 'xml' or 'xmlns' and namespaceURI doesn't match
153                 public override string Prefix {
154                         set {
155                                 if(IsReadOnly)
156                                         throw new XmlException ("This node is readonly.");
157
158                                 XmlNamespaceManager nsmgr = ConstructNamespaceManager ();
159                                 string nsuri = nsmgr.LookupNamespace (value);
160                                 if(nsuri == null)
161                                         throw new XmlException ("Namespace URI not found for this prefix");
162
163                                 prefix = value;
164                         }
165                         
166                         get {
167                                 return prefix;
168                         }
169                 }
170
171                 [MonoTODO("There are no code which sets 'specified = true', so this logic is without checking.")]
172                 public virtual bool Specified {
173                         get {
174                                 return !isDefault;
175                         }
176                 }
177
178                 public override string Value {
179                         get {
180                                 XmlNode firstChild = FirstChild;
181                                 if (firstChild == null)
182                                         return String.Empty;
183                                 return firstChild.Value;
184                         }
185
186                         set {
187                                 XmlNode firstChild = FirstChild;
188                                 if (firstChild == null)
189                                         AppendChild (OwnerDocument.CreateTextNode (value));
190                                 else
191                                         firstChild.Value = value;
192                         }
193                 }
194
195                 internal override string XmlLang {
196                         get { return OwnerElement.XmlLang; }
197                 }
198
199                 internal override XmlSpace XmlSpace {
200                         get { return OwnerElement.XmlSpace; }
201                 }
202
203                 #endregion
204
205                 #region Methods
206
207                 public override XmlNode CloneNode (bool deep)
208                 {
209                         XmlNode node = new XmlAttribute (prefix, localName, namespaceURI,
210                                                          OwnerDocument);
211                         if (deep) {
212                                 while ((node != null) && (node.HasChildNodes)) {
213                                         AppendChild (node.NextSibling.CloneNode (true));
214                                         node = node.NextSibling;
215                                 }
216                         }
217
218                         return node;
219                 }
220
221                 // Parent of XmlAttribute must be null
222                 internal void SetOwnerElement (XmlElement el) {
223                         ownerElement = el;
224                 }
225
226                 public override void WriteContentTo (XmlWriter w)
227                 {
228                         w.WriteString (Value);
229                 }
230
231                 public override void WriteTo (XmlWriter w)
232                 {
233                         w.WriteAttributeString (prefix, localName, namespaceURI, Value);
234                 }
235
236                 #endregion
237
238                 internal override XmlLinkedNode LastLinkedChild {
239                         get { return lastChild; }
240
241                         set { lastChild = value; }
242                 }
243         }
244 }