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