2003-04-27 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.Initialize (BaseURI, ctx, new System.IO.StringReader ("'" + value.Replace ("'", "&apos;") + "'"), XmlNodeType.Attribute);
90
91                                 OwnerDocument.ReadAttributeNodeValue (xtr, this);
92                         }
93                 }
94
95                 public override string LocalName {
96                         get {
97                                 return localName;
98                         }
99                 }
100
101                 public override string Name {
102                         get { 
103                                 return prefix != String.Empty ? prefix + ":" + localName : localName; 
104                         }
105                 }
106
107                 public override string NamespaceURI {
108                         get {
109                                 return namespaceURI;
110                         }
111                 }
112
113                 public override XmlNodeType NodeType {
114                         get {
115                                 return XmlNodeType.Attribute;
116                         }
117                 }
118
119                 internal override XPathNodeType XPathNodeType {
120                         get {
121                                 return XPathNodeType.Attribute;
122                         }
123                 }
124
125                 public override XmlDocument OwnerDocument {
126                         get {
127                                 return base.OwnerDocument;
128                         }
129                 }
130
131                 public virtual XmlElement OwnerElement {
132                         get {
133                                 return ownerElement;
134                         }
135                 }
136
137                 public override XmlNode ParentNode {
138                         get {
139                                 // It always returns null (by specification).
140                                 return null;
141                         }
142                 }
143
144                 [MonoTODO("setter incomplete (name character check, format check, wrong prefix&nsURI)")]
145                 // We gotta do more in the set block here
146                 // We need to do the proper tests and throw
147                 // the correct Exceptions
148                 //
149                 // Wrong cases are: (1)check readonly, (2)check character validity,
150                 // (3)check format validity, (4)this is attribute and qualifiedName != "xmlns"
151                 // (5)when argument is 'xml' or 'xmlns' and namespaceURI doesn't match
152                 public override string Prefix {
153                         set {
154                                 if(IsReadOnly)
155                                         throw new XmlException ("This node is readonly.");
156
157                                 XmlNamespaceManager nsmgr = ConstructNamespaceManager ();
158                                 string nsuri = nsmgr.LookupNamespace (value);
159                                 if(nsuri == null)
160                                         throw new XmlException ("Namespace URI not found for this prefix");
161
162                                 prefix = value;
163                         }
164                         
165                         get {
166                                 return prefix;
167                         }
168                 }
169
170                 [MonoTODO("There are no code which sets 'specified = true', so this logic is without checking.")]
171                 public virtual bool Specified {
172                         get {
173                                 return !isDefault;
174                         }
175                 }
176
177                 public override string Value {
178                         get {
179                                 XmlNode firstChild = FirstChild;
180                                 if (firstChild == null)
181                                         return String.Empty;
182                                 return firstChild.Value;
183                         }
184
185                         set {
186                                 XmlNode firstChild = FirstChild;
187                                 if (firstChild == null)
188                                         AppendChild (OwnerDocument.CreateTextNode (value));
189                                 else
190                                         firstChild.Value = value;
191                         }
192                 }
193
194                 internal override string XmlLang {
195                         get { return OwnerElement.XmlLang; }
196                 }
197
198                 internal override XmlSpace XmlSpace {
199                         get { return OwnerElement.XmlSpace; }
200                 }
201
202                 #endregion
203
204                 #region Methods
205
206                 public override XmlNode CloneNode (bool deep)
207                 {
208                         XmlNode node = new XmlAttribute (prefix, localName, namespaceURI,
209                                                          OwnerDocument);
210                         if (deep) {
211                                 while ((node != null) && (node.HasChildNodes)) {
212                                         AppendChild (node.NextSibling.CloneNode (true));
213                                         node = node.NextSibling;
214                                 }
215                         }
216
217                         return node;
218                 }
219
220                 // Parent of XmlAttribute must be null
221                 internal void SetOwnerElement (XmlElement el) {
222                         ownerElement = el;
223                 }
224
225                 public override void WriteContentTo (XmlWriter w)
226                 {
227                         foreach (XmlNode n in ChildNodes)
228                                 n.WriteTo (w);
229                 }
230
231                 public override void WriteTo (XmlWriter w)
232                 {
233                         w.WriteStartAttribute (prefix, localName, namespaceURI);
234                         WriteContentTo (w);
235                         w.WriteEndAttribute ();
236                 }
237
238                 #endregion
239
240                 internal override XmlLinkedNode LastLinkedChild {
241                         get { return lastChild; }
242
243                         set { lastChild = value; }
244                 }
245         }
246 }