New test.
[mono.git] / mcs / class / System.XML / System.Xml / XmlDeclaration.cs
1 //
2 // System.Xml.XmlDeclaration
3 //
4 // Author:
5 //      Duncan Mak  (duncan@ximian.com)
6 //      Atsushi Enomotot  (atsushi@ximian.com)
7 //
8 // (C) Ximian, Inc.
9
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 // 
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 // 
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30
31 using System;
32 using System.Globalization;
33 using System.Text;
34 using System.Xml;
35
36 namespace System.Xml
37 {
38         public class XmlDeclaration : XmlLinkedNode
39         {
40                 string encoding = "UTF-8"; // defaults to UTF-8
41                 string standalone;
42                 string version;
43
44                 protected internal XmlDeclaration (string version, string encoding,
45                                                    string standalone, XmlDocument doc)
46                         : base (doc)
47                 {
48                         if (encoding == null)
49                                 encoding = "";
50
51                         if (standalone == null)
52                                 standalone = "";
53
54                         this.version = version;
55                         this.encoding = encoding;
56                         this.standalone = standalone;
57                 }
58
59                 public string Encoding  {
60                         get { return encoding; } 
61                         set { encoding = (value == null) ? String.Empty : value; }
62                 }
63
64                 public override string InnerText {
65                         get { return Value; }
66                         set { ParseInput (value); }
67                 }
68                 
69                 public override string LocalName {
70                         get { return "xml"; }
71                 }
72
73                 public override string Name {
74                         get { return "xml"; }
75                 }
76
77                 public override XmlNodeType NodeType {
78                         get { return XmlNodeType.XmlDeclaration; }
79                 }
80
81                 public string Standalone {
82                         get { return standalone; }
83                         set {
84                                 if(value != null)
85                                 {
86                                         if (String.Compare (value, "YES", true, CultureInfo.InvariantCulture) == 0)
87                                                 standalone = "yes";
88                                         if (String.Compare (value, "NO", true, CultureInfo.InvariantCulture) == 0)
89                                                 standalone = "no";
90                                 }
91                                 else
92                                         standalone = String.Empty;
93                         }
94                 }
95
96                 public override string Value {
97                         get {
98                                 string formatEncoding = "";
99                                 string formatStandalone = "";
100
101                                 if (encoding != String.Empty)
102                                         formatEncoding = String.Format (" encoding=\"{0}\"", encoding);
103
104                                 if (standalone != String.Empty)
105                                         formatStandalone = String.Format (" standalone=\"{0}\"", standalone);
106
107                                 return String.Format ("version=\"{0}\"{1}{2}", Version, formatEncoding, formatStandalone);
108                         }
109                         set { ParseInput (value); }
110                 }
111
112                 public string Version {
113                         get { return version; }
114                 }
115
116                 public override XmlNode CloneNode (bool deep)
117                 {
118                         return new XmlDeclaration (Version, Encoding, standalone, OwnerDocument);
119                 }
120
121                 public override void WriteContentTo (XmlWriter w) {}
122
123                 public override void WriteTo (XmlWriter w)
124                 {
125                         // This doesn't seem to match up very well with w.WriteStartDocument()
126                         // so writing out custom here.
127                         w.WriteRaw (String.Format ("<?xml {0}?>", Value));
128                 }
129
130                 private int SkipWhitespace (string input, int index)
131                 {
132                         while (index < input.Length) {
133                                 if (XmlChar.IsWhitespace (input [index]))
134                                         index++;
135                                 else
136                                         break;
137                         }
138                         return index;
139                 }
140
141                 void ParseInput (string input)
142                 {
143                         int index = SkipWhitespace (input, 0);
144                         if (index + 7 > input.Length || input.IndexOf ("version", index, 7) != index)
145                                 throw new XmlException ("Missing 'version' specification.");
146                         index = SkipWhitespace (input, index + 7);
147
148                         char c = input [index];
149                         if (c != '=')
150                                 throw new XmlException ("Invalid 'version' specification.");
151                         index++;
152                         index = SkipWhitespace (input, index);
153                         c = input [index];
154                         if (c != '"' && c != '\'')
155                                 throw new XmlException ("Invalid 'version' specification.");
156                         index++;
157                         int end = input.IndexOf (c, index);
158                         if (end < 0 || input.IndexOf ("1.0", index, 3) != index)
159                                 throw new XmlException ("Invalid 'version' specification.");
160                         index += 4;
161                         if (index == input.Length)
162                                 return;
163                         if (!XmlChar.IsWhitespace (input [index]))
164                                 throw new XmlException ("Invalid XML declaration.");
165                         index = SkipWhitespace (input, index + 1);
166                         if (index == input.Length)
167                                 return;
168
169                         if (input.Length > index + 8 && input.IndexOf ("encoding", index, 8) > 0) {
170                                 index = SkipWhitespace (input, index + 8);
171                                 c = input [index];
172                                 if (c != '=')
173                                         throw new XmlException ("Invalid 'version' specification.");
174                                 index++;
175                                 index = SkipWhitespace (input, index);
176                                 c = input [index];
177                                 if (c != '"' && c != '\'')
178                                         throw new XmlException ("Invalid 'encoding' specification.");
179                                 end = input.IndexOf (c, index + 1);
180                                 if (end < 0)
181                                         throw new XmlException ("Invalid 'encoding' specification.");
182                                 Encoding = input.Substring (index + 1, end - index - 1);
183                                 index = end + 1;
184                                 if (index == input.Length)
185                                         return;
186                                 if (!XmlChar.IsWhitespace (input [index]))
187                                         throw new XmlException ("Invalid XML declaration.");
188                                 index = SkipWhitespace (input, index + 1);
189                         }
190
191                         if (input.Length > index + 10 && input.IndexOf ("standalone", index, 10) > 0) {
192                                 index = SkipWhitespace (input, index + 10);
193                                 c = input [index];
194                                 if (c != '=')
195                                         throw new XmlException ("Invalid 'version' specification.");
196                                 index++;
197                                 index = SkipWhitespace (input, index);
198                                 c = input [index];
199                                 if (c != '"' && c != '\'')
200                                         throw new XmlException ("Invalid 'standalone' specification.");
201                                 end = input.IndexOf (c, index + 1);
202                                 if (end < 0)
203                                         throw new XmlException ("Invalid 'standalone' specification.");
204                                 string tmp = input.Substring (index + 1, end - index - 1);
205                                 switch (tmp) {
206                                 case "yes":
207                                 case "no":
208                                         break;
209                                 default:
210                                         throw new XmlException ("Invalid standalone specification.");
211                                 }
212                                 Standalone = tmp;
213                                 index = end + 1;
214                                 index = SkipWhitespace (input, index);
215                         }
216                         if (index != input.Length)
217                                 throw new XmlException ("Invalid XML declaration.");
218                 }
219         }
220 }